Android6.0 MountService和vold详解(一)Mountservice的初始化

Android6.0对存储这块的改动还是比较大的,前面我们讲过了Android5.1上相关的代码,这里我们主要讲下区别,至于相同的部分,比如通信部分就不讲了,大家感兴趣可以看我之前5.1MountService和vold相关的博客。


一、MountService实例化

我们先从MountService的实例化开始:

mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);//这个是MountService的lifecycle静态类

在SystemServer中调用了上面函数,

    public <T extends SystemService> T startService(Class<T> serviceClass) {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);

        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);//实例化
        } catch (InstantiationException ex) {
         ...........

        // Register it.
        mServices.add(service);//放入自己列表

        // Start it.
        try {
            service.onStart();//调用onStart方法
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + name
                    + ": onStart threw an exception", ex);
        }
        return service;
    }

在SystemServiceManager的

startService函数中我们看到,是将Service实例化,然后放入自己维护的一个列表,最后调用了Service的onstart函数。

    public static class Lifecycle extends SystemService {
        private MountService mMountService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mMountService = new MountService(getContext());
            publishBinderService("mount", mMountService);
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mMountService.systemReady();
            }
        }

        @Override
        public void onStartUser(int userHandle) {
            mMountService.onStartUser(userHandle);
        }

        @Override
        public void onCleanupUser(int userHandle) {
            mMountService.onCleanupUser(userHandle);
        }
    }

在静态类Lifecycle 中的onStart函数,实例化了MountService,以及调用publishBinderService函数,把它放入ServiceManager中。

下面我们先看看MountService的构造函数:几乎和之前一样,我们说下区别的地方

 public MountService(Context context) {
        sSelf = this;

        mContext = context;
        mCallbacks = new Callbacks(FgThread.get().getLooper());//回调,后面详细说

        // XXX: This will go away soon in favor of IMountServiceObserver
        mPms = (PackageManagerService) ServiceManager.getService("package");

        HandlerThread hthread = new HandlerThread(TAG);
        hthread.start();
        mHandler = new MountServiceHandler(hthread.getLooper());

        // Add OBB Action Handler to MountService thread.
        mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());

        // Initialize the last-fstrim tracking if necessary
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);
        if (!mLastMaintenanceFile.exists()) {
            // Not setting mLastMaintenance here means that we will force an
            // fstrim during reboot following the OTA that installs this code.
            try {
                (new FileOutputStream(mLastMaintenanceFile)).close();
            } catch (IOException e) {
                Slog.e(TAG, "Unable to create fstrim record " + mLastMaintenanceFile.getPath());
            }
        } else {
            mLastMaintenance = mLastMaintenanceFile.lastModified();
        }

        mSettingsFile = new AtomicFile(
                new File(Environment.getSystemSecureDirectory(), "storage.xml"));

        synchronized (mLock) {
            readSettingsLocked();
        }

        LocalServices.addService(MountServiceInternal.class, mMountServiceInternal);

        /*
         * Create the connection to vold with a maximum queue of twice the
         * amount of containers we'd ever expect to have. This keeps an
         * "asec list" from blocking a thread repeatedly.
         */

        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                null);
        mConnector.setDebug(true);

        Thread thread = new Thread(mConnector, VOLD_TAG);
        thread.start();

        // Reuse parameters from first connector since they are tested and safe
        mCryptConnector = new NativeDaemonConnector(this, "cryptd",
                MAX_CONTAINERS * 2, CRYPTD_TAG, 25, null);
        mCryptConnector.setDebug(true);

        Thread crypt_thread = new Thread(mCryptConnector, CRYPTD_TAG);
        crypt_thread.start();

        final IntentFilter userFilter = new IntentFilter();
        userFilter.addAction(Intent.ACTION_USER_ADDED);
        userFilter.addAction(Intent.ACTION_USER_REMOVED);
        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);

        addInternalVolume();//添加内部Volume

        // Add ourself to the Watchdog monitors if enabled.
        if (WATCHDOG_ENABLE) {
            Watchdog.getInstance().addMonitor(this);
        }
    }

MountService在Volume这块改动比较大,我们先看下addInterVolume方法:

    private void addInternalVolume() {
        // Create a stub volume that represents internal storage
        final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
                VolumeInfo.TYPE_PRIVATE, null, null);
        internal.state = VolumeInfo.STATE_MOUNTED;
        internal.path = Environment.getDataDirectory().getAbsolutePath();
        mVolumes.put(internal.id, internal);
    }

其实就是在mVolumes增加了一个volume。

在看看MountServicesystemReady函数会发一个消息,最后由handleSystemReady执行

    private void handleSystemReady() {
        synchronized (mLock) {
            resetIfReadyAndConnectedLocked();
        }

        // Start scheduling nominally-daily fstrim operations
        MountServiceIdler.scheduleIdlePass(mContext);
    }
resetIfReadyAndConnectedLocked函数
    private void resetIfReadyAndConnectedLocked() {
        if (mSystemReady && mDaemonConnected) {
            killMediaProvider();

            mDisks.clear();
            mVolumes.clear();

            addInternalVolume();

            try {
                mConnector.execute("volume", "reset");//通知vold执行reset

                // Tell vold about all existing and started users
                final UserManager um = mContext.getSystemService(UserManager.class);
                final List<UserInfo> users = um.getUsers();
                for (UserInfo user : users) {
                    mConnector.execute("volume", "user_added", user.id, user.serialNumber);
                }
                for (int userId : mStartedUsers) {
                    mConnector.execute("volume", "user_started", userId);
                }
            } catch (NativeDaemonConnectorException e) {
                Slog.w(TAG, "Failed to reset vold", e);
            }
        }
    }
通知vold执行reset以及user_add、user_started命令


二、onStartUser函数

我们再看onStartUser函数,这个函数是统一由SystemServiceManager调用

    public void startUser(final int userHandle) {
        final int serviceLen = mServices.size();
        for (int i = 0; i < serviceLen; i++) {
            final SystemService service = mServices.get(i);
            try {
                service.onStartUser(userHandle);
            } catch (Exception ex) {
                Slog.wtf(TAG, "Failure reporting start of user " + userHandle
                        + " to service " + service.getClass().getName(), ex);
            }
        }
    }
而在SystemServer中,把这个SystemServiceManager传给了ActivityManagerService中,最后在AMS中调用它的startUser方法。

        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

我们再来看看MountService的onStartUser方法:

    private void onStartUser(int userId) {
        Slog.d(TAG, "onStartUser " + userId);

        // We purposefully block here to make sure that user-specific
        // staging area is ready so it's ready for zygote-forked apps to
        // bind mount against.
        try {
            mConnector.execute("volume", "user_started", userId);//往vold传user_started
        } catch (NativeDaemonConnectorException ignored) {
        }

        synchronized (mVolumes) {
            for (int i = 0; i < mVolumes.size(); i++) {//遍历mVolumes
                final VolumeInfo vol = mVolumes.valueAt(i);
                if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
                    mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();

                    final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
                    mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);//通知回调
                }
            }
            mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userId);
        }
    }

onStartUser会通知回调现在有的volume,就是primary的volume。在构造函数中已经添加。

我们再来看看这个回调

        private void notifyStorageStateChanged(String path, String oldState, String newState) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = path;
            args.arg2 = oldState;
            args.arg3 = newState;
            obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
        }
然后发送消息,因为注册的回调有好多个,所以需要遍历。最后调用了IMountServiceListener 的接口
@Override
        public void handleMessage(Message msg) {
            final SomeArgs args = (SomeArgs) msg.obj;
            final int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                final IMountServiceListener callback = mCallbacks.getBroadcastItem(i);
                try {
                    invokeCallback(callback, msg.what, args);
                } catch (RemoteException ignored) {
                }
            }
            mCallbacks.finishBroadcast();
            args.recycle();
        }

        private void invokeCallback(IMountServiceListener callback, int what, SomeArgs args)
                throws RemoteException {
            switch (what) {
                case MSG_STORAGE_STATE_CHANGED: {
                    callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
                            (String) args.arg3);
                    break;
                }
                case MSG_VOLUME_STATE_CHANGED: {
                    callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
                    break;
                }
                case MSG_VOLUME_RECORD_CHANGED: {
                    callback.onVolumeRecordChanged((VolumeRecord) args.arg1);
                    break;
                }
                case MSG_VOLUME_FORGOTTEN: {
                    callback.onVolumeForgotten((String) args.arg1);
                    break;
                }
                case MSG_DISK_SCANNED: {
                    callback.onDiskScanned((DiskInfo) args.arg1, args.argi2);
                    break;
                }
                case MSG_DISK_DESTROYED: {
                    callback.onDiskDestroyed((DiskInfo) args.arg1);
                    break;
                }
            }
        }
下一步我们看MountService的onEvent函数,这个需要结合vold来看。




  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值