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

news2024/9/21 14:33:33

前言

在 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.Stub
        implements Watchdog.Monitor, ScreenObserver {
    public static class Lifecycle extends SystemService {
        private StorageManagerService mStorageManagerService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mStorageManagerService = new StorageManagerService(getContext());
            publishBinderService("mount", mStorageManagerService);
            mStorageManagerService.start();
        }

        @Override
        public 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();
            }
        }

        @Override
        public 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;
            }
        }

        @Override
        public void onUserUnlocking(@NonNull TargetUser user) {
            mStorageManagerService.onUnlockUser(user.getUserIdentifier());
        }

        @Override
        public void onUserStopped(@NonNull TargetUser user) {
            mStorageManagerService.onCleanupUser(user.getUserIdentifier());
        }

        @Override
        public void onUserStopping(@NonNull TargetUser user) {
            mStorageManagerService.onStopUser(user.getUserIdentifier());
        }

        @Override
        public void onUserStarting(TargetUser user) {
            mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle());
        }
    }
}

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

class StorageManagerService extends IStorageManager.Stub
        implements 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”的线程,并创建对应的Handler
        HandlerThread 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 necessary
        File 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.coloradmin.cn/o/1933202.html

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

相关文章

思路|如何利用oneNote钓鱼?

本文仅用于技术研究学习&#xff0c;请遵守相关法律&#xff0c;禁止使用本文所提及的相关技术开展非法攻击行为&#xff0c;由于传播、利用本文所提供的信息而造成任何不良后果及损失&#xff0c;与本账号及作者无关。 本文来源无问社区&#xff0c;更多实战内容&#xff0c;…

GuLi商城-商品服务-API-属性分组-分组修改级联选择器回显

前端代码:略 后端回显接口: 递归方法: @Override publi

Airtest封装的Tidevice接口有多好用(一)

一、前言 很多同学都有在Windows电脑上连接本地iOS设备去进行测试的需求&#xff0c;其中tidevice库是大家在Windows上使用的最多的iOS通信库&#xff0c;其中有一些接口是我们比较常用的&#xff0c;所以Airtest这边对一些常用的接口进行了封装&#xff0c;供大家日常写脚本的…

【web】-反序列化-to_string

<?php highlight_file(__FILE__); class A{public $s;public function __destruct(){echo "hello".$this->s;}} class B{public $cmd;public function __toString(){system($this->cmd);return 1;} } unserialize($_GET[code]); __toString()当对象被当着…

Java小白入门到实战应用教程-变量

变量 说明 变量是存储数据的基础单元。通过变量我们可以在代码去获取变量的数据、操作变量的数据。换种说法就是数据的存储体。 比如我们现在声明一个变量&#xff0c;并用它来存放一个数字1&#xff1b; int a 1;那么此时这个变量的值就为1&#xff0c;也可以理解成这个变…

QT应用编程: window下QT程序异常捕获并生成DMP文件、PDB文件

文章目录 main.cpp代码捕获异常 生成dmp文件和pdb文件DebugTest生成错误代码注意 分析软件崩溃&#xff0c;除了需要dmp&#xff0c;还需要这个pdb文件 dmp&#xff0c;文件记录了崩溃的信息&#xff0c;而pdb&#xff08;代码工程数据库&#xff09;&#xff0c;则包含了你写的…

【机器学习-00】机器学习是什么?

在科技飞速发展的今天&#xff0c;机器学习已成为一个热门话题&#xff0c;广泛应用于各个行业和领域。那么&#xff0c;机器学习到底是什么&#xff1f;它又是如何工作的&#xff1f;本文将深入探讨机器学习的定义、原理及其在各领域的应用&#xff0c;带领读者走进这个神秘而…

FGF18:骨关节炎治疗靶标

成纤维细胞生长因子18&#xff08;FGF18&#xff09;属于FGF8亚家族成员&#xff0c;在细胞增殖、细胞分化和细胞迁移的调节中起重要作用&#xff0c;是正常骨化和骨骼发育所需&#xff0c;同时刺激肝脏和肠道增殖。 &#xff08;数据来源AlphaFold&#xff09; FGF18由207个氨…

arcgis怎么选取某个指定区域地方的数据,比如从全国乡镇数据选取长沙市乡镇数据

一共5个步骤&#xff0c;没一句废话&#xff0c;耐心看完。 1、如图&#xff0c;先将数据加载到arcgis里面&#xff0c;我们要选取里面长沙市的范围数据。 2、选取长沙市的语句 “市” like ‘长沙%’ 切记&#xff0c;切记&#xff0c;切记。所有符号要在 输入法英文状态…

重生奇迹mu智力妹妹的召唤技能

很多人错误地认为智能小帮手只是一种辅助职业&#xff0c;没有太多的攻击能力。但是实际情况是&#xff0c;有一些智能小帮手不仅能够提供辅助&#xff0c;而且还可以扮演输出角色。他们的技能加持可以配合召唤宠物的攻击和仇恨&#xff0c;在击败BOSS的过程中发挥重要作用。 召…

【I²C协议】STC89C51单片机IIC通信(代码+原理)

STC89C51单片机IIC通信 什么是IC协议特点构成 通信协议开始信号、结束信号、应答信号数据传输 代码示例 什么是IC协议 IIC,即IC&#xff0c;全称 Inter-Integrated Circuit&#xff0c;字面上的意思是集成电路之间&#xff0c;它其实是IC Bus简称&#xff0c;所以中文应该叫 集…

ELK企业级日志分析

目 录 一、ELK简介 1.1 elasticsearch简介 1.2 logstash简介 1.3 kibana简介 1.4 ELK的好处 1.5 ELK的工作原理 二、部署ELK 2.1 部署elasticsearch(集群) 2.1.1 修改配置文件 2.1.2 修改系统参数 2.1.2.1 修改systemmd服务管理器 2.1.2.2 性能调优参数 2.1.2.3 …

网络和安全操作

一、编辑文件 文本编辑器有很多&#xff0c;比如图形模式的gedit、OpenOffice 等&#xff0c;文本模式下的编辑器有vi、vim&#xff08;vi的增强版本&#xff09;等。vi和vim是我们在Linux中最常用的编辑器。 gedit&#xff1a;类似于windows下的记事本&#xff0c;很方便的去…

JDK新特性(Lambda表达式,Stream流)

Lambda表达式&#xff1a; Lambda 表达式背后的思想是函数式编程&#xff08;Functional Programming&#xff09;思想。在传统的面向对象编程中&#xff0c;程序主要由对象和对象之间的交互&#xff08;方法调用&#xff09;构成&#xff1b;而在函数式编程中&#xff0c;重点…

数据结构之跳表SkipList、ConcurrentSkipListMap

概述 SkipList&#xff0c;跳表&#xff0c;跳跃表&#xff0c;在LevelDB和Lucene中都广为使用。跳表被广泛地运用到各种缓存实现当中&#xff0c;跳跃表使用概率均衡技术而不是使用强制性均衡&#xff0c;因此对于插入和删除结点比传统上的平衡树算法更为简洁高效。 Skip lis…

ROS参数服务器理论模型

ROS参数服务器理论模型 参数服务器角色实现参数服务器流程参数可以使用的类型 参数服务器角色 参数服务器实现是最为简单的&#xff0c;该模型如下图所示,该模型中涉及到三个角色: ROS Master (管理者)Talker (参数设置者)Listener (参数调用者) 实现参数服务器流程 整个流…

“论企业集成平台的理解与应用”,软考高级论文,系统架构设计师论文

论文真题 企业集成平台&#xff08;Enterprise Imtcgation Plaform,EIP)是支特企业信息集成的像环境&#xff0c;其主要功能是为企业中的数据、系统和应用等多种对象的协同行提供各种公共服务及运行时的支撑环境。企业集成平台能够根据业务模型的变化快速地进行信息系统的配置…

业务能力构建设计规划咨询项目(48页PPT)

业务能力构建设计规划咨询项目旨在为企业提供全面系统的指导与支持&#xff0c;通过48页PPT详细阐述如何从零开始建立起一套高效的业务体系。该项目将首先识别企业的核心竞争力&#xff0c;分析市场需求和内部资源配置&#xff0c;制定出切实可行的战略规划。 从流程优化、技术…

图片如何去水印,PS 图片去水印的几种常见方法

在数字图像的世界里&#xff0c;水印常常被用来标识版权或防止未经授权的使用&#xff0c;但有时它们却成为了美观的障碍。无论是出于个人偏好还是专业需求&#xff0c;去除图片上的水印已经成为一项常见的任务。 Adobe Photoshop 作为行业标准的图像编辑软件&#xff0c;提供…

Golang | Leetcode Golang题解之第240题搜索二维矩阵II

题目&#xff1a; 题解&#xff1a; func searchMatrix(matrix [][]int, target int) bool {m, n : len(matrix), len(matrix[0])x, y : 0, n-1for x < m && y > 0 {if matrix[x][y] target {return true}if matrix[x][y] > target {y--} else {x}}return f…