Setting中格式化SD卡

今天分析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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值