android版本:android-11.0.0_r21
http://aospxref.com/android-11.0.0_r21
概述:SystemServiceManager收到unlock事件后,遍歷service鏈表,執(zhí)行各個service的onUserUnlocking。對于存儲service,執(zhí)行的是StorageManagerService$Lifecycle中的onUserUnlocking,在這個方法中,存儲的StorageSessionController、vold、storaged模塊進行各自初始化操作。
一、SystemServiceManager處理unlock事件
設備解鎖后,loop線程處理unlock消息,最終會執(zhí)行到存儲的StorageManagerService$Lifecycle中的onUserUnlocking方法,整個流程如下:
loop() //android.os.Looper
|
|-->msg.target.dispatchMessage(msg) //android.os.Handler
|
|--mCallback.handleMessage(msg) //com.android.server.am.UserController
|
|--case USER_UNLOCK_MSG:
mInjector.getSystemServiceManager().unlockUser(userId) //com.android.server.SystemServiceManager
|
①|(zhì)--onUser(UNLOCKING, userHandle) //com.android.server.SystemServiceManager
|
②|--onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, userHandle) //com.android.server.SystemServiceManager
|
③|--onUser(t, onWhat, userHandle, UserHandle.USER_NULL) //com.android.server.SystemServiceManager
|
|--case UNLOCKING:
service.onUserUnlocking(curUser) //com.android.server.SystemService
|
|--onUnlockUser(user.getUserInfo()) //com.android.server.SystemService
|
|--onUnlockUser(userInfo.id) //com.android.server.StorageManagerService$Lifecycle
1)loop線程處理Android消息隊列中的消息和事件,從隊列中獲取事件,將unlock事件通知其他系統(tǒng)服務。
2)系統(tǒng)服務UserController管理用戶和用戶操作,接收到USER_UNLOCK_MSG消息后執(zhí)行SystemServiceManager中的unlockUser方法。
3)unlockUser方法經(jīng)過幾次轉(zhuǎn)換(①②③見下,只是做了參數(shù)轉(zhuǎn)換。參數(shù)差異見下)。
SystemServiceManager::(final @UserIdInt int userHandle)
-->?onUser(@NonNull String onWhat, @UserIdInt int userHandle) ①
-->?onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
? ? ? ? ? ? @UserIdInt int userHandle) ②
???????-->onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
? ? ? ? ? ? @UserIdInt int curUserId, @UserIdInt int prevUserId) ③
(如果未寫明方法所屬class,默認所屬class與前面相同,所以這些onUser方法都是SystemServiceManager類中實現(xiàn)的)
UserController收到USER_UNLOCK_MSG后的處理細節(jié)見其他文章。
最終③處的onUser會遍歷mServices鏈表,執(zhí)行各個service的?onUserUnlocking,簡化后的代碼如下:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java#onUser
//frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
@UserIdInt int curUserId, @UserIdInt int prevUserId) {
final TargetUser curUser = new TargetUser(getUserInfo(curUserId));
final int serviceLen = mServices.size();
// 遍歷系統(tǒng)服務,執(zhí)行每個servie的onUserUnlocking方法
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
final String serviceName = service.getClass().getName();
try {
switch (onWhat) {
case UNLOCKING:
service.onUserUnlocking(curUser); // ④,存儲的sevice是"StorageManagerService$Lifecycle"
break;
……
}
}
}
《android存儲2--初始化.存儲service的啟動》中“mount service”一節(jié)已經(jīng)闡述了StorageManagerService$Lifecycle發(fā)布的流程,所以上面代碼執(zhí)行for循環(huán)時,SystemService service = mServices.get(i)將會獲取到StorageManagerService$Lifecycle。在④處,service.onUserUnlocking(curUser)將會執(zhí)行StorageManagerService$Lifecycle中的onUserUnlocking方法。
二、存儲模塊處理unlock事件
2.1? StorageManagerService$Lifecycle::onUserUnlocking
StorageManagerService中定義了靜態(tài)內(nèi)部類StorageManagerService$Lifecycle,這個內(nèi)部類用來控制StorageManagerService的Lifecycle,代碼見下:http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#246
public class StorageManagerService extends IStorageManager.Stub
implements Watchdog.Monitor, ScreenObserver {
public static class Lifecycle extends SystemService {
protected StorageManagerService mStorageManagerService;
@Override
public void onUnlockUser(int userHandle) {
mStorageManagerService.onUnlockUser(userHandle);
}
……
}
}
從StorageManagerService$Lifecycle函數(shù)可知道:
- Lifecycle繼承自SystemService抽象類
- ???????子類Lifecycle覆寫了父類SystemService的onUnlockUser方法,但沒有覆寫onUserUnlocking
上文④處service.onUserUnlocking(curUser)調(diào)用的是父類SystemService::onUserUnlocking方法(因為StorageManagerService$Lifecycle沒有覆寫onUserUnlocking),見下。
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemService.java#onUserUnlocking
// SystemService類中的實現(xiàn)
public void onUserUnlocking(@NonNull TargetUser user) {
onUnlockUser(user.getUserInfo());
}
onUnlockUser(user.getUserInfo())執(zhí)行SystemService::onUnlockUser(@NonNull UserInfo userInfo)方法(注意重載參數(shù)類型)。
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/SystemService.java#onUnlockUser
// SystemService類中的實現(xiàn)
public void onUnlockUser(@NonNull UserInfo userInfo) {
onUnlockUser(userInfo.id);
}
onUnlockUser(userInfo.id)執(zhí)行的是被StorageManagerService$Lifecycle覆寫后的方法:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#onUnlockUser
//StorageManagerService$Lifecycle類中的實現(xiàn)
@Override
public void onUnlockUser(int userHandle) {
mStorageManagerService.onUnlockUser(userHandle);
}
mStorageManagerService.onUnlockUser代碼:
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#1162
//StorageManagerService類中的實現(xiàn)
1162 private void onUnlockUser(int userId) {
1163 Slog.d(TAG, "onUnlockUser " + userId);
1164
1165 // We purposefully block here to make sure that user-specific
1166 // staging area is ready so it's ready for zygote-forked apps to
1167 // bind mount against.
1168 try {
1169 mStorageSessionController.onUnlockUser(userId); // ⑤
1170 mVold.onUserStarted(userId); // ⑥
1171 mStoraged.onUserStarted(userId); // ⑦
1172 } catch (Exception e) {
1173 Slog.wtf(TAG, e);
1174 }
1175
1176 mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
1177 }
http://aospxref.com/android-11.0.0_r21/xref/frameworks/base/services/core/java/com/android/server/StorageManagerService.java#1162即StorageManagerService$Lifecycle中的onUserUnlocking方法最終執(zhí)行到StorageManagerService::onUnlockUser方法。⑤⑥⑦是存儲內(nèi)部各模塊處理unlock user后的邏輯,后面分段分析。
2.2??⑤處代碼mStorageSessionController.onUnlockUser分析
StorageManagerService::onUnlockUser中,mStorageManagerService.onUnlockUser執(zhí)行的是StorageSessionController::onUnlockUser:
// 初始化?mExternalStorageServiceComponent變量(ComponentName類型)
StorageManagerService::onUnlockUser
-->?StorageSessionController::initExternalStorageServiceComponent
mExternalStorageServiceComponent用于提供外部存儲服務,初始化后mExternalStorageServiceComponent的信息如下:
mExternalStorageServiceComponent.getPackageName()
值為:com.android.providers.media.module
mExternalStorageServiceComponent.getClassName()
值為:com.android.providers.media.fuse.ExternalStorageServiceImpl
ComponentName
值為:com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl
⑤處代碼很簡單,就是初始化了mExternalStorageServiceComponent變量。
附上mExternalStorageServiceComponent是何時使用的:
StorageSessionController::getExternalStorageServiceComponentName獲取mExternalStorageServiceComponent,即com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl。這個服務是在provider/media/fuse目錄實現(xiàn)的:
http://aospxref.com/android-11.0.0_r21/xref/packages/providers/MediaProvider/src/com/android/providers/media/fuse/
mExternalStorageServiceComponent在mount emulated 存儲時,用于連接ExternalStorageServiceImpl服務,流程如下:
StorageManagerService::mount
--> mStorageSessionController.onVolumeMount(pfd, vol) // StorageSessionController::onVolumeMount
// sessionId: emulated;0
// deviceFd代表的文件:/dev/fuse
// vol.getPath().getPath()對應upperPath,值為:/storage/emulated
// vol.getInternalPath().getPath()對應lowerPath,值為:/data/media
-->?connection.startSession(sessionId, deviceFd, vol.getPath().getPath(),
vol.getInternalPath().getPath()) // StorageUserConnection::startSession
// sessionId, upperPath, lowerPath封裝進session
--> session = new Session(sessionId, upperPath, lowerPath)
--> mActiveConnection.startSession(session, pfd) // StorageUserConnection$ActiveConnection::startSession
// fd代表的文件:/dev/fuse
--> waitForAsync((service, callback) -> service.startSession(session.sessionId,
FLAG_SESSION_TYPE_FUSE | FLAG_SESSION_ATTRIBUTE_INDEXABLE,
fd, session.upperPath, session.lowerPath, callback))
--> serviceFuture = connectIfNeeded()
//獲取外部存儲組件名稱com.android.providers.media.module/com.android.providers.media.fuse.ExternalStorageServiceImpl
--> name = mSessionController.getExternalStorageServiceComponentName()
--> mContext.bindServiceAsUser(new Intent().setComponent(name),
mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
mHandlerThread.getThreadHandler(),
UserHandle.of(mUserId))) // ContextImpl::bindServiceAsUser
--> bindServiceCommon(service, conn, flags, null, handler, null, user) // ContextImpl::bindServiceCommon
--> ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver())
MediaProvider::openFile -->?openFileCommon -->?openFileAndEnforcePathPermissionsHelper中:
// MediaProvider.java openFileAndEnforcePathPermissionsHelper函數(shù)
// 通過ExternalStorageServiceImpl.getFuseDaemon獲取daemon
daemon = getFuseDaemonForFile(file);
boolean shouldOpenWithFuse = daemon != null
&& daemon.shouldOpenWithFuse(filePath, true /* forRead */,
lowerFsFd.getFd());
if (SystemProperties.getBoolean(PROP_FUSE, false) && shouldOpenWithFuse) {
// 走fuse流程
pfd = FileUtils.openSafely(getFuseFile(file), modeBits);
try {
lowerFsFd.close();
}
} else {
// 繞過fuse,直接走底層文件系統(tǒng)
Log.i(TAG, "Using lower FS for " + filePath);
}
2.3? ⑥處代碼mVold.onUserStarted(userId)分析
StorageManagerService::onUnlockUser中,mVold.onUserStarted(userId)是核心代碼,比較復雜。這篇文章簡單說一下mVold.onUserStarted功能,它主要是為外部存儲創(chuàng)建、掛載相關目錄,以主用戶0為例,掛載視圖如下:
?注意,圖中⑦⑧⑨?處在代碼中bind mount掛載的分別是:
⑦:/mnt/runtime/default/emulated/0/Android/data??on? /mnt/user/0/emulated/0/Android/data
⑧:/mnt/runtime/default/emulated/0/Android/obb??on? /mnt/user/0/emulated/0/Android/obb
⑨:/mnt/runtime/write/emulated/0/Android/obb? on? /mnt/installer/0/emulated/0/Android/obb
?:/mnt/runtime/full/emulated??on? /mnt/pass_through/0/emulated
但mount命令看到的卻是/data/media目錄被bind mount到其他目錄:
/data/media on /mnt/user/0/emulated/0/Android/data?
/data/media on /mnt/user/0/emulated/0/Android/obb
……
流程在下一篇文章中講解。
2.4? StorageManagerService::onUnlockUser⑦處代碼mStoraged.onUserStarted(userId)分析
StorageManagerService::onUnlockUser中,mStoraged.onUserStarted(userId)功能比較簡單,為storaged加載/data/misc_ce/0/storaged.proto文件。
storaged周期地將統(tǒng)計結(jié)果寫入/data/misc_ce/0/storaged.proto(默認1小時更新一次,見DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO宏),這個文件按照system/core/storaged/storaged.proto格式編碼。執(zhí)行storaged -p命令時從/data/misc_ce/0/storaged.proto讀取數(shù)據(jù)輸出到終端上。示例如下:文章來源:http://www.zghlxwxcb.cn/news/detail-496915.html
cp15:/data/misc_ce/0/storaged # ls
storaged.proto
cp15:/data/misc_ce/0/storaged # storaged -p
I/O perf history (KB/s) : most_recent <--------- least_recent
last 24 hours : 66468 33941 44126 35316 45839 37312
last 7 days : 0 0 0 0 0 0 0
last 52 weeks : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
cp15:/data/misc_ce/0/storaged #
下一篇文章分析mVold.onUserStarted為外部存儲掛載目錄的流程。文章來源地址http://www.zghlxwxcb.cn/news/detail-496915.html
到了這里,關于android存儲3--初始化.unlock事件的處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!