前言
在 Android 系统中,StorageManagerService是一个用于获取存储设备信息和管理存储设备的服务。它提供了一系列方法,可以获取当前挂载的存储设备信息,以及对存储设备进行挂载和卸载操作。
一、Storage存储模块介绍
1.1、StorageManagerService 简介
Android 外部存储空间由 Vold 服务和 StorageManagerService 系统服务共同管理。外部实体存储卷的装载由 Vold 处理,准备好后上报给 StorageManagerService,然后再将其提供给应用。在 Android 8.0 及以后,MountService 服务已经更名为 StorageManagerServic,并且 StorageManagerService 与 Vold 的通信由 socket 变更为 binder 方式。
代码路径分布:
| 层级结构 | 主要文件 | 代码路径 | 
|---|---|---|
| 应用 api 接口层 | StorageManager.java | android/frameworks/base/core/java/android/os/storage | 
| 系统 framework 层 | StorageManagerService.java | android/frameworks/base/services/core/java/com/android/server | 
| Vold 服务 | VoldNativeService.cpp | android/system/vold | 
1.2、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_REMOVED | volume已经移除,代表移除流程已经走完 | 
| Intent.ACTION_MEDIA_BAD_REMOVAL | volume已经移除,代表移除流程已经走完,可能节点没有卸载干净 | 
二、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",
}



















