Android 14 vold 分析(3)vold和mount service通信

2024-04-09 19:20

本文主要是介绍Android 14 vold 分析(3)vold和mount service通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

vold和mount service都是binder service,并不是mount service只调用vold,vold也会调用mount service,这是双向的,这里解答上一章的问题

思考, vold比mount service启动的早,那开机时vold获取到的listener为空,也就是说虽然disk创建了但是不会mount,那什么时候才会mount呢?

这里通过mount service 的分析解释上面的问题
1. mount service在SystemServer->startOtherServices() 可以看出这个service对android来说不是至关重要的,至少他不是bootstrap、core service
 
frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
.....
1788                      mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);
1789                      storageManager = IStorageManager.Stub.asInterface(
1790                              ServiceManager.getService("mount"));

2. onStart()
 
frameworks/base/services/core/java/com/android/server/StorageManagerService.java#231
231          public void onStart() {
232              mStorageManagerService = new StorageManagerService(getContext());  ----> 创建StorageManagerService实例
233              publishBinderService("mount", mStorageManagerService);   -----> 添加mount到ServiceManager里
234              mStorageManagerService.start();   -
235          }
3. 两件事: connectStoraged() 和 connectVold()
 
1926      private void start() {
1927          connectStoraged();
1928          connectVold();
1929      }
1930  
1931      private void connectStoraged() {
1932          IBinder binder = ServiceManager.getService("storaged");
1933          if (binder != null) {
1934              try {
1935                  binder.linkToDeath(new DeathRecipient() {
1936                      @Override
1937                      public void binderDied() {
1938                          Slog.w(TAG, "storaged died; reconnecting");
1939                          mStoraged = null;
1940                          connectStoraged();
1941                      }
1942                  }, 0);
1943              } catch (RemoteException e) {
1944                  binder = null;
1945              }
1946          }
1947  
1948          if (binder != null) {
1949              mStoraged = IStoraged.Stub.asInterface(binder);
1950          } else {
1951              Slog.w(TAG, "storaged not found; trying again");
1952          }
1953  
1954          if (mStoraged == null) {
1955              BackgroundThread.getHandler().postDelayed(() -> {
1956                  connectStoraged();
1957              }, DateUtils.SECOND_IN_MILLIS);
1958          } else {
1959              onDaemonConnected();
1960          }
1961      }
1962  
1963      private void connectVold() {
1964          IBinder binder = ServiceManager.getService("vold");
1965          if (binder != null) {
1966              try {
1967                  binder.linkToDeath(new DeathRecipient() {
1968                      @Override
1969                      public void binderDied() {
1970                          Slog.w(TAG, "vold died; reconnecting");
1971                          mVold = null;
1972                          connectVold();
1973                      }
1974                  }, 0);
1975              } catch (RemoteException e) {
1976                  binder = null;
1977              }
1978          }
1979  
1980          if (binder != null) {
1981              mVold = IVold.Stub.asInterface(binder);
1982              try {
1983                  mVold.setListener(mListener);   ---------->  连上vold 后把listener设置到了vold中
1984              } catch (RemoteException e) {
1985                  mVold = null;
1986                  Slog.w(TAG, "vold listener rejected; trying again", e);
1987              }
1988          } else {
1989              Slog.w(TAG, "vold not found; trying again");
1990          }
1991  
1992          if (mVold == null) {
1993              BackgroundThread.getHandler().postDelayed(() -> {
1994                  connectVold();
1995              }, DateUtils.SECOND_IN_MILLIS);
1996          } else {
1997              restoreLocalUnlockedUsers();
1998              onDaemonConnected();
1999          }
2000      }
3. onDaemonConnected()
1313      public void onDaemonConnected() {
1314          mDaemonConnected = true;
1315          mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
1316      }
1317  
1318      private void handleDaemonConnected() {
1319          resetIfBootedAndConnected();
1320      }

4. resetIfBootedAndConnected() 这里就是上一章提出的问题的原因函数
 
1056      private void resetIfBootedAndConnected() {
1057          Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
1058                  + ", mDaemonConnected=" + mDaemonConnected);
1059          if (mBootCompleted && mDaemonConnected) {              -------->  只有两个条件同时满足,才会执行reset操作
1060              final UserManager userManager = mContext.getSystemService(UserManager.class);
1061              final List<UserInfo> users = userManager.getUsers();
1062  
1063              mStorageSessionController.onReset(mVold, () -> {
1064                  mHandler.removeCallbacksAndMessages(null);
1065              });
1066  
1067              final int[] systemUnlockedUsers;
1068              synchronized (mLock) {
1069                  // make copy as sorting can change order
1070                  systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
1071                          mSystemUnlockedUsers.length);
1072  
1073                  mDisks.clear();
1074                  mVolumes.clear();
1075  
1076                  addInternalVolumeLocked();
1077              }
1078  
1079              try {
1080                  // Reset vold to tear down existing disks/volumes and start from
1081                  // a clean state.  Exception: already-unlocked user storage will
1082                  // remain unlocked and is not affected by the reset.
1083                  //
1084                  // TODO(b/135341433): Remove cautious logging when FUSE is stable
1085                  Slog.i(TAG, "Resetting vold...");
1086                  mVold.reset();                            ----------->>>>>>>>>> 根源在这里
1087                  Slog.i(TAG, "Reset vold");
1088  
1089                  // Tell vold about all existing and started users
1090                  for (UserInfo user : users) {
1091                      if (user.isCloneProfile()) {
1092                          mVold.onUserAdded(user.id, user.serialNumber, user.profileGroupId);
1093                      } else {
1094                          mVold.onUserAdded(user.id, user.serialNumber, -1);
1095                      }
1096                  }
1097                  for (int userId : systemUnlockedUsers) {
1098                      mVold.onUserStarted(userId);
1099                      mStoraged.onUserStarted(userId);
1100                  }
1101                  restoreSystemUnlockedUsers(userManager, users, systemUnlockedUsers);
1102                  mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
1103                  mStorageManagerInternal.onReset(mVold);
1104              } catch (Exception e) {
1105                  Slog.wtf(TAG, e);
1106              }
1107          }
1108      }

5.bootCompleted() 这里才会真正的执行到reset
238          public void onBootPhase(int phase) {
239              if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
240                  mStorageManagerService.servicesReady();
241              } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
242                  mStorageManagerService.systemReady();
243              } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
244                  mStorageManagerService.bootCompleted();
245              }2088      private void bootCompleted() {
2089          mBootCompleted = true;
2090          mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
2091      }2093      private void handleBootCompleted() {
2094          resetIfBootedAndConnected();
2095      }

log: 第三次才会执行reset
 

04-09 15:27:35.006  2112  3684 D StorageManagerService: Thinking about reset, mBootCompleted=false, mDaemonConnected=true
04-09 15:27:35.012  2112  3684 D StorageManagerService: Thinking about reset, mBootCompleted=false, mDaemonConnected=true
04-09 15:27:37.854  2112  3684 D StorageManagerService: Thinking about reset, mBootCompleted=true, mDaemonConnected=true

6. vold reset 就是执行的是VolumeManager::reset() 这里就不赘述了
 
904  int VolumeManager::reset() {
905      // Tear down all existing disks/volumes and start from a blank slate so
906      // newly connected framework hears all events.
907      for (const auto& vol : mInternalEmulatedVolumes) {
908          vol->destroy();
909      }
910      mInternalEmulatedVolumes.clear();                      
911  
912      // Destroy and recreate all disks except that StubVolume disks are just
913      // destroyed and removed from both mDisks and mPendingDisks.
914      // StubVolumes are managed from outside Android (e.g. from Chrome OS) and
915      // their disk recreation on reset events should be handled from outside by
916      // calling createStubVolume() again.
917      for (const auto& disk : mDisks) {
918          disk->destroy();
919          if (!disk->isStub()) {
920              disk->create();    -------------> 所有的disks 重新create一遍, 这回listener不会为空了
921          }
922      }
923      const auto isStub = [](const auto& disk) { return disk->isStub(); };
924      mDisks.remove_if(isStub);
925      mPendingDisks.remove_if(isStub);
926  
927      updateVirtualDisk();
928      mAddedUsers.clear();
929      mStartedUsers.clear();
930      mSharedStorageUser.clear();
931  
932      // Abort all FUSE connections to avoid deadlocks if the FUSE daemon was killed
933      // with FUSE fds open.
934      abortFuse();
935      return 0;
936  }


7. onVolumeCreated()
 
system/vold/model/VolumeBase.cpp
181  status_t VolumeBase::create() {
182      CHECK(!mCreated);
183  
184      mCreated = true;
185      status_t res = doCreate();
186  
187      auto listener = getListener();
188      if (listener) {
189          listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid,
190                                    mMountUserId);
191      }
192  
193      setState(State::kUnmounted);
194      return res;
195  }

8. onVolumeCreatedLocked()
 

1373          public void onVolumeCreated(String volId, int type, String diskId, String partGuid,
1374                  int userId) {
1375              synchronized (mLock) {
1376                  final DiskInfo disk = mDisks.get(diskId);
1377                  final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1378                  vol.mountUserId = userId;
1379                  mVolumes.put(volId, vol);
1380                  onVolumeCreatedLocked(vol);
1381              }
1382          }


9. onVolumeCreatedLocked()
.....
1523          } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
1524              // TODO: only look at first public partition
1525              if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1526                      && vol.disk.isDefaultPrimary()) {
1527                  Slog.v(TAG, "Found primary storage at " + vol);
1528                  vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1529                  vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
1530              }
1531  
1532              // Adoptable public disks are visible to apps, since they meet
1533              // public API requirement of being in a stable location.
1534              // If FBE is enabled, sdcard is no longer considered adoptable,
1535              // make sdcard visible.
1536              if (vol.disk.isAdoptable() || (vol.disk.isSd() && !vol.disk.label.equals("Virtual"))) {
1537                  vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
1538              }
1539  
1540              vol.mountUserId = mCurrentUserId;
1541              mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();  ------->  执行mount
1542  
1543          }....
740                  case H_VOLUME_MOUNT: {
741                      final VolumeInfo vol = (VolumeInfo) msg.obj;
742                      if (isMountDisallowed(vol)) {
743                          Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
744                          break;
745                      }
746  
747                      mount(vol);
748                      brea

这篇关于Android 14 vold 分析(3)vold和mount service通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/889014

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne