Android6.0对存储这块的改动还是比较大的,前面我们讲过了Android5.1上相关的代码,这里我们主要讲下区别,至于相同的部分,比如通信部分就不讲了,大家感兴趣可以看我之前5.1MountService和vold相关的博客。
我们先从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函数,这个函数是统一由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来看。