android存储第一篇--开机初始化流程

android版本:android-11.0.0_r21
http://aospxref.com/android-11.0.0_r21/

开机后,StorageManagerService收到开机广播消息H_BOOT_COMPLETED,按时间顺序完成以下4件事情:

  • init用户目录的加密状态
  • reset external storage service
  • reset vold service
  • 添加用户

代码整体逻辑如下:

android存储第一篇--开机初始化流程_第1张图片

1,init用户目录的加密状态

代码路径:StorageManagerServiceHandler::handleMessage --> handleBootCompleted --> initIfBootedAndConnected

分两种情况:
1)用户目录采用硬件加解密(native encryption),此阶段什么事也不做,函数直接返回
2)用户目录采用软件加解密(enmulated encryption),执行lock  encryption key(用户目录已加密的情况)或者unlock encryption key(用户目录未加密的情况)

从安全性、性能角度看,硬件加解密更好。

现在的手机基本都是硬件加解密方式,通过adb shell getprop ro.crypto.state可查询手机用的是哪种加解密方式。

adb shell getprop ro.crypto.state

返回字符串

加解密方式

"encrypted"

native encryption(硬件加解密)

"unencrypted" 或 "unsupported"

enmulated encryption(软件加解密)

"default"

手机还没有加密过

handleMessage处理H_BOOT_COMPLETED:
StorageManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/StorageManagerService.java

707      class StorageManagerServiceHandler extends Handler {
713          public void handleMessage(Message msg) {
714              switch (msg.what) {
719                  case H_BOOT_COMPLETED: {
720                      handleBootCompleted();
721                      break;
722                  }

 收到H_BOOT_COMPLETED广播消息后, 执行719行分支,handleBootCompleted函数如下:

2076      private void handleBootCompleted() {
2077          initIfBootedAndConnected();
2078          resetIfBootedAndConnected();
2079      }

initIfBootedAndConnected函数处理enmulated encryption场景,如果用户目录是加密状态,那么lock encryption key,否则就unlock encryption key。
StorageManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/StorageManagerService.java

1061      private void initIfBootedAndConnected() {

1064          if (mBootCompleted && mDaemonConnected
1065                  && !StorageManager.isFileEncryptedNativeOnly()) {

1069              final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();

1071              final List users = mContext.getSystemService(UserManager.class).getUsers();
1072              for (UserInfo user : users) {
1073                  try {
1074                      if (initLocked) {
1075                          mVold.lockUserKey(user.id);
1076                      } else {
1077                          mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
            
        ……

1065行StorageManager.isFileEncryptedNativeOnly(),判断设备是不是硬件加解密。如果是硬件加解密,则什么也不做,退出函数。设备用软件加解密时,进入1066行分支处理,根据StorageManager.isFileEncryptedEmulatedOnly()获取到的用户目录加密状态,执行lock 或者unlock encryption key操作。

2,reset external service

代码路径:StorageManagerServiceHandler::handleMessage --> handleBootCompleted --> resetIfBootedAndConnected --> StorageSessionController::onReset

external storage service是一个由名为com.android.providers.media.module的package提供的服务,用于管理外部存储设备(sd卡、u盘等),服务名称为com.android.providers.media.fuse.ExternalStorageServiceImpl。external storage service负责挂载/卸载外部存储设备、管理存储设备上的文件系统、处理app访问外部存储的请求。可通过adb shell dumpsys activity services com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl命令查看service详细信息。

app访问外部存储时,调用framework提供的接口(比如函数getExternalFilesDir、getExternalStorageDirectory、Environment.getExternalStoragePublicDirectory),然后这些函数再通过external storage service去访问外部存储。出于安全考虑,只有用户connect到external storage service后,也即该用户是被认可的,用户名下的app才允许访问外部存储。

reset external service主要完成2件事:
1)umount外部存储
2)关闭连接至external storage service的所有connection

一般情况下,外部存储还没有挂载成功,所以不需要卸载任何存储,也不需要关闭任何connection。不过下面还是过一下代码:

StorageManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/StorageManagerService.java

1087      private void resetIfBootedAndConnected() {

1090          if (mBootCompleted && mDaemonConnected) {
1091              final UserManager userManager = mContext.getSystemService(UserManager.class);
1092              final List users = userManager.getUsers();
1093  
1094              if (mIsFuseEnabled) {
1095                  mStorageSessionController.onReset(mVold, () -> {
1096                      mHandler.removeCallbacksAndMessages(null);
1097                  });
1098              } else {
1099                  killMediaProvider(users);
1100              }
            
            ……

1095行umount外部存储并关闭connection,mStorageSessionController.onReset函数如下:
StorageSessionController.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/storage/StorageSessionController.java

240      public void onReset(IVold vold, Runnable resetHandlerRunnable) {
245          SparseArray connections = new SparseArray();
246          synchronized (mLock) {
247              mIsResetting = true;
248              Slog.i(TAG, "Started resetting external storage service...");
249              for (int i = 0; i < mConnections.size(); i++) {
250                  connections.put(mConnections.keyAt(i), mConnections.valueAt(i));
251              }
252          }
253  
254          for (int i = 0; i < connections.size(); i++) {
255              StorageUserConnection connection = connections.valueAt(i);
256              for (String sessionId : connection.getAllSessionIds()) {
259                 vold.unmount(sessionId);
                     ……
268                  connection.removeSessionAndWait(sessionId);
279                  connection.close();

259行vold.unmount(即VoldNativeService::mount函数,参考StorageManagerService.java中的mVold.mount_geshifei的博客-CSDN博客)卸载外部存储设备,不过,在开机流程不会执行到这个函数。

279行关闭connection。

3,reset vold service

代码路径:StorageManagerServiceHandler::handleMessage --> handleBootCompleted --> resetIfBootedAndConnected --> mVold.reset

这个阶段主要完成3件事:

  • 销毁volume
  • 重置disk对象
  • 清空用户

StorageManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/StorageManagerService.java
 

1087      private void resetIfBootedAndConnected() {

                     /* reset external service,
                      * umount外部存储并关闭external storage service所有connection
                      */
1095                  mStorageSessionController.onReset(mVold, () -> {
1096                      mHandler.removeCallbacksAndMessages(null);
1097                  });         
1101  
1115                  // TODO(b/135341433): Remove paranoid logging when FUSE is stable
1116                  Slog.i(TAG, "Resetting vold...");
1117                  mVold.reset();
1118                  Slog.i(TAG, "Reset vold");
1112              }


1117行,mVold.reset()执行VoldNativeService::reset。
VoldNativeService.cpp - OpenGrok cross reference for /system/vold/VoldNativeService.cpp
 

164  binder::Status VoldNativeService::reset() {
165      ENFORCE_SYSTEM_OR_ROOT;
166      ACQUIRE_LOCK;
167  
168      return translate(VolumeManager::Instance()->reset());
169  }

168行,执行VolumeManager::reset函数。
VolumeManager.cpp - OpenGrok cross reference for /system/vold/VolumeManager.cpp

912  int VolumeManager::reset() {
913      // Tear down all existing disks/volumes and start from a blank slate so
914      // newly connected framework hears all events.
915      for (const auto& vol : mInternalEmulatedVolumes) {
916          vol->destroy();
917      }
918      mInternalEmulatedVolumes.clear();
919  
920      for (const auto& disk : mDisks) {
921          disk->destroy();
922          disk->create();
923      }
924      updateVirtualDisk();
925      mAddedUsers.clear();
926      mStartedUsers.clear();
927      return 0;
928  }

916行销毁volume(vol->destroy --> VolumeBase::destroy --> doDestroy)。

920行如果创建了disk对象(此时一般没有创建任何disk),就重置disk(先disk->destroy --> Disk:destory销毁disk对象,再disk->create --> Disk::create创建disk对象)。

925行,清空mAddedUsers中保存的所有用户ID,即删除所有已添加的用户。

926行,清空mStartedUsers中保存的所有用户ID,即删除所有已启动的用户。

4,在mAddedUsers中记录用户信息

代码路径:StorageManagerServiceHandler::handleMessage --> handleBootCompleted --> resetIfBootedAndConnected --> mVold.onUserAdded

mAddedUsers 是 VolumeManager 用于跟踪已添加的用户信息的数据结构,当系统启动时,它会将记录在其中的用户信息发送给 vold,以确保 vold 了解系统中所有用户的存在。这样可以确保 vold 能够正确地管理卷和磁盘。android支持多用户,用户外部存储挂载点为/storage/emulated/用户id,如果某个用户在连接设备后注销了系统,VolumeManager将记录在mAddedUsers中该用户信息发送给vold,vold就可以正确地卸个载设备上的卷或文件系统。

StorageManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/StorageManagerService.java

1087      private void resetIfBootedAndConnected() {

                      /* reset external service,
                       * umount外部存储并关闭external storage service所有connection
                       */
1095                  mStorageSessionController.onReset(mVold, () -> {
1096                      mHandler.removeCallbacksAndMessages(null);
1097                  });

                      /* reset vold service,
                       * 销毁volume,重置disk,清空用户
1117                  mVold.reset();

                      /* 在mAddedUsers中 记录用户信息 */
1121                  for (UserInfo user : users) {
1122                      mVold.onUserAdded(user.id, user.serialNumber);
1123                  }
1124                  for (int userId : systemUnlockedUsers) {
1125                      mVold.onUserStarted(userId);
1126                      mStoraged.onUserStarted(userId);
1127                  }
1128                  if (mIsAutomotive) {
1129                      restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
1130                  }
1131                  mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1132                  mStorageManagerInternal.onReset(mVold);
1133             

1122行mVold.onUserAdded,调用VoldNativeService::onUserAdded,代码VoldNativeService.cpp - OpenGrok cross reference for /system/vold/VoldNativeService.cpp

185  binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) {
186      ENFORCE_SYSTEM_OR_ROOT;
187      ACQUIRE_LOCK;
188  
189      return translate(VolumeManager::Instance()->onUserAdded(userId, userSerial));
190  }

189行执行的是VolumeManager::onUserAdded,代码VolumeManager.cpp - OpenGrok cross reference for /system/vold/VolumeManager.cpp

455  int VolumeManager::onUserAdded(userid_t userId, int userSerialNumber) {
456      LOG(INFO) << "onUserAdded: " << userId;
457  
458      mAddedUsers[userId] = userSerialNumber;
459      return 0;
460  }

458行将user信息添加到mAddedUsers中。

回到resetIfBootedAndConnected函数,看一下1124行分支:

1087      private void resetIfBootedAndConnected() {

                      /* reset external service,
                       * umount外部存储并关闭external storage service所有connection
                       */
1095                  mStorageSessionController.onReset(mVold, () -> {
1096                      mHandler.removeCallbacksAndMessages(null);
1097                  });

                      /* reset vold service,
                       * 销毁volume,重置disk,清空用户
1117                  mVold.reset();

                      /* 在mAddedUsers中 记录用户信息 */
1121                  for (UserInfo user : users) {
1122                      mVold.onUserAdded(user.id, user.serialNumber);
1123                  }
1124                  for (int userId : systemUnlockedUsers) {
1125                      mVold.onUserStarted(userId);
1126                      mStoraged.onUserStarted(userId);
1127                  }
1128                  if (mIsAutomotive) {
1129                      restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
1130                  }
1131                  mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1132                  mStorageManagerInternal.onReset(mVold);
1133             

systemUnlockedUsers"数组包含已经解锁的用户ID。当设备启动时,通常只有一个用户(User 0)被解锁,而其他用户(如果有的话)会在后续解锁后被添加到数组中。所以,对于开机流程,mVold.onUserStarted(userId)不会执行。
在某些情况下,例如设备支持多用户功能并且用户在设置中添加了一个或多个额外的用户,或者设备已经解锁并且用户在后续的操作中解锁了其他用户,则systemUnlockedUsers数组中就会包含多个用户ID。

那么,什么时间触发mVold.onUserStarted启动用户,为用户创建、挂载相关目录呢?看下一篇文章分析。

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