android版本:android-11.0.0_r21
http://aospxref.com/android-11.0.0_r21
概述:SystemServiceManager收到unlock事件后,遍历service链表,执行各个service的onUserUnlocking。对于存储service,执行的是StorageManagerService$Lifecycle中的onUserUnlocking,在这个方法中,存储的StorageSessionController、vold、storaged模块进行各自初始化操作。
设备解锁后,loop线程处理unlock消息,最终会执行到存储的StorageManagerService$Lifecycle中的onUserUnlocking方法,整个流程如下:
loop() //android.os.Looper
|
|-->msg.target.dispatchMessage(msg) //android.os.Handler
|
|--mCallback.handleMessage(msg) //com.android.server.am.UserController
|
|--case USER_UNLOCK_MSG:
mInjector.getSystemServiceManager().unlockUser(userId) //com.android.server.SystemServiceManager
|
①|--onUser(UNLOCKING, userHandle) //com.android.server.SystemServiceManager
|
②|--onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle) //com.android.server.SystemServiceManager
|
③|--onUser(t, onWhat, userHandle, UserHandle.USER_NULL) //com.android.server.SystemServiceManager
|
|--case UNLOCKING:
service.onUserUnlocking(curUser) //com.android.server.SystemService
|
|--onUnlockUser(user.getUserInfo()) //com.android.server.SystemService
|
|--onUnlockUser(userInfo.id) //com.android.server.StorageManagerService$Lifecycle
1)loop线程处理Android消息队列中的消息和事件,从队列中获取事件,将unlock事件通知其他系统服务。
2)系统服务UserController管理用户和用户操作,接收到USER_UNLOCK_MSG消息后执行SystemServiceManager中的unlockUser方法。
3)unlockUser方法经过几次转换(①②③见下,只是做了参数转换。参数差异见下)。
SystemServiceManager::(final @UserIdInt int userHandle)
--> onUser(@NonNull String onWhat, @UserIdInt int userHandle) ①
--> onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
@UserIdInt int userHandle) ②
-->onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
@UserIdInt int curUserId, @UserIdInt int prevUserId) ③
(如果未写明方法所属class,默认所属class与前面相同,所以这些onUser方法都是SystemServiceManager类中实现的)
UserController收到USER_UNLOCK_MSG后的处理细节见其他文章。
最终③处的onUser会遍历mServices链表,执行各个service的 onUserUnlocking,简化后的代码如下:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java#onUser
//frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
@UserIdInt int curUserId, @UserIdInt int prevUserId) {
final TargetUser curUser = new TargetUser(getUserInfo(curUserId));
final int serviceLen = mServices.size();
// 遍历系统服务,执行每个servie的onUserUnlocking方法
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
final String serviceName = service.getClass().getName();
try {
switch (onWhat) {
case UNLOCKING:
service.onUserUnlocking(curUser); // ④,存储的sevice是"StorageManagerService$Lifecycle"
break;
……
}
}
}
《android存储2--初始化.存储service的启动》中“mount service”一节已经阐述了StorageManagerService$Lifecycle发布的流程,所以上面代码执行for循环时,SystemService service = mServices.get(i)将会获取到StorageManagerService$Lifecycle。在④处,service.onUserUnlocking(curUser)将会执行StorageManagerService$Lifecycle中的onUserUnlocking方法。
StorageManagerService中定义了静态内部类StorageManagerService$Lifecycle,这个内部类用来控制StorageManagerService的Lifecycle,代码见下:http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#246
public class StorageManagerService extends IStorageManager.Stub
implements Watchdog.Monitor, ScreenObserver {
public static class Lifecycle extends SystemService {
protected StorageManagerService mStorageManagerService;
@Override
public void onUnlockUser(int userHandle) {
mStorageManagerService.onUnlockUser(userHandle);
}
……
}
}
从StorageManagerService$Lifecycle函数可知道:
上文④处service.onUserUnlocking(curUser)调用的是父类SystemService::onUserUnlocking方法(因为StorageManagerService$Lifecycle没有覆写onUserUnlocking),见下。
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemService.java#onUserUnlocking
// SystemService类中的实现
public void onUserUnlocking(@NonNull TargetUser user) {
onUnlockUser(user.getUserInfo());
}
onUnlockUser(user.getUserInfo())执行SystemService::onUnlockUser(@NonNull UserInfo userInfo)方法(注意重载参数类型)。
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemService.java#onUnlockUser
// SystemService类中的实现
public void onUnlockUser(@NonNull UserInfo userInfo) {
onUnlockUser(userInfo.id);
}
onUnlockUser(userInfo.id)执行的是被StorageManagerService$Lifecycle覆写后的方法:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#onUnlockUser
//StorageManagerService$Lifecycle类中的实现
@Override
public void onUnlockUser(int userHandle) {
mStorageManagerService.onUnlockUser(userHandle);
}
mStorageManagerService.onUnlockUser代码:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#1162
//StorageManagerService类中的实现
1162 private void onUnlockUser(int userId) {
1163 Slog.d(TAG, "onUnlockUser " + userId);
1164
1165 // We purposefully block here to make sure that user-specific
1166 // staging area is ready so it's ready for zygote-forked apps to
1167 // bind mount against.
1168 try {
1169 mStorageSessionController.onUnlockUser(userId); // ⑤
1170 mVold.onUserStarted(userId); // ⑥
1171 mStoraged.onUserStarted(userId); // ⑦
1172 } catch (Exception e) {
1173 Slog.wtf(TAG, e);
1174 }
1175
1176 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1177 }
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#1162即StorageManagerService$Lifecycle中的onUserUnlocking方法最终执行到StorageManagerService::onUnlockUser方法。⑤⑥⑦是存储内部各模块处理unlock user后的逻辑,后面分段分析。
StorageManagerService::onUnlockUser中,mStorageManagerService.onUnlockUser执行的是StorageSessionController::onUnlockUser:
// 初始化 mExternalStorageServiceComponent变量(ComponentName类型)
StorageManagerService::onUnlockUser
--> StorageSessionController::initExternalStorageServiceComponent
mExternalStorageServiceComponent用于提供外部存储服务,初始化后mExternalStorageServiceComponent的信息如下:
mExternalStorageServiceComponent.getPackageName()
值为:com.android.providers.media.module
mExternalStorageServiceComponent.getClassName()
值为:com.android.providers.media.fuse.ExternalStorageServiceImpl
ComponentName
值为:com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl
⑤处代码很简单,就是初始化了mExternalStorageServiceComponent变量。
附上mExternalStorageServiceComponent是何时使用的:
StorageSessionController::getExternalStorageServiceComponentName获取mExternalStorageServiceComponent,即com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl。这个服务是在provider/media/fuse目录实现的:
http://aospxref.com/android-11.0.0_r21/xref/packages/providers/MediaProvider/src/com/android/providers/media/fuse/
mExternalStorageServiceComponent在mount emulated 存储时,用于连接ExternalStorageServiceImpl服务,流程如下:
StorageManagerService::mount
--> mStorageSessionController.onVolumeMount(pfd, vol) // StorageSessionController::onVolumeMount
// sessionId: emulated;0
// deviceFd代表的文件:/dev/fuse
// vol.getPath().getPath()对应upperPath,值为:/storage/emulated
// vol.getInternalPath().getPath()对应lowerPath,值为:/data/media
--> connection.startSession(sessionId, deviceFd, vol.getPath().getPath(),
vol.getInternalPath().getPath()) // StorageUserConnection::startSession
// sessionId, upperPath, lowerPath封装进session
--> session = new Session(sessionId, upperPath, lowerPath)
--> mActiveConnection.startSession(session, pfd) // StorageUserConnection$ActiveConnection::startSession
// fd代表的文件:/dev/fuse
--> waitForAsync((service, callback) -> service.startSession(session.sessionId,
FLAG_SESSION_TYPE_FUSE | FLAG_SESSION_ATTRIBUTE_INDEXABLE,
fd, session.upperPath, session.lowerPath, callback))
--> serviceFuture = connectIfNeeded()
//获取外部存储组件名称com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl
--> name = mSessionController.getExternalStorageServiceComponentName()
--> mContext.bindServiceAsUser(new Intent().setComponent(name),
mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
mHandlerThread.getThreadHandler(),
UserHandle.of(mUserId))) // ContextImpl::bindServiceAsUser
--> bindServiceCommon(service, conn, flags, null, handler, null, user) // ContextImpl::bindServiceCommon
--> ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver())
MediaProvider::openFile --> openFileCommon --> openFileAndEnforcePathPermissionsHelper中:
// MediaProvider.java openFileAndEnforcePathPermissionsHelper函数
// 通过ExternalStorageServiceImpl.getFuseDaemon获取daemon
daemon = getFuseDaemonForFile(file);
boolean shouldOpenWithFuse = daemon != null
&& daemon.shouldOpenWithFuse(filePath, true /* forRead */,
lowerFsFd.getFd());
if (SystemProperties.getBoolean(PROP_FUSE, false) && shouldOpenWithFuse) {
// 走fuse流程
pfd = FileUtils.openSafely(getFuseFile(file), modeBits);
try {
lowerFsFd.close();
}
} else {
// 绕过fuse,直接走底层文件系统
Log.i(TAG, "Using lower FS for " + filePath);
}
StorageManagerService::onUnlockUser中,mVold.onUserStarted(userId)是核心代码,比较复杂。这篇文章简单说一下mVold.onUserStarted功能,它主要是为外部存储创建、挂载相关目录,以主用户0为例,挂载视图如下:
注意,①②③④处在代码中bind mount挂载的分别是:
①:/mnt/runtime/full/emulated on /mnt/pass_through/0/emulated
②:/mnt/runtime/default/emulated/0/Android/data on /mnt/user/0/emulated/0/Android/data
③:/mnt/runtime/default/emulated/0/Android/obb on /mnt/user/0/emulated/0/Android/obb
④:/mnt/runtime/write/emulated/0/Android/obb on /mnt/installer/0/emulated/0/Android/obb
但mount命令看到的却是/data/media目录被bindmount到其他的目录。
流程在下一篇文章中讲解。
StorageManagerService::onUnlockUser中,mStoraged.onUserStarted(userId)功能比较简单,为storaged加载/data/misc_ce/0/storaged.proto文件。
storaged周期地将统计结果写入/data/misc_ce/0/storaged.proto(默认1小时更新一次,见DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO宏),这个文件按照system/core/storaged/storaged.proto格式编码。执行storaged -p命令时从/data/misc_ce/0/storaged.proto读取数据输出到终端上。示例如下:
cp15:/data/misc_ce/0/storaged # ls
storaged.proto
cp15:/data/misc_ce/0/storaged # storaged -p
I/O perf history (KB/s) : most_recent <--------- least_recent
last 24 hours : 66468 33941 44126 35316 45839 37312
last 7 days : 0 0 0 0 0 0 0
last 52 weeks : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
cp15:/data/misc_ce/0/storaged #
下一篇文章分析mVold.onUserStarted为外部存储挂载目录的流程。