当前位置: 首页 > news >正文

Android 12系统源码_存储(二)StorageManager类介绍

前言

在 Android 系统中,StorageManager类是一个用于获取存储设备信息和管理存储设备的类。它提供了一系列方法,可以获取当前挂载的存储设备信息,以及对存储设备进行挂载和卸载操作。

一、Storage存储模块介绍

1.1、StorageManagerService 简介

Android 外部存储空间由 Vold 服务和 StorageManagerService 系统服务共同管理。外部实体存储卷的装载由 Vold 处理,准备好后上报给 StorageManagerService,然后再将其提供给应用。在 Android 8.0 及以后,MountService 服务已经更名为 StorageManagerServic,并且 StorageManagerService 与 Vold 的通信由 socket 变更为 binder 方式。

代码路径分布:

层级结构主要文件代码路径
应用 api 接口层StorageManager.javaandroid/frameworks/base/core/java/android/os/storage
系统 framework 层StorageManagerService.javaandroid/frameworks/base/services/core/java/com/android/server
Vold 服务VoldNativeService.cppandroid/system/vold

1.2、StorageManagerService 架构

StorageManagerService架构图
图中描述了 StorageManagerService 模块的架构,上层 framework 服务 StorageManagerService 是由 SystemService 在启动阶段开启;Vold 服务在 init 阶段由 rc 文件启动,StorageManagerService 与 Vold 服务通过 aidl 的方式交互,Vold 服务中 VoldNativeService 实现了 aidl 接口,是作为 aidl 的服务端,但实际处理是在 VolumeManager 中实现,NetlinkManager 是 VolumeManager 与 驱动层通信事件上报的处理类,NetlinkManager 和 kernel 建立 socket 通讯,监听 kernel 的 uevent 事件,当驱动检测到有 U盘 接入/拔出时,会上报 event 事件给到 NetlinkHandler 处理,进入挂载/卸载流程。

1.3、监听U盘插拔的状态

Android 提供了一系列广播,应用可以通过这些广播来获取当前U盘状态。

广播含义
Intent.ACTION_MEDIA_CHECKING检查
Intent.ACTION_MEDIA_MOUNTED挂载
Intent.ACTION_MEDIA_UNMOUNTABLE无法挂载,挂载失败(常见是U盘挂载节点已经存在无法继续挂载)
Intent.ACTION_MEDIA_EJECT硬件弹出
Intent.ACTION_MEDIA_UNMOUNTED卸载
Intent.ACTION_MEDIA_REMOVEDvolume已经移除,代表移除流程已经走完
Intent.ACTION_MEDIA_BAD_REMOVALvolume已经移除,代表移除流程已经走完,可能节点没有卸载干净

二、StorageManagerService 启动

2.1、 SystemServer 阶段

SystemServer 会在 startOtherServices() 阶段启动 StorageManagerService 服务。

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {private static final String STORAGE_MANAGER_SERVICE_CLASS ="com.android.server.StorageManagerService$Lifecycle";private SystemServiceManager mSystemServiceManager;private void startOtherServices(@NonNull TimingsTraceAndSlog t) {...代码省略...if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {t.traceBegin("StartStorageManagerService");try {/** NotificationManagerService is dependant on StorageManagerService,* (for media / usb notifications) so we must start StorageManagerService first.*/mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS);storageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));} catch (Throwable e) {reportWtf("starting StorageManagerService", e);}t.traceEnd();...代码省略...}}  ...代码省略...        }    
}

2.2、SystemServiceManager启动StorageManagerService服务

frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public final class SystemServiceManager implements Dumpable {/*** 创建一个系统服务,该服务必须是com.android.server.SystemService的子类** @param serviceClass 一个实现了SystemService接口的Java类* @return 返回一个服务实例对象*/public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();Slog.i(TAG, "Starting " + name);Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + 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 {//获取参数为Context的构造方法,通过反射创建service对象Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException("Failed to create service " + name+ ": service could not be instantiated", ex);} catch (IllegalAccessException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (NoSuchMethodException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (InvocationTargetException ex) {throw new RuntimeException("Failed to create service " + name+ ": service constructor threw an exception", ex);}//继续调用startService方法startService(service);return service;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}}
}

SystemManagerService通过反射构建com.android.server.StorageManagerService$Lifecycle实例对象并调用onStart() 方法。

2.3、StorageManagerService阶段

1、StorageManagerService$Lifecycle的onStart方法会构建StorageManagerService实例对象并调用该对象的start方法。

frameworks/base/services/core/java/com/android/server/StorageManagerService.java

class StorageManagerService extends IStorageManager.Stubimplements Watchdog.Monitor, ScreenObserver {public static class Lifecycle extends SystemService {private StorageManagerService mStorageManagerService;public Lifecycle(Context context) {super(context);}@Overridepublic void onStart() {mStorageManagerService = new StorageManagerService(getContext());publishBinderService("mount", mStorageManagerService);mStorageManagerService.start();}@Overridepublic void onBootPhase(int phase) {if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {mStorageManagerService.servicesReady();} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {mStorageManagerService.systemReady();} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {mStorageManagerService.bootCompleted();}}@Overridepublic void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {int currentUserId = to.getUserIdentifier();mStorageManagerService.mCurrentUserId = currentUserId;UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);if (umInternal.isUserUnlocked(currentUserId)) {Slog.d(TAG, "Attempt remount volumes for user: " + currentUserId);mStorageManagerService.maybeRemountVolumes(currentUserId);mStorageManagerService.mRemountCurrentUserVolumesOnUnlock = false;} else {Slog.d(TAG, "Attempt remount volumes for user: " + currentUserId + " on unlock");mStorageManagerService.mRemountCurrentUserVolumesOnUnlock = true;}}@Overridepublic void onUserUnlocking(@NonNull TargetUser user) {mStorageManagerService.onUnlockUser(user.getUserIdentifier());}@Overridepublic void onUserStopped(@NonNull TargetUser user) {mStorageManagerService.onCleanupUser(user.getUserIdentifier());}@Overridepublic void onUserStopping(@NonNull TargetUser user) {mStorageManagerService.onStopUser(user.getUserIdentifier());}@Overridepublic void onUserStarting(TargetUser user) {mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle());}}
}

2、StorageManagerService$Lifecycle的onStart方法会构建StorageManagerService实例对象并调用该对象的start方法。

class StorageManagerService extends IStorageManager.Stubimplements Watchdog.Monitor, ScreenObserver {public StorageManagerService(Context context) {sSelf = this;// 前面先是读取一些属性状态,其中关于FUSE下面会稍微介绍一下mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);mContext = context;mResolver = mContext.getContentResolver();mCallbacks = new Callbacks(FgThread.get().getLooper());mLockPatternUtils = new LockPatternUtils(mContext);// 创建名为“StorageManagerService”的线程,并创建对应的HandlerHandlerThread hthread = new HandlerThread(TAG);hthread.start();mHandler = new StorageManagerServiceHandler(hthread.getLooper());//mObbActionHandler对应“android.io”线程// Add OBB Action Handler to StorageManagerService thread.mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());mStorageSessionController = new StorageSessionController(mContext);//启动installd服务mInstaller = new Installer(mContext);mInstaller.onStart();// Initialize the last-fstrim tracking if necessaryFile dataDir = Environment.getDataDirectory();File systemDir = new File(dataDir, "system");mLastMaintenanceFile = new File(systemDir, LAST_FSTRIM_FILE);//判断/data/system/last-fstrim文件,不存在则创建,存在则更新最后修改时间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();}// 读取data/system/storage.xml配置mSettingsFile = new AtomicFile(new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");synchronized (mLock) {readSettingsLocked();}LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);// 监听ACTION_USER_ADDED、ACTION_USER_REMOVED广播final IntentFilter userFilter = new IntentFilter();userFilter.addAction(Intent.ACTION_USER_ADDED);userFilter.addAction(Intent.ACTION_USER_REMOVED);mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);// 内部私有volume的路径为/data,该volume通过dumpsys mount是不会显示的synchronized (mLock) {addInternalVolumeLocked();}// Add ourself to the Watchdog monitors if enabled.if (WATCHDOG_ENABLE) {Watchdog.getInstance().addMonitor(this);}// 汽车应用支持mIsAutomotive = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);}private void start() {connectStoraged();connectVold();}
}

三、AIDL 接口层

1、aidl接口文件

Vold 的 aidl 文件定义在 /system/vold/binder/android/os/ 目录下。
在这里插入图片描述
该目录存在四个aidl文件:IVold.aidl、IVoldListener.aidl、IVoldMountCallback.aidl、IVoldTaskListener.aidl。

2、Vold模块Android.bp文件

Vold模块对应的Android.bp文件关于aild的编译语法如下所示:

package {default_applicable_licenses: ["Android-Apache-2.0"],
}
...代码省略...
cc_library_static {name: "libvold_binder",defaults: ["vold_default_flags"],srcs: [":vold_aidl",],shared_libs: ["libbinder","libutils",],aidl: {local_include_dirs: ["binder"],include_dirs: ["frameworks/native/aidl/binder","frameworks/base/core/java",],export_aidl_headers: true,},whole_static_libs: ["libincremental_aidl-cpp",],export_shared_lib_headers: ["libbinder",],
}...代码省略...filegroup {name: "vold_aidl",srcs: ["binder/android/os/IVold.aidl","binder/android/os/IVoldListener.aidl","binder/android/os/IVoldMountCallback.aidl","binder/android/os/IVoldTaskListener.aidl",],path: "binder",
}

相关文章:

  • MySQL数据库慢查询日志、SQL分析、数据库诊断
  • 1.厦门面试
  • 学习Python的IDE功能--(一)入门导览
  • uniapp小程序上传pdf文件
  • 好玩的调度技术-场景编辑器
  • Linux内核编译安装 - Deepin,Debian系
  • llama-index,uncharted and llama2:7b run locally to generate Index
  • C语言从头学35——struct结构
  • Web开发:卡片翻转效果(HTML、CSS)
  • 文心一言:如何备考软考架构师
  • MySQL第一次作业
  • 数据库day2
  • 伪元素::before :: after的用法?
  • 微软GraphRAG +本地模型+Gradio 简单测试笔记
  • 【C#】Array和List
  • [译] 怎样写一个基础的编译器
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 11111111
  • php ci框架整合银盛支付
  • Sequelize 中文文档 v4 - Getting started - 入门
  • Spring核心 Bean的高级装配
  • Vim 折腾记
  • zookeeper系列(七)实战分布式命名服务
  • 基于web的全景—— Pannellum小试
  • 计算机在识别图像时“看到”了什么?
  • 容器服务kubernetes弹性伸缩高级用法
  • 写给高年级小学生看的《Bash 指南》
  • 一、python与pycharm的安装
  • 一文看透浏览器架构
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​虚拟化系列介绍(十)
  • # SpringBoot 如何让指定的Bean先加载
  • # 飞书APP集成平台-数字化落地
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #14vue3生成表单并跳转到外部地址的方式
  • #includecmath
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • %@ page import=%的用法
  • (06)金属布线——为半导体注入生命的连接
  • (70min)字节暑假实习二面(已挂)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (二) 初入MySQL 【数据库管理】
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (五十)第 7 章 图(有向图的十字链表存储)
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)Linux整合apache和tomcat构建Web服务器
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .Net FrameWork总结
  • .NET Reactor简单使用教程
  • .net 后台导出excel ,word
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .NET中winform传递参数至Url并获得返回值或文件