成為一名優(yōu)秀的Android開(kāi)發(fā)劣像,需要一份完備的知識(shí)體系,在這里晾虑,讓我們一起成長(zhǎng)為自己所想的那樣~挥唠。
前言
PMS的創(chuàng)建過(guò)程分為兩個(gè)部分進(jìn)行講解够掠,分別是SyetemServer處理部分和PMS構(gòu)造方法忠聚。其中SyetemServer處理部分和AMS和WMS的創(chuàng)建過(guò)程是類似的,可以將它們進(jìn)行對(duì)比柳弄,這樣可以更好的理解和記憶這一知識(shí)點(diǎn)舶胀。
1. SyetemServer處理部分
PMS是在SyetemServer進(jìn)程中被創(chuàng)建的,SyetemServer進(jìn)程用來(lái)創(chuàng)建系統(tǒng)服務(wù)碧注,不了解它的可以查看Android系統(tǒng)啟動(dòng)流程(三)解析SyetemServer進(jìn)程啟動(dòng)過(guò)程這篇文章嚣伐。 從SyetemServer的入口方法main方法開(kāi)始講起,如下所示萍丐。 frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
復(fù)制代碼
main方法中只調(diào)用了SystemServer的run方法轩端,如下所示。 frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
try {
...
//創(chuàng)建消息Looper
Looper.prepareMainLooper();
//加載了動(dòng)態(tài)庫(kù)libandroid_servers.so
System.loadLibrary("android_servers");//1
performPendingShutdown();
// 創(chuàng)建系統(tǒng)的Context
createSystemContext();
// 創(chuàng)建SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
SystemServerInitThreadPool.get();
} finally {
traceEnd();
}
try {
traceBeginAndSlog("StartServices");
//啟動(dòng)引導(dǎo)服務(wù)
startBootstrapServices();//3
//啟動(dòng)核心服務(wù)
startCoreServices();//4
//啟動(dòng)其他服務(wù)
startOtherServices();//5
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
}
復(fù)制代碼
在注釋1處加載了動(dòng)態(tài)庫(kù)libandroid_servers.so逝变。接下來(lái)在注釋2處創(chuàng)建SystemServiceManager基茵,它會(huì)對(duì)系統(tǒng)的服務(wù)進(jìn)行創(chuàng)建、啟動(dòng)和生命周期管理壳影。在注釋3中的startBootstrapServices方法中用SystemServiceManager啟動(dòng)了ActivityManagerService拱层、PowerManagerService、PackageManagerService等服務(wù)宴咧。在注釋4處的startCoreServices方法中則啟動(dòng)了DropBoxManagerService根灯、BatteryService、UsageStatsService和WebViewUpdateService悠汽。注釋5處的startOtherServices方法中啟動(dòng)了CameraService、AlarmManagerService芥驳、VrManagerService等服務(wù)柿冲。這些服務(wù)的父類均為SystemService。從注釋3兆旬、4假抄、5的方法可以看出,官方把系統(tǒng)服務(wù)分為了三種類型丽猬,分別是引導(dǎo)服務(wù)宿饱、核心服務(wù)和其他服務(wù),其中其他服務(wù)是一些非緊要和一些不需要立即啟動(dòng)的服務(wù)脚祟。這些系統(tǒng)服務(wù)總共有100多個(gè)谬以,我們熟知的AMS屬于引導(dǎo)服務(wù),WMS屬于其他服務(wù)由桌, 本文要講的PMS屬于引導(dǎo)服務(wù)为黎,因此這里列出引導(dǎo)服務(wù)以及它們的作用邮丰,見(jiàn)下表。
引導(dǎo)服務(wù) | 作用 |
---|---|
Installer | 系統(tǒng)安裝apk時(shí)的一個(gè)服務(wù)類铭乾,啟動(dòng)完成Installer服務(wù)之后才能啟動(dòng)其他的系統(tǒng)服務(wù) |
ActivityManagerService | 負(fù)責(zé)四大組件的啟動(dòng)剪廉、切換、調(diào)度炕檩。 |
PowerManagerService | 計(jì)算系統(tǒng)中和Power相關(guān)的計(jì)算斗蒋,然后決策系統(tǒng)應(yīng)該如何反應(yīng) |
LightsService | 管理和顯示背光LED |
DisplayManagerService | 用來(lái)管理所有顯示設(shè)備 |
UserManagerService | 多用戶模式管理 |
SensorService | 為系統(tǒng)提供各種感應(yīng)器服務(wù) |
PackageManagerService | 用來(lái)對(duì)apk進(jìn)行安裝、解析笛质、刪除泉沾、卸載等等操作 |
查看啟動(dòng)引導(dǎo)服務(wù)的注釋3處的startBootstrapServices方法。 frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
...
traceBeginAndSlog("StartPackageManagerService");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);//1
mFirstBoot = mPackageManagerService.isFirstBoot();//2
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
...
}
復(fù)制代碼
注釋1處的PMS的main方法主要用來(lái)創(chuàng)建PMS经瓷,其中最后一個(gè)參數(shù)mOnlyCore代表是否只掃描系統(tǒng)的目錄爆哑,它在本篇文章中會(huì)出現(xiàn)多次,一般情況下它的值為false舆吮。注釋2處獲取boolean類型的變量mFirstBoot揭朝,它用于表示PMS是否首次被啟動(dòng)。mFirstBoot是后續(xù)WMS創(chuàng)建時(shí)所需要的參數(shù)色冀,從這里就可以看出系統(tǒng)服務(wù)之間是有依賴關(guān)系的潭袱,它們的啟動(dòng)順序不能隨意被更改。
2. PMS構(gòu)造方法
PMS的main方法如下所示锋恬。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerServiceCompilerMapping.checkProperties();
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
return m;
}
復(fù)制代碼
main方法主要做了兩件事屯换,一個(gè)是創(chuàng)建PMS對(duì)象,另一個(gè)是將PMS注冊(cè)到ServiceManager中与学。 PMS的構(gòu)造方法大概有600多行彤悔,分為5個(gè)階段,每個(gè)階段會(huì)打印出相應(yīng)的EventLog索守,EventLog用于打印Android系統(tǒng)的事件日志晕窑。
- BOOT_PROGRESS_PMS_START(開(kāi)始階段)
- BOOT_PROGRESS_PMS_SYSTEM_SCAN_START(掃描系統(tǒng)階段)
- BOOT_PROGRESS_PMS_DATA_SCAN_START(掃描Data分區(qū)階段)
- BOOT_PROGRESS_PMS_SCAN_END(掃描結(jié)束階段)
- BOOT_PROGRESS_PMS_READY(準(zhǔn)備階段)
2.1 開(kāi)始階段
PMS的構(gòu)造方法中會(huì)獲取一些包管理需要屬性,如下所示卵佛。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
//打印開(kāi)始階段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis())
...
//用于存儲(chǔ)屏幕的相關(guān)信息
mMetrics = new DisplayMetrics();
//Settings用于保存所有包的動(dòng)態(tài)設(shè)置
mSettings = new Settings(mPackages);
//在Settings中添加多個(gè)默認(rèn)的sharedUserId
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);//1
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
...
mInstaller = installer;
//創(chuàng)建Dex優(yōu)化工具類
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
FgThread.get().getLooper());
getDefaultDisplayMetrics(context, mMetrics);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
//得到全局系統(tǒng)配置信息杨赤。
SystemConfig systemConfig = SystemConfig.getInstance();
//獲取全局的groupId
mGlobalGids = systemConfig.getGlobalGids();
//獲取系統(tǒng)權(quán)限
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mProtectedPackages = new ProtectedPackages(mContext);
//安裝APK時(shí)需要的鎖,保護(hù)所有對(duì)installd的訪問(wèn)截汪。
synchronized (mInstallLock) {//1
//更新APK時(shí)需要的鎖疾牲,保護(hù)內(nèi)存中已經(jīng)解析的包信息等內(nèi)容
synchronized (mPackages) {//2
//創(chuàng)建后臺(tái)線程ServiceThread
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//創(chuàng)建PackageHandler綁定到ServiceThread的消息隊(duì)列
mHandler = new PackageHandler(mHandlerThread.getLooper());//3
mProcessLoggingHandler = new ProcessLoggingHandler();
//將PackageHandler添加到Watchdog的檢測(cè)集中
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);//4
mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
mInstantAppRegistry = new InstantAppRegistry(this);
//在Data分區(qū)創(chuàng)建一些目錄
File dataDir = Environment.getDataDirectory();//5
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
//創(chuàng)建多用戶管理服務(wù)
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
...
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false))//6
...
}
復(fù)制代碼
在開(kāi)始階段中創(chuàng)建了很多PMS中的關(guān)鍵對(duì)象并賦值給PMS中的成員變量,下面簡(jiǎn)單介紹這些成員變量衙解。
- mSettings :用于保存所有包的動(dòng)態(tài)設(shè)置阳柔。注釋1處將系統(tǒng)進(jìn)程的sharedUserId添加到Settings中,sharedUserId用于進(jìn)程間共享數(shù)據(jù)蚓峦,比如兩個(gè)App的之間的數(shù)據(jù)是不共享的盔沫,如果它們有了共同的sharedUserId医咨,就可以運(yùn)行在同一個(gè)進(jìn)程中共享數(shù)據(jù)。
- mInstaller :Installer繼承自SystemService架诞,和PMS拟淮、AMS一樣是系統(tǒng)的服務(wù)(雖然名稱不像是服務(wù)),PMS很多的操作都是由Installer來(lái)完成的谴忧,比如APK的安裝和卸載很泊。在Installer內(nèi)部,通過(guò)IInstalld和installd進(jìn)行Binder通信沾谓,由位于nativie層的installd來(lái)完成具體的操作委造。
- systemConfig:用于得到全局系統(tǒng)配置信息。比如系統(tǒng)的權(quán)限就可以通過(guò)SystemConfig來(lái)獲取均驶。
- mPackageDexOptimizer : Dex優(yōu)化的工具類昏兆。
- mHandler(PackageHandler類型) :PackageHandler繼承自Handler,在注釋3處它綁定了后臺(tái)線程ServiceThread的消息隊(duì)列妇穴。PMS通過(guò)PackageHandler驅(qū)動(dòng)APK的復(fù)制和安裝工作爬虱,具體的請(qǐng)看在Android包管理機(jī)制(三)PMS處理APK的安裝這篇文章。 PackageHandler處理的消息隊(duì)列如果過(guò)于繁忙腾它,有可能導(dǎo)致系統(tǒng)卡住跑筝, 因此在注釋4處將它添加到Watchdog的監(jiān)測(cè)集中。 Watchdog主要有兩個(gè)用途瞒滴,一個(gè)是定時(shí)檢測(cè)系統(tǒng)關(guān)鍵服務(wù)(AMS和WMS等)是否可能發(fā)生死鎖曲梗,還有一個(gè)是定時(shí)檢測(cè)線程的消息隊(duì)列是否長(zhǎng)時(shí)間處于工作狀態(tài)(可能阻塞等待了很長(zhǎng)時(shí)間)。如果出現(xiàn)上述問(wèn)題妓忍,Watchdog會(huì)將日志保存起來(lái)虏两,必要時(shí)還會(huì)殺掉自己所在的進(jìn)程,也就是SystemServer進(jìn)程世剖。
- sUserManager(UserManagerService類型) :多用戶管理服務(wù)定罢。
除了創(chuàng)建這些關(guān)鍵對(duì)象,在開(kāi)始階段還有一些關(guān)鍵代碼需要去講解:
- 注釋1處和注釋2處加了兩個(gè)鎖搁廓,其中mInstallLock是安裝APK時(shí)需要的鎖引颈,保護(hù)所有對(duì)installd的訪問(wèn)耕皮;mPackages是更新APK時(shí)需要的鎖境蜕,保護(hù)內(nèi)存中已經(jīng)解析的包信息等內(nèi)容。
- 注釋5處后的代碼創(chuàng)建了一些Data分區(qū)中的子目錄凌停,比如/data/app粱年。
- 注釋6處會(huì)解析packages.xml等文件的信息,保存到Settings的對(duì)應(yīng)字段中罚拟。packages.xml中記錄系統(tǒng)中所有安裝的應(yīng)用信息台诗,包括基本信息完箩、簽名和權(quán)限。如果packages.xml有安裝的應(yīng)用信息拉队,那么注釋6處Settings的readLPw方法會(huì)返回true弊知,mFirstBoot的值為false,說(shuō)明PMS不是首次被啟動(dòng)粱快。
2.2 掃描系統(tǒng)階段
...
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
//打印掃描系統(tǒng)階段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
...
//在/system中創(chuàng)建framework目錄
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
...
//掃描/vendor/overlay目錄下的文件
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
//掃描/system/framework 目錄下的文件
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
//掃描 /system/priv-app 目錄下的文件
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
//掃描/system/app 目錄下的文件
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
//掃描 /vendor/app 目錄下的文件
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//掃描/oem/app 目錄下的文件
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//這個(gè)列表代表有可能有升級(jí)包的系統(tǒng)App
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();//1
if (!mOnlyCore) {
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
//這里的mPackages的是PMS的成員變量秩彤,代表scanDirTracedLI方法掃描上面那些目錄得到的
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {//2
...
//將這個(gè)系統(tǒng)App的PackageSetting從PMS的mPackages中移除
removePackageLI(scannedPkg, true);
//將升級(jí)包的路徑添加到mExpectingBetter列表中
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
...
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
//這個(gè)系統(tǒng)App升級(jí)包信息在mDisabledSysPackages中,但是沒(méi)有發(fā)現(xiàn)這個(gè)升級(jí)包存在
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {//5
possiblyDeletedUpdatedSystemApps.add(ps.name);//
}
}
}
}
...
}
復(fù)制代碼
/system可以稱作為System分區(qū),里面主要存儲(chǔ)谷歌和其他廠商提供的Android系統(tǒng)相關(guān)文件和框架事哭。Android系統(tǒng)架構(gòu)分為應(yīng)用層漫雷、應(yīng)用框架層、系統(tǒng)運(yùn)行庫(kù)層(Native 層)鳍咱、硬件抽象層(HAL層)和Linux內(nèi)核層降盹,除了Linux內(nèi)核層在Boot分區(qū),其他層的代碼都在System分區(qū)谤辜。下面列出 System分區(qū)的部分子目錄蓄坏。
目錄 | 含義 |
---|---|
app | 存放系統(tǒng)App,包括了谷歌內(nèi)置的App也有廠商或者運(yùn)營(yíng)商提供的App |
framework | 存放應(yīng)用框架層的jar包 |
priv-app | 存放特權(quán)App |
lib | 存放so文件 |
fonts | 存放系統(tǒng)字體文件 |
media | 存放系統(tǒng)的各種聲音每辟,比如鈴聲剑辫、提示音,以及系統(tǒng)啟動(dòng)播放的動(dòng)畫 |
上面的代碼還涉及到/vendor 目錄渠欺,它用來(lái)存儲(chǔ)廠商對(duì)Android系統(tǒng)的定制部分妹蔽。
系統(tǒng)掃描階段的主要工作有以下3點(diǎn):
- 創(chuàng)建/system的子目錄,比如/system/framework挠将、/system/priv-app和/system/app等等
- 掃描系統(tǒng)文件胳岂,比如/vendor/overlay、/system/framework舔稀、/system/app等等目錄下的文件乳丰。
- 對(duì)掃描到的系統(tǒng)文件做后續(xù)處理。
主要來(lái)說(shuō)第3點(diǎn)内贮,一次OTA升級(jí)對(duì)于一個(gè)系統(tǒng)App會(huì)有三種情況:
- 這個(gè)系統(tǒng)APP無(wú)更新产园。
- 這個(gè)系統(tǒng)APP有更新。
- 新的OTA版本中夜郁,這個(gè)系統(tǒng)APP已經(jīng)被刪除什燕。
當(dāng)系統(tǒng)App升級(jí),PMS會(huì)將該系統(tǒng)App的升級(jí)包設(shè)置數(shù)據(jù)(PackageSetting)存儲(chǔ)到Settings的mDisabledSysPackages列表中(具體見(jiàn)PMS的replaceSystemPackageLIF方法)竞端,mDisabledSysPackages的類型為ArrayMap<String, PackageSetting>
屎即。mDisabledSysPackages中的信息會(huì)被PMS保存到packages.xml中的<updated-package>
標(biāo)簽下(具體見(jiàn)Settings的writeDisabledSysPackageLPr方法)。 注釋2處說(shuō)明這個(gè)系統(tǒng)App有升級(jí)包,那么就將該系統(tǒng)App的PackageSetting從mDisabledSysPackages列表中移除技俐,并將系統(tǒng)App的升級(jí)包的路徑添加到mExpectingBetter列表中乘陪,mExpectingBetter的類型為ArrayMap<String, File>
等待后續(xù)處理。 注釋5處如果這個(gè)系統(tǒng)App的升級(jí)包信息存儲(chǔ)在mDisabledSysPackages列表中雕擂,但是沒(méi)有發(fā)現(xiàn)這個(gè)升級(jí)包存在啡邑,則將它加入到possiblyDeletedUpdatedSystemApps列表中,意為“系統(tǒng)App的升級(jí)包可能被刪除”井赌,之所以是“可能”谣拣,是因?yàn)橄到y(tǒng)還沒(méi)有掃描Data分區(qū),只能暫放到possiblyDeletedUpdatedSystemApps列表中族展,等到掃描完Data分區(qū)后再做處理森缠。
2.3 掃描Data分區(qū)階段
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
...
mSettings.pruneSharedUsersLPw();
//如果不是只掃描系統(tǒng)的目錄,那么就開(kāi)始掃描Data分區(qū)仪缸。
if (!mOnlyCore) {
//打印掃描Data分區(qū)階段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
//掃描/data/app目錄下的文件
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
//掃描/data/app-private目錄下的文件
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
//掃描完Data分區(qū)后贵涵,處理possiblyDeletedUpdatedSystemApps列表
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
// 從mSettings.mDisabledSysPackages變量中移除去此應(yīng)用
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
String msg;
//1:如果這個(gè)系統(tǒng)App的包信息不在PMS的變量mPackages中,說(shuō)明是殘留的App信息恰画,后續(xù)會(huì)刪除它的數(shù)據(jù)宾茂。
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; it's data will be wiped";
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
//2:如果這個(gè)系統(tǒng)App在mPackages中,說(shuō)明是存在于Data分區(qū)拴还,不屬于系統(tǒng)App跨晴,那么移除其系統(tǒng)權(quán)限。
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
+ deletedAppName;
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
logCriticalInfo(Log.WARN, msg);
}
//遍歷mExpectingBetter列表
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
//得到系統(tǒng)App的升級(jí)包路徑
final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");
int reparseFlags = mDefParseFlags;
//3:根據(jù)系統(tǒng)App所在的目錄設(shè)置掃描的解析參數(shù)
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
}
...
//將packageName對(duì)應(yīng)的包設(shè)置數(shù)據(jù)(PackageSetting)添加到mSettings的mPackages中
mSettings.enableSystemPackageLPw(packageName);//4
try {
//掃描系統(tǒng)App的升級(jí)包
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);//5
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
}
//清除mExpectingBetter列表
mExpectingBetter.clear();
...
}
復(fù)制代碼
/data可以稱為Data分區(qū)片林,它用來(lái)存儲(chǔ)所有用戶的個(gè)人數(shù)據(jù)和配置文件端盆。下面列出Data分區(qū)部分子目錄:
目錄 | 含義 |
---|---|
app | 存儲(chǔ)用戶自己安裝的App |
data | 存儲(chǔ)所有已安裝的App數(shù)據(jù)的目錄,每個(gè)App都有自己?jiǎn)为?dú)的子目錄 |
app-private | App的私有存儲(chǔ)空間 |
app-lib | 存儲(chǔ)所有App的Jni庫(kù) |
system | 存放系統(tǒng)配置文件 |
anr | 用于存儲(chǔ)ANR發(fā)生時(shí)系統(tǒng)生成的traces.txt文件 |
掃描Data分區(qū)階段主要做了以下幾件事:
- 掃描/data/app和/data/app-private目錄下的文件。
- 遍歷possiblyDeletedUpdatedSystemApps列表,注釋1處如果這個(gè)系統(tǒng)App的包信息不在PMS的變量mPackages中一膨,說(shuō)明是殘留的App信息,后續(xù)會(huì)刪除它的數(shù)據(jù)盖呼。注釋2處如果這個(gè)系統(tǒng)App的包信息在mPackages中,說(shuō)明是存在于Data分區(qū),不屬于系統(tǒng)App,那么移除其系統(tǒng)權(quán)限末患。
- 遍歷mExpectingBetter列表,注釋3處根據(jù)系統(tǒng)App所在的目錄設(shè)置掃描的解析參數(shù)锤窑,注釋4處的方法內(nèi)部會(huì)將packageName對(duì)應(yīng)的包設(shè)置數(shù)據(jù)(PackageSetting)添加到mSettings的mPackages中璧针。注釋5處掃描系統(tǒng)App的升級(jí)包,最后清除mExpectingBetter列表果复。
2.4 掃描結(jié)束階段
//打印掃描結(jié)束階段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
int updateFlags = UPDATE_PERMISSIONS_ALL;
// 如果當(dāng)前平臺(tái)SDK版本和上次啟動(dòng)時(shí)的SDK版本不同陈莽,重新更新APK的授權(quán)
if (ver.sdkVersion != mSdkVersion) {
Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
+ mSdkVersion + "; regranting permissions for internal storage");
updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
}
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
//如果是第一次啟動(dòng)或者是Android M升級(jí)后的第一次啟動(dòng)渤昌,需要初始化所有用戶定義的默認(rèn)首選App
if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
...
//OTA后的第一次啟動(dòng)虽抄,會(huì)清除代碼緩存目錄走搁。
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}
...
// 把Settings的內(nèi)容保存到packages.xml中
mSettings.writeLPr();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
復(fù)制代碼
掃描結(jié)束結(jié)束階段主要做了以下幾件事:
- 如果當(dāng)前平臺(tái)SDK版本和上次啟動(dòng)時(shí)的SDK版本不同,重新更新APK的授權(quán)迈窟。
- 如果是第一次啟動(dòng)或者是Android M升級(jí)后的第一次啟動(dòng)私植,需要初始化所有用戶定義的默認(rèn)首選App。
- OTA升級(jí)后的第一次啟動(dòng)车酣,會(huì)清除代碼緩存目錄曲稼。
- 把Settings的內(nèi)容保存到packages.xml中,這樣此后PMS再次創(chuàng)建時(shí)會(huì)讀到此前保存的Settings的內(nèi)容湖员。
2.5 準(zhǔn)備階段
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
...
mInstallerService = new PackageInstallerService(context, this);//1
...
Runtime.getRuntime().gc();//2
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mInstaller.setWarnIfHeld(mPackages);
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());//3
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
復(fù)制代碼
注釋1處創(chuàng)建PackageInstallerService贫悄,PackageInstallerService是用于管理安裝會(huì)話的服務(wù),它會(huì)為每次安裝過(guò)程分配一個(gè)SessionId娘摔,在Android包管理機(jī)制(二)PackageInstaller安裝APK這篇文章中提到過(guò)PackageInstallerService窄坦。 注釋2處進(jìn)行一次垃圾收集。注釋3處將PackageManagerInternalImpl(PackageManager的本地服務(wù))添加到LocalServices中凳寺, LocalServices用于存儲(chǔ)運(yùn)行在當(dāng)前的進(jìn)程中的本地服務(wù)鸭津。
3. 總結(jié)
本篇文章介紹了PMS的創(chuàng)建過(guò)程,分為兩個(gè)部分肠缨,分別是SyetemServer處理部分和PMS構(gòu)造方法逆趋,PMS構(gòu)造方法又分為5個(gè)部分,分別是開(kāi)始階段晒奕、掃描系統(tǒng)階段闻书、掃描Data分區(qū)階段、掃描結(jié)束階段和準(zhǔn)備階段脑慧。
作者:劉望舒
鏈接:https://juejin.cn/post/6844903649408188429
來(lái)源:掘金
著作權(quán)歸作者所有惠窄。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處漾橙。