Setting中格式化SD卡

来源:互联网 发布:网络运行维护培训课程 编辑:程序博客网 时间:2024/05/01 12:29

今天分析setting中直接格式化的流程,直接上代码:

Setting中的MediaFormat.java中的mFinalClickListener 这个回调,就是调用Format的地方:其是其了一个Service。

    private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {            public void onClick(View v) {                if (Utils.isMonkeyRunning()) {                    return;                }                Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY);                intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);                // Transfer the storage volume to the new intent                final StorageVolume storageVolume = getIntent().getParcelableExtra(                        StorageVolume.EXTRA_STORAGE_VOLUME);                intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, storageVolume);                startService(intent);                finish();            }        };

ExternalStorageFormatter.java就是这个Service,Service刚建立调用onCreate函数,起来在MountService中注册了回调,然后持一个睡眠锁。

    StorageEventListener mStorageListener = new StorageEventListener() {//放在MountService中的回调        @Override        public void onStorageStateChanged(String path, String oldState, String newState) {            Log.i(TAG, "Received storage state changed notification that " +                    path + " changed state from " + oldState +                    " to " + newState);            updateProgressState();//updateProgressState(主要的函数)        }    };    @Override    public void onCreate() {        super.onCreate();        if (mStorageManager == null) {            mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);            mStorageManager.registerListener(mStorageListener);        }        mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE))                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExternalStorageFormatter");        mWakeLock.acquire();    }

调用了onCreate之后,会调用onStartCommand函数

    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        if (FORMAT_AND_FACTORY_RESET.equals(intent.getAction())) {            mFactoryReset = true;        }        if (intent.getBooleanExtra(EXTRA_ALWAYS_RESET, false)) {            mAlwaysReset = true;        }        mReason = intent.getStringExtra(Intent.EXTRA_REASON);        mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);//获取StorageVolume        if (mProgressDialog == null) {//第一次调用的时候,新建一个Dialog            mProgressDialog = new ProgressDialog(this);            mProgressDialog.setIndeterminate(true);            mProgressDialog.setCancelable(true);            mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);            if (!mAlwaysReset) {                mProgressDialog.setOnCancelListener(this);            }            updateProgressState();//第一次调用updateProgressState            mProgressDialog.show();        }        return Service.START_REDELIVER_INTENT;    }

下面我们就来分析下主要的函数,第一次会将其卸载,然后MountService会将其Volume的状态改变,并且通知回调函数来调用updateProgressState函数。第二次过来已经是unmounted了,这时候将其格式化,最后再挂载sd卡。

 void updateProgressState() {        String status = mStorageVolume == null ?                Environment.getExternalStorageState() :                mStorageManager.getVolumeState(mStorageVolume.getPath());        if (Environment.MEDIA_MOUNTED.equals(status)//第一次调用的时候,发现Volume是mounted,就将它卸载                || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) {            updateProgressDialog(R.string.progress_unmounting);            IMountService mountService = getMountService();            final String extStoragePath = mStorageVolume == null ?                    Environment.getLegacyExternalStorageDirectory().toString() :                    mStorageVolume.getPath();            try {                // Remove encryption mapping if this is an unmount for a factory reset.                mountService.unmountVolume(extStoragePath, true, mFactoryReset);            } catch (RemoteException e) {                Log.w(TAG, "Failed talking with mount service", e);            }        } else if (Environment.MEDIA_NOFS.equals(status)                || Environment.MEDIA_UNMOUNTED.equals(status)                || Environment.MEDIA_UNMOUNTABLE.equals(status)) {//当第二次回调过来,应该是已经卸载了,这时候再去格式化;由于format耗时其了一个thread            updateProgressDialog(R.string.progress_erasing);            final IMountService mountService = getMountService();            final String extStoragePath = mStorageVolume == null ?                    Environment.getLegacyExternalStorageDirectory().toString() :                    mStorageVolume.getPath();            if (mountService != null) {                new Thread() {                    @Override                    public void run() {                        boolean success = false;                        try {                            mountService.formatVolume(extStoragePath);                            success = true;                        } catch (Exception e) {                            Toast.makeText(ExternalStorageFormatter.this,                                    R.string.format_error, Toast.LENGTH_LONG).show();                        }                        if (success) {                            if (mFactoryReset) {                                Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);                                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);                                intent.putExtra(Intent.EXTRA_REASON, mReason);                                sendBroadcast(intent);                                // Intent handling is asynchronous -- assume it will happen soon.                                stopSelf();                                return;                            }                        }                        // If we didn't succeed, or aren't doing a full factory                        // reset, then it is time to remount the storage.                        if (!success && mAlwaysReset) {                            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);                            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);                            intent.putExtra(Intent.EXTRA_REASON, mReason);                            sendBroadcast(intent);                        } else {//格式化完后再挂载SD卡                            try {                                mountService.mountVolume(extStoragePath);                            } catch (RemoteException e) {                                Log.w(TAG, "Failed talking with mount service", e);                            }                        }                        stopSelf();//最后将Service暂停了                        return;                    }                }.start();            } else {                Log.w(TAG, "Unable to locate IMountService");            }        } else if (Environment.MEDIA_BAD_REMOVAL.equals(status)) {            fail(R.string.media_bad_removal);        } else if (Environment.MEDIA_CHECKING.equals(status)) {            fail(R.string.media_checking);        } else if (Environment.MEDIA_REMOVED.equals(status)) {            fail(R.string.media_removed);        } else if (Environment.MEDIA_SHARED.equals(status)) {            fail(R.string.media_shared);        } else {//如果发过来的状态不对,直接停止Service            fail(R.string.media_unknown_state);            Log.w(TAG, "Unknown storage state: " + status);            stopSelf();        }    }
调完Format,紧接着就调mount,会不会有问题。因为这几个函数都是阻塞的,一定要等vold执行完,才结束,所以连续调也不会有问题,但是一定要起线程。



1 0
原创粉丝点击