android存储3--初始化.unlock事件的处理

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模块进行各自初始化操作。

一、SystemServiceManager处理unlock事件

设备解锁后,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方法。

二、存储模块处理unlock事件

2.1  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函数可知道:

  • Lifecycle继承自SystemService抽象类
  • ​​​​​​​子类Lifecycle覆写了父类SystemService的onUnlockUser方法,但没有覆写onUserUnlocking

上文④处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后的逻辑,后面分段分析。

2.2  ⑤处代码mStorageSessionController.onUnlockUser分析

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);
    }

2.3  ⑥处代码mVold.onUserStarted(userId)分析

StorageManagerService::onUnlockUser中,mVold.onUserStarted(userId)是核心代码,比较复杂。这篇文章简单说一下mVold.onUserStarted功能,它主要是为外部存储创建、挂载相关目录,以主用户0为例,挂载视图如下:

android存储3--初始化.unlock事件的处理_第1张图片

注意,①②③④处在代码中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到其他的目录。

流程在下一篇文章中讲解。

2.4  ⑦处代码mStoraged.onUserStarted(userId)分析

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为外部存储挂载目录的流程。

你可能感兴趣的:(android,存储,android)