前言
Android外部存儲空間由 vold init 服務(wù)和 StorageManagerService 系統(tǒng)服務(wù)共同管理肋僧。外部實(shí)體存儲卷的裝載由 vold 處理:通過執(zhí)行分階段操作準(zhǔn)備好媒體剿涮,然后再將其提供給應(yīng)用萍悴。
從 Android 8.0 開始入篮,MountService 類已更名為 StorageManagerService谨垃。
并且StorageManagerService與Vold的通信方式由socket方式變?yōu)閎inder方式,精簡了部分代碼墓拜。
涉及代碼路徑:
基于android11走讀存儲系統(tǒng)部分代碼
frameworks/base/services/core/java/com/android/server/StorageManagerService.java
frameworks/base/services/java/com/android/server/SystemServer.java
StorageManagerService
startService
StorageManagerService同其他系統(tǒng)服務(wù)一樣港柜,也是從SystemServer啟動
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();
t.traceBegin("StartStorageStatsService");
try {
mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting StorageStatsService", e);
}
t.traceEnd();
}
}
...
}
NotificationManagerService依賴于StorageManagerService,所以必需先啟動StroageManagerService咳榜。
private static final String STORAGE_MANAGER_SERVICE_CLASS = "com.android.server.StorageManagerService$Lifecycle";
SystemManagerService通過反射構(gòu)建LifeCycle并調(diào)用onStart()方法
@Override
public void onStart() {
mStorageManagerService = new StorageManagerService(getContext());
publishBinderService("mount", mStorageManagerService);
mStorageManagerService.start();
}
StorageManagerService
public StorageManagerService(Context context) {
sSelf = this;
// 前面先是讀取一些屬性狀態(tài)夏醉,其中關(guān)于FUSE下面會稍微介紹一下
// Snapshot feature flag used for this boot
SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
// If there is no value in the property yet (first boot after data wipe), this value may be
// incorrect until #updateFusePropFromSettings where we set the correct value and reboot if
// different
mIsFuseEnabled = SystemProperties.getBoolean(PROP_FUSE, DEFAULT_FUSE_ENABLED);
mVoldAppDataIsolationEnabled = mIsFuseEnabled && 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);
// 創(chuàng)建名為“StorageManagerService”的線程,并創(chuàng)建對應(yīng)的Handler
HandlerThread hthread = new HandlerThread(TAG);
hthread.start();
mHandler = new StorageManagerServiceHandler(hthread.getLooper());
// mObbActionHandler對應(yīng)“android.io”線程
// Add OBB Action Handler to StorageManagerService thread.
mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
mStorageSessionController = new StorageSessionController(mContext, mIsFuseEnabled);
// 啟動installd服務(wù)
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文件涌韩,不存在則創(chuàng)建畔柔,存在則更新最后修改時間
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);
// 監(jiān)聽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);
// 內(nèi)部私有volume的路徑為/data臣樱,該volume通過dumpsys mount是不會顯示的
synchronized (mLock) {
addInternalVolumeLocked();
}
// Add ourself to the Watchdog monitors if enabled.
if (WATCHDOG_ENABLE) {
Watchdog.getInstance().addMonitor(this);
}
// 汽車應(yīng)用支持
mIsAutomotive = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
}
FUSE
為了實(shí)現(xiàn)更靈活的權(quán)限管理能力靶擦,Android引入了fuse文件系統(tǒng)。
Filesystem in Userspace顧名思義雇毫,即在用戶空間的文件系統(tǒng)奢啥。
為什么要強(qiáng)調(diào)用戶空間呢?接觸過Linux內(nèi)核的同學(xué)大概會知道嘴拢,文件系統(tǒng)一般是實(shí)現(xiàn)在內(nèi)核里面的,比如寂纪,Ext4席吴、Fat32赌结、NTFS(Kernel原生版)等常見的文件系統(tǒng),其代碼都在內(nèi)核中孝冒,而FUSE特殊之處就是柬姚,其文件系統(tǒng)的核心邏輯是在用戶空間實(shí)現(xiàn)的。
FUSE實(shí)現(xiàn)原理
圖中體現(xiàn)了FUSE的2個關(guān)鍵部分(綠色方框)庄涡,分別是Kernel中的那個FUSE(這里簡稱kernel FUSE)和user space中的那個fuse_user程序量承。其中kernel FUSE是負(fù)責(zé)把從用戶層過來的文件系統(tǒng)操作請求傳遞給fuse_user程序的,而這個fuse_user程序?qū)崿F(xiàn)了前面所說的文件系統(tǒng)的核心邏輯穴店。
onStart
private void start() {
connectStoraged();
connectVold();
}
private void connectStoraged() {
IBinder binder = ServiceManager.getService("storaged");
if (binder != null) {
try {
// 設(shè)置死亡代理以重新建立連接
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "storaged died; reconnecting");
mStoraged = null;
connectStoraged();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
// 獲取storaged的bp端用于通信
mStoraged = IStoraged.Stub.asInterface(binder);
} else {
Slog.w(TAG, "storaged not found; trying again");
}
if (mStoraged == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connectStoraged();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
}
}
private void connectVold() {
IBinder binder = ServiceManager.getService("vold");
if (binder != null) {
try {
// 設(shè)置死亡代理以重新建立連接
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "vold died; reconnecting");
mVold = null;
connectVold();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
// 獲取Vold的bp端用于通信
mVold = IVold.Stub.asInterface(binder);
try {
// 關(guān)鍵代碼:設(shè)置Vold的Listener
mVold.setListener(mListener);
} catch (RemoteException e) {
mVold = null;
Slog.w(TAG, "vold listener rejected; trying again", e);
}
} else {
Slog.w(TAG, "vold not found; trying again");
}
if (mVold == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connectVold();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
}
}
connectStoraged和connectVold分別是獲取Vold和Storaged服務(wù)的bp端撕捍,設(shè)置死亡代理,
為Vold設(shè)置Listener監(jiān)聽泣洞,然后調(diào)用onDaemonConnected
public void onDaemonConnected() {
mDaemonConnected = true;
mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
}
private void handleDaemonConnected() {
initIfBootedAndConnected();
resetIfBootedAndConnected();
// On an encrypted device we can't see system properties yet, so pull
// the system locale out of the mount service.
if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
copyLocaleFromMountService();
}
}
private void initIfBootedAndConnected() {
Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
+ ", mDaemonConnected=" + mDaemonConnected);
if (mBootCompleted && mDaemonConnected
&& !StorageManager.isFileEncryptedNativeOnly()) {
// 根據(jù)persist.sys.emulate_fbe確定用戶目錄的加鎖/解鎖狀態(tài)
final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
for (UserInfo user : users) {
try {
if (initLocked) {
mVold.lockUserKey(user.id);
} else {
mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
encodeBytes(null));
}
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
}
}
private void resetIfBootedAndConnected() {
Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
+ ", mDaemonConnected=" + mDaemonConnected);
// systemserver啟動進(jìn)入bootcomplete階段
if (mBootCompleted && mDaemonConnected) {
final UserManager userManager = mContext.getSystemService(UserManager.class);
final List<UserInfo> users = userManager.getUsers();
if (mIsFuseEnabled) {
mStorageSessionController.onReset(mVold, () -> {
mHandler.removeCallbacksAndMessages(null);
});
} else {
killMediaProvider(users);
}
final int[] systemUnlockedUsers;
synchronized (mLock) {
// make copy as sorting can change order
systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
mSystemUnlockedUsers.length);
// 清空mDisk和mVolumes兩個ArrayMap
mDisks.clear();
mVolumes.clear();
// 將/data為路徑的private volume添加到mVolumes
addInternalVolumeLocked();
}
try {
// 通過Vold的bp端調(diào)用reset()方法
// TODO(b/135341433): Remove paranoid logging when FUSE is stable
Slog.i(TAG, "Resetting vold...");
mVold.reset();
Slog.i(TAG, "Reset vold");
// 通知Vold所有的用戶和已解鎖用戶
for (UserInfo user : users) {
mVold.onUserAdded(user.id, user.serialNumber);
}
for (int userId : systemUnlockedUsers) {
mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
}
if (mIsAutomotive) {
restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
}
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
mStorageManagerInternal.onReset(mVold);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
}
onBootPhase
@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();
}
}
SystemServiceManager的startBootPhase()貫穿system_server進(jìn)程的整個啟動過程
1. servicesReady
private void servicesReady() {
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
mIPackageManager = IPackageManager.Stub.asInterface(
ServiceManager.getService("package"));
mIAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
// MediaProvider
ProviderInfo provider = getProviderInfo(MediaStore.AUTHORITY);
if (provider != null) {
mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
sMediaStoreAuthorityProcessName = provider.applicationInfo.processName;
}
// DownloadsProvider
provider = getProviderInfo(Downloads.Impl.AUTHORITY);
if (provider != null) {
mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
// DocumentsUiProvider
provider = getProviderInfo(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
if (provider != null) {
mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
if (!mIsFuseEnabled) {
try {
mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null,
mAppOpsCallback);
mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
} catch (RemoteException e) {
}
}
}
2. systemReady
private void systemReady() {();
LocalServices.getService(ActivityTaskManagerInternal.class)
.registerScreenObserver(this);
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
private void handleSystemReady() {
//計劃執(zhí)行日常的fstrim操作?
// Start scheduling nominally-daily fstrim operations
MountServiceIdler.scheduleIdlePass(mContext);
// 響應(yīng)設(shè)置而切換zram-enable系統(tǒng)屬性
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
false /*notifyForDescendants*/,
new ContentObserver(null /* current thread */) {
@Override
public void onChange(boolean selfChange) {
refreshZramSettings();
}
});
refreshZramSettings();
// 計劃zram寫回忧风,除非由persist.sys.zram_enabled禁用了zram
String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY);
if (!zramPropValue.equals("0")
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_zramWriteback)) {
ZramWriteback.scheduleZramWriteback(mContext);
}
// 響應(yīng)設(shè)置切換isolated-enable 的系統(tǒng)屬性
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
false /*notifyForDescendants*/,
new ContentObserver(null /* current thread */) {
@Override
public void onChange(boolean selfChange) {
refreshIsolatedStorageSettings();
}
});
// 在屬性更改時克隆屬性
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
mContext.getMainExecutor(), (properties) -> {
refreshIsolatedStorageSettings();
refreshFuseSettings();
});
refreshIsolatedStorageSettings();
}
3. bootCompleted
private void bootCompleted() {
mBootCompleted = true;
mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
updateFusePropFromSettings();
}
private void handleBootCompleted() {
// 與onStart部分調(diào)用一致
initIfBootedAndConnected();
resetIfBootedAndConnected();
}
小結(jié)
StorageManagerService與storaged和Vold服務(wù)建立鏈接,并持有了storaged和Vold的BP對象以進(jìn)行通信球凰。
StorageManagerService還設(shè)置Vold設(shè)置了Listener接收Vold回調(diào)過來的各類事件狮腿。
下文我將分析Vold部分代碼。