首先我們要清楚總體可以分成如下幾種安裝的情況
- 系統(tǒng)開機(jī)的應(yīng)用安裝,安裝的是系統(tǒng)級別的應(yīng)用,用戶在沒有獲取到root權(quán)限的情況下無法卸載的應(yīng)用
- adb安裝的應(yīng)用,沒有安裝界面
- 第三方市場下載的應(yīng)用,此處要分情況,部分是通過電腦的客戶端安裝的沒有安裝的界面,部分是手機(jī)上的市場安裝的,會(huì)有安裝的界面
那么我們就對幾種情況一一分析它的安裝流程
開機(jī)安裝
-
首先在開機(jī)的時(shí)候systemServer會(huì)啟動(dòng)PackageMangerService來
具體是通過systemServer的main()->init1()->init2()->new ServerThread()->構(gòu)建PMS
以上都是SystemServer.cpp中的代碼,了解即可。我們前往PMS查看接下去的邏輯:在PMS的構(gòu)造方法中我們看到了一大坨的邏輯
,源碼過于長,我們直接在構(gòu)造方法里面搜索如下這兩個(gè)方法:
scanDirTracedLI //最后還是會(huì)調(diào)用下面的方法,只是對下面的方法做一下跟蹤
scanDirLI
就是通過這兩個(gè)方法進(jìn)行應(yīng)用的安裝,從scanDirLI開始追蹤:
private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {
final File[] files = dir.listFiles();
...
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
try {
scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
removeCodePathLI(file);
}
}
}
}
繼續(xù)看scanPackageTracedLI方法:
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}
我們看到從這個(gè)方法開始parsePackage, 通過PackageParser解析apk文件,我們可以去到PackageParser的文件中看到這個(gè)parsePackage方法就是把安裝包中的配置文件解析出來,并且保存到Package中返回出來,中間輾轉(zhuǎn)反側(cè)對于配置文件各種分情況進(jìn)行parse,最最主要的是parseBaseApkCommon方法,這個(gè)方法對manifast文件的標(biāo)簽進(jìn)行解析,而其中還調(diào)用了parseBaseApplication方法對application標(biāo)簽進(jìn)行解析。
然后再scanPackageLI->scanPackageDirtyLI,在后者的方法中,我們會(huì)把之前解析出來的
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProviders.addProvider(p);
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
mServices.addService(s);
等等,我們會(huì)把相應(yīng)的provider,service,receiver,activity全都保存到PMS的成員集合類中去.
至此系統(tǒng)應(yīng)用的安裝算是全部完成了,也許你會(huì)說我們并有看到什么install的什么方法,其實(shí)最最精髓的就是上面最后那一坨1000+行的方法,這里面把所有parser出來的信息全部保存到PMS中去了,而這就是所謂的安裝,安裝就是一個(gè)吧apk中的信息解析出來保存給PMS的過程,然后在launcher上生成一個(gè)圖標(biāo),以供用戶打開,僅此而已。
從網(wǎng)絡(luò)上下載應(yīng)用安裝
最終都是通過如下的方式去進(jìn)行安裝的
String fileName = "/mnt/usb/sda4/test.apk";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");
startActivity(intent);
啟動(dòng)的就是PackageInstallerActivity,而這個(gè)activity是Android的系統(tǒng)應(yīng)用之一,源碼在package/app/packageinstaller中,具體源碼可以前往下面鏈接查看:
https://github.com/android/platform_packages_apps_packageinstaller/blob/master/src/com/android/packageinstaller/PackageInstallerActivity.java
我們在其onCreate方法中看到之后會(huì)調(diào)用checkIfAllowedAndInitiateInstall->initiateInstall-> startInstallConfirm,會(huì)處理有關(guān)權(quán)限的一些問題
之后如果我們點(diǎn)擊下方的ok按鈕,會(huì)進(jìn)入到安裝流程:
public void onClick(View v) {
if (v == mOk) {
if (mOkCanInstall || mScrollView == null) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
clearCachedApkIfNeededAndFinish();
} else {
startInstall();
}
} else {
mScrollView.pageScroll(View.FOCUS_DOWN);
}
} else if (v == mCancel) {
...
}
我們接著去startInstall方法看:
private void startInstall() {
// Start subactivity to actually install the application
Intent newIntent = new Intent();
...
newIntent.setClass(this, InstallAppProgress.class);
...
startActivity(newIntent);
finish();
}
跳到InstallAppProgress這個(gè)activity,很明顯就是我們點(diǎn)擊安裝之后進(jìn)入的安裝界面,有個(gè)進(jìn)度條一直在閃的那個(gè)正在安裝的界面。
onCreate()->initView():
void initView() {
setContentView(R.layout.op_progress);
...
if ("package".equals(mPackageURI.getScheme())) {
try {
pm.installExistingPackage(mAppInfo.packageName);
onPackageInstalled(PackageInstaller.STATUS_SUCCESS);
} catch (PackageManager.NameNotFoundException e) {
onPackageInstalled(PackageInstaller.STATUS_FAILURE_INVALID);
}
} else {
...
mInstallHandler.post(new Runnable() {
@Override
public void run() {
doPackageStage(pm, params);
}
});
}
}
精簡了一下,主要是這兩個(gè)方法。
installExistingPackage
一個(gè)是pm.installExistingPackage,我們知道實(shí)際上調(diào)用的就是ApplicationPackageManager的installExistingPackage
@Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
return installExistingPackageAsUser(packageName, mContext.getUserId());
}
@Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
try {
int res = mPM.installExistingPackageAsUser(packageName, userId);
if (res == INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
return res;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
繼續(xù),我們前往PMS的installExistingPackageAsUser方法,具體方法不貼出,實(shí)際的意思就是這個(gè)安裝包已經(jīng)裝過了,只是當(dāng)前用戶下還沒有安裝,就會(huì)對后臺(tái)的設(shè)置做一下處理,實(shí)際并不涉及到安裝的東西的。我們來看另外一個(gè)方法
doPackageStage
private void doPackageStage(PackageManager pm, PackageInstaller.SessionParams params) {
final PackageInstaller packageInstaller = pm.getPackageInstaller();
PackageInstaller.Session session = null;
try {
session = packageInstaller.openSession(sessionId);
...
session.commit(pendingIntent.getIntentSender());
} catch (IOException e) {
onPackageInstalled(PackageInstaller.STATUS_FAILURE);
} finally {
IoUtils.closeQuietly(session);
}
}
當(dāng)中對session做了很多操作,我們只看最主要的最后一個(gè)session.commit,
- PackageInstaller.Session
這個(gè)session是在5.0之后新加進(jìn)來的一種安裝處理的方式,我們可以把它理解為一種記錄,就和瀏覽器中的session的作用是一樣的,它用來保存應(yīng)用安裝的所有信息,當(dāng)我們的手機(jī)如果因?yàn)楫惓V话惭b了一半退出了之后,當(dāng)我們下回再次打開手機(jī)的時(shí)候,可以繼續(xù)上次的安裝。
ok,我們接著進(jìn)到PackageInstaller.java看session的commit方法
public void commit(@NonNull IntentSender statusReceiver) {
try {
mSession.commit(statusReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
這里的mSession我們看到是
private IPackageInstallerSession mSession;
/** {@hide} */
public Session(IPackageInstallerSession session) {
mSession = session;
}
萬惡的binder,回到上面看session的定義:
session = packageInstaller.openSession(sessionId);
找openSession方法
public @NonNull Session openSession(int sessionId) throws IOException {
try {
return new Session(mInstaller.openSession(sessionId));
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
mInstaller是什么,
private final IPackageInstaller mInstaller;
又來一個(gè)binder,我們就不繼續(xù)一步一步貼了,相信讀者也可以自己找到最終的實(shí)現(xiàn)是在PackageInstallerSession
@Override
public void commit(IntentSender statusReceiver) {
...
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
}
省去部分直接看到最后給handler發(fā)了條消息
mHandler = new Handler(looper, mHandlerCallback);
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// Cache package manager data without the lock held
final PackageInfo pkgInfo = mPm.getPackageInfo(
params.appPackageName, PackageManager.GET_SIGNATURES /*flags*/, userId);
final ApplicationInfo appInfo = mPm.getApplicationInfo(
params.appPackageName, 0, userId);
synchronized (mLock) {
if (msg.obj != null) {
mRemoteObserver = (IPackageInstallObserver2) msg.obj;
}
try {
commitLocked(pkgInfo, appInfo);
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);
}
return true;
}
}
};
重要的就是那句commitLocked,這個(gè)方法比較長,依然是做一些權(quán)限和配置方面的事情,能在方法的最后看到
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
installerPackageName, installerUid, user, mCertificates);
我們?nèi)サ絇MS的installStage方法:
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
Certificate[][] certificates) {
...
final Message msg = mHandler.obtainMessage(INIT_COPY);
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
sessionParams.grantedRuntimePermissions, certificates);
...
msg.obj = params;
...
mHandler.sendMessage(msg);
}
我們把整個(gè)過程精簡到上面三局代碼,發(fā)送一個(gè)what為INIT_COPY的消息
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
// 此處為了連接服務(wù),初始情況都為false,待服務(wù)臉上之后就會(huì)把mBound設(shè)置為true,就可以進(jìn)入下面條件
// 因此這里我們直接進(jìn)入else的條件
if (!mBound) {
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
// If this is the only one pending we might
// have to bind to the service again.
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
System.identityHashCode(mHandler));
if (params.traceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
params.traceCookie);
}
return;
} else {
// Once we bind to the service, the first
// pending request will be processed.
mPendingInstalls.add(idx, params);
}
} else {
mPendingInstalls.add(idx, params);
// Already bound to the service. Just make
// sure we trigger off processing the first request.
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
直接在最后看到發(fā)送了MCS_BOUND消息
case MCS_BOUND: {
...
//服務(wù)已經(jīng)連上,直接跳到else if
if (mContainerService == null) {
...
}
//等待安裝的隊(duì)列肯定大于0
else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
//開始進(jìn)入到copy
if (params.startCopy()) {
// We are done... look for more work or to
// go idle.
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Checking for more work or unbind...");
// Delete pending install
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
//如果已經(jīng)把要安裝的都處理完了,那么久斷開服務(wù)連接
//否則就再發(fā)送一個(gè)MCS_BOUND信息,繼續(xù)循環(huán)處理
if (mPendingInstalls.size() == 0) {
if (mBound) {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
// Unbind after a little delay, to avoid
// continual thrashing.
sendMessageDelayed(ubmsg, 10000);
}
} else {
// There are more pending requests in queue.
// Just post MCS_BOUND message to trigger processing
// of next pending install.
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting MCS_BOUND for next work");
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
} else {
// Should never happen ideally.
Slog.w(TAG, "Empty queue");
}
break;
}
我們直接進(jìn)入到startCopy
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
//嘗試的次數(shù)超過了最大嘗試次數(shù),就宣告失敗
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
} else {
//開始進(jìn)行拷貝
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
//處理return code
handleReturnCode();
return res;
}
我們先來看一下handleStartCopy方法,發(fā)現(xiàn)時(shí)抽象方法,具體的實(shí)現(xiàn),我們網(wǎng)上可以找到是 InstallParams。
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
// 決定是安裝在手機(jī)內(nèi)還是sdcard中,設(shè)置對應(yīng)標(biāo)志位
if (origin.staged) {
if (origin.file != null) {
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
} else if (origin.cid != null) {
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else {
throw new IllegalStateException("Invalid stage location");
}
}
...
// 檢查APK的安裝位置是否正確
if (onInt && onSd) {
// Check if both bits are set.
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (onSd && ephemeral) {
Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
...
}
...
// createInstallArgs用于創(chuàng)建一個(gè)安裝參數(shù)對象
final InstallArgs args = createInstallArgs(this);
if (ret == PackageManager.INSTALL_SUCCEEDED) {
...
// 調(diào)用InstallArgs的copyApk函數(shù)
ret = args.copyApk(mContainerService, true);
}
}
mRet = ret;
}
主要工作就是復(fù)制apk消息到指定位置
再來看handleReturnCode
void handleReturnCode() {
// If mArgs is null, then MCS couldn't be reached. When it
// reconnects, it will try again to install. At that point, this
// will succeed.
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
我們一路看,processPendingInstall()->installPackageTracedLI()->installPackageLI(),整個(gè)方法比較長,主要做了清單文件解析和獲取證書,提取簽名的工作,你可以從這個(gè)方法中找到如下代碼段,就是這段代碼處理了安裝
try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
"installPackageLI")) {
if (replace) {
// 4.更新已經(jīng)存在的packages
replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res);
} else {
// 5.安裝新的packages
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res);
}
}
我們繼續(xù)
/*
* Install a non-existing package.
*/
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res) {
...
try {
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, null, res, user);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage);
} else {
// Remove package from internal structures, but keep around any
// data that might have already existed
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
...
}
經(jīng)過刪減省略,我們看到了我們熟悉的方法scanPackageTracedLI,再具體的步驟見上面系統(tǒng)應(yīng)用安裝。
最后我們再來看一下另外一種ADB的安裝
adb安裝
當(dāng)我們在在命令行窗口輸入adb install的時(shí)候?qū)嶋H上,系統(tǒng)會(huì)幫我們運(yùn)行如下的程序
db_commandline
install_app_legacy or install_app
pm_command
send_shell_command
Pm.runInstall()
這個(gè)過程會(huì)把a(bǔ)pk文件copy到data/local/tmp/目錄下,然后向shell服務(wù)發(fā)送pm命令安裝apk,最后調(diào)用Pm.runInstall()方法來安裝apk。
我們可以看到這個(gè)方法:
private int runInstall() throws RemoteException {
...
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);
try {
if (inPath == null && params.sessionParams.sizeBytes == 0) {
System.err.println("Error: must either specify a package size or an APK file");
return 1;
}
if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
if (doCommitSession(sessionId, false /*logSuccess*/)
!= PackageInstaller.STATUS_SUCCESS) {
return 1;
}
System.out.println("Success");
return 0;
} finally {
try {
mInstaller.abandonSession(sessionId);
} catch (Exception ignore) {
}
}
}
我們依然省略著看,把上面這一段略去,直接在最下面看到三個(gè)重要的方法,doCreateSession,doWriteSession,doCommitSession,直接點(diǎn)開最后一個(gè)
private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
PackageInstaller.Session session = null;
try {
session = new PackageInstaller.Session(
mInstaller.openSession(sessionId));
final LocalIntentReceiver receiver = new LocalIntentReceiver();
session.commit(receiver.getIntentSender());
final Intent result = receiver.getResult();
final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
if (logSuccess) {
System.out.println("Success");
}
} else {
System.err.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
}
return status;
} finally {
IoUtils.closeQuietly(session);
}
}
看到熟悉的session.commit了么,
總結(jié)
下面是有安裝界面的app安裝流程,中途插入adb install以及沒有安裝界面的系統(tǒng)安裝。
- PackageInstallerActivity的onCreate();
- 根據(jù)從Intent中獲取的Data的scheme的不同,調(diào)用不同的處理邏輯安裝App;
- 解析App文件到Package對象;
- initInstall()函數(shù)獲取apk中的權(quán)限信息;
- onClick()監(jiān)聽用戶點(diǎn)擊同意安裝按鈕;
- 啟動(dòng)InstallAppProcess Activity;
- onCrete()函數(shù)調(diào)用
- initView()函數(shù);
- 繼續(xù)調(diào)用doPackageStage()函數(shù),做session.commit();
此處插入adb install 1.Pm.runInstall() 2.Pm.doCommitSession() - 通過Handler機(jī)制啟動(dòng)了startCopy()函數(shù);
- startCopy()調(diào)用了啟動(dòng)了handlerStartCopy()將apk拷貝到/data/app、pkg-name/和把.so文件拷貝到/data/app/pkg-name/lib/的
- handlerReturnCode()函數(shù);
- handlerReturnCode調(diào)用了installPackageLI()函數(shù);
- 在installPackageLI()中,首先調(diào)用了collectCertificates()函數(shù)對apk的簽名做了校驗(yàn),確保apk沒有被非法修改(修改其中的文件);
接著,調(diào)用collectManifestDigest()函數(shù)計(jì)算了Manifest.xml的文件摘要,并且存在了Package的manifestDigest成員下;
接著,將從apk文件中提提取的manifest計(jì)算摘要和之前installer解析到的進(jìn)行比較,若不匹配,則拋出異常。
然后,對App升級或者使用了共享屬性sharedUid的情況校驗(yàn)待安裝的App的證書是否匹配,并就升級方式做了具體處理,這里有兩個(gè)問題,就是升級過程中的Upgrade keysets升級方式和Signature[]的獲得不明朗。 - 根據(jù)是升級App還是安裝新App,調(diào)用不同的函數(shù)進(jìn)行處理環(huán)節(jié)。
此處插入系統(tǒng)應(yīng)用安裝 1.scanPackageTracedLI 2.scanPackageLI 3.scanPackageDirtyLI - 最后在scanPackageDirtyLI方法中,把所有的provider,service,receiver,activity從parser中拿出來保存到PMS中。