Android 12系统源码_存储(二)StorageManagerService服务

前言

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

一、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",
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/872963.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1个Xpath定位可以在Web页面查找到多个元素Selenium

1个Xpath定位可以在Web页面查找到多个元素Selenium//input[id\"transactionId\"] 打开Web页面&#xff0c; 点击F12可以看到压面 点击Ctrl F 可以点图如下图的输入框&#xff0c;输入xpath&#xff0c;看右侧可以找到3个对应的元素 点击Ctrl F 点击Ctrl F 点…

PHP 在shell服务器 创建定时任务 - thinkphp6 crontab

需求 需要设置定时任务&#xff0c;定时执行预设的php代码&#xff0c;完成预设的任务。 1.首先shell打开服务器需要设置定时任务文件夹 我的位置是 /opt/apache/html/jobs/ 你们自己看你们的位置了&#xff0c;这个不固定 2.查看定时任务 crontab -l contab 定时任务固定用…

图神经网络实战(17)——深度图生成模型

图神经网络实战&#xff08;17&#xff09;——深度图生成模型 0. 前言1. 变分图自编码器2. 自回归模型3. 生成对抗网络小结系列链接 0. 前言 我们已经学习了经典的图生成算法&#xff0c;虽然它们能够完成图生成任务&#xff0c;但也存在一些问题&#xff0c;促使基于图神经网…

Nginx 和 PHP(特别是使用 Swoole 扩展)的配置和调优

针对千万级用户的高并发应用&#xff0c;Nginx 和 PHP&#xff08;特别是使用 Swoole 扩展&#xff09;的配置和调优是至关重要的。 以下是详细的配置和调优建议&#xff1a; Nginx 配置和调优 工作进程数&#xff08;worker_processes&#xff09;&#xff1a; 根据 CPU 核心…

28_EfficientNetV2网络详解

V1&#xff1a;https://blog.csdn.net/qq_51605551/article/details/140487051?spm1001.2014.3001.5502 1.1 简介 EfficientNetV2是Google研究人员Mingxing Tan和Quoc V. Le等人在2021年提出的一种深度学习模型&#xff0c;它是EfficientNet系列的最新迭代&#xff0c;旨在提…

leetcode日记(42)螺旋矩阵

我使用的是递归&#xff0c;每次递归遍历一圈矩阵&#xff0c;将遍历结果塞进结果vector中&#xff0c;每次遍历修改上下左右边界&#xff0c;直至遍历后其中两边界重合或交错。 class Solution { public:vector<int> spiralOrder(vector<vector<int>>&…

好玩的动作单机游戏:鬼泣4 游戏安装包

Devil May Cry 4让玩家沉醉于哥德式的超自然世界之中&#xff1b;体验一个新主角与熟悉的英雄发生冲突的故事。玩家操作新主角Nero&#xff0c;利用游戏独特的新系统──强大的「恶魔之手」能释放令人难以置信的攻击和製作出不间断的连续技。 凭藉PC的高效能图形显示功能&…

收银系统源码-千呼新零售2.0【数据报表】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

LeetCode-计数质数

计数质数 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 示例 1&#xff1a; 输入&#xff1a;n 10 输出&#xff1a;4 解释&#xff1a;小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 示例 2&#xff1a; 输入&#xff1a;n 0 输出&#xff1a;0 示…

在 Java 中,如何进行基本数据类型与其包装类之间的转换?

在Java中&#xff0c;基本数据类型&#xff08;如int, double, boolean等&#xff09;和它们对应的包装类&#xff08;如Integer, Double, Boolean等&#xff09;之间转换是一项常见的操作。 包装类主要是为了方便在需要对象的地方使用基本类型值&#xff0c;比如集合类&#…

解决SpringBoot集成Mybatis 配置多数据源后,打印SQL失效问题

SpringBoot集成Mybati 配置多数据源参考上一篇文章 在Spring框架中使用MyBatis时&#xff0c;如果配置了多数据源&#xff0c;可能会导致之前配置的打印SQL语句的设置失效。这通常是因为在多数据源配置中&#xff0c;MyBatis的SQL打印功能只对默认数据源生效&#xff0c;而对于…

深度学习落地实战:人脸五官定位检测

前言 大家好,我是机长 本专栏将持续收集整理市场上深度学习的相关项目,旨在为准备从事深度学习工作或相关科研活动的伙伴,储备、提升更多的实际开发经验,每个项目实例都可作为实际开发项目写入简历,且都附带完整的代码与数据集。可通过百度云盘进行获取,实现开箱即用 …

【LeetCode】162. 寻找峰值

1. 题目 2. 分析 这道题的难点有二&#xff1a;第一&#xff0c;知道用二分法求解&#xff1b;第二&#xff0c;二分判断的标准是什么&#xff1f;传统的题目的二分标注都是跟某个固定的值做比较&#xff0c;但是此题不然。此题的比较对象是相邻的元素。 不要硬凭自己的脑子…

LeetCode第106题:从中序与后序遍历序列构造二叉树的Java实现

摘要 LeetCode第106题要求使用一棵树的中序遍历和后序遍历序列来重建二叉树。本文将介绍两种Java实现方法&#xff1a;递归和迭代。 1. 问题描述 给定一棵树的中序遍历和后序遍历序列&#xff0c;重建出这棵树的唯一二叉树结构。 2. 示例分析 输入&#xff1a;[1,2,4]&…

C语言·函数(超详细系列·全面总结)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;为了更好地形成一个学习c语言的体系&#xff0c;最近将会更新关于c语言语法基础的知识&#xff0c;今天更新一下函数的知识点&#xff0c;我们一起来看看吧&#xff01; 目录 一、函数是什么 &a…

vue、js截取视频任意一帧图片

html有本地上传替换部分&#xff0c;可以不看 原理&#xff1a;通过video标签对视频进行加载&#xff0c;随后使用canvas对截取的视频帧生成需要的图片 <template> <el-row :gutter"18" class"preview-video"><h4>视频预览<span&…

execv函数简单使用

在Unix-like系统中&#xff0c;execv 函数用于执行一个新的程序&#xff0c;同时可以传递参数给它。这个函数是 exec 系列函数之一&#xff0c;用于替换当前进程映像。 execv 的原型如下&#xff1a; int execv(const char *path, char *const argv[]); path&#xff1a;新程…

【边缘计算网关教程】9.对接ThingsBoard(MQTT协议)

前景回顾-【边缘计算网关教程】8.ModbusTCP采集存储Influxdb-CSDN博客 目录 需求分析 平台配置&#xff1a; 需求实现 第一步&#xff1a;采集Modbus TCP数据 第二步&#xff1a;拼接Json 第三步&#xff1a;MQTT上报 平台配置 第一步&#xff1a;添加设备 ​编辑第二…

国内新能源汽车芯片自给,承认差距,任重道远

【科技明说 &#xff5c; 科技热点关注】 据近日工信部电子五所元器件与材料研究院高级副院长罗道军表示&#xff0c;中国拥有最大的新能源车产能&#xff0c;芯片用量也是越来越多。但是芯片的自给率目前不到10%&#xff0c;是结构性的短缺。 中国拥有最大新能源车产能&#…

自学网络安全:从菜鸟到守护者的蜕变之旅

在这个数字化时代&#xff0c;网络安全不再是遥不可及的专业术语&#xff0c;而是与我们每个人的生活息息相关。随着网络攻击事件的频发&#xff0c;掌握一定的网络安全知识&#xff0c;不仅是对个人隐私的保护&#xff0c;更是对社会安全的贡献。今天&#xff0c;就让我们一起…