Android6.0对存储这块的改动还是比较大的,前面我们讲过了Android5.1上相关的代码,这里我们主要讲下区别,至于相同的部分,比如通信部分就不讲了,大家感兴趣可以看我之前5.1MountService和vold相关的博客。
我们先从MountService的实例化开始:
mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);//这个是MountService的lifecycle静态类
在SystemServer中调用了上面函数,
public T startService(Class 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 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 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来看。