1、adb install xxx
會(huì)響應(yīng)到adb_commandline碘赖,本文重點(diǎn)講解單個(gè)app安裝install_app
// system/core/adb/client/commandline.cpp
int adb_commandline(int argc, const char** argv) {
...
} else if (!strcmp(argv[0], "install")) {
if (argc < 2) error_exit("install requires an argument");
return install_app(argc, argv); // 安裝單個(gè)應(yīng)用驾荣,本文重點(diǎn)講解
} else if (!strcmp(argv[0], "install-multiple")) {
if (argc < 2) error_exit("install-multiple requires an argument");
return install_multiple_app(argc, argv);
} else if (!strcmp(argv[0], "install-multi-package")) {
if (argc < 3) error_exit("install-multi-package requires an argument");
return install_multi_package(argc, argv);
} else if (!strcmp(argv[0], "uninstall")) {
if (argc < 2) error_exit("uninstall requires an argument");
return uninstall_app(argc, argv);
}
...
}
// system/core/adb/client/adb_install.cpp
int install_app(int argc, const char** argv) {
...
return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
use_fastdeploy, use_localagent);
...
}
static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
bool use_localagent) {
...
result = pm_command(argc, argv);
...
}
static int pm_command(int argc, const char** argv) {
std::string cmd = "pm";
while (argc-- > 0) {
cmd += " " + escape_arg(*argv++);
}
return send_shell_command(cmd);
}
// system/core/adb/client/commandline.cpp
int send_shell_command(const std::string& command, bool disable_shell_protocol,
StandardStreamsCallbackInterface* callback) {
// 這塊較為繁瑣,原理是是通過(guò)socket傳遞到frameworks/native/cmds/cmd/cmd.cpp中
}
// frameworks/native/cmds/cmd/cmd.cpp
int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,
int in, int out, int err, RunMode runMode) {
...
String16 serviceName = String16(cmd.data(), cmd.size());
for (int i = 1; i < argc; i++) {
args.add(String16(argv[i].data(), argv[i].size()));
}
sp<IBinder> service = sm->checkService(serviceName);
...
status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
...
}
// frameworks/base/core/java/android/os/Binder.java
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
// 這里會(huì)根據(jù)不同服務(wù)傳遞到不服務(wù)對(duì)應(yīng)的onShellCommand接口中
onShellCommand(in, out, err, args, callback, resultReceiver);
}
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
(new PackageManagerShellCommand(this)).exec(
this, in, out, err, args, callback, resultReceiver);
}
public int onCommand(String cmd) {
...
case "install":
return runInstall();
...
}
private int runInstall() throws RemoteException {
...
// 創(chuàng)建session
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);
...
// 把a(bǔ)pk信息寫入到sessionID對(duì)應(yīng)的session中
if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
// 提交session普泡,執(zhí)行安裝
if (doCommitSession(sessionId, false /*logSuccess*/)
!= PackageInstaller.STATUS_SUCCESS) {
return 1;
}
...
}
private int doCommitSession(int sessionId, boolean logSuccess)
throws RemoteException {
...
session.commit(receiver.getIntentSender());
...
}
// frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
...
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();// handler到handleCommit
}
private void handleCommit() {
...
commitNonStagedLocked(childSessions);
...
}
private void commitNonStagedLocked(List<PackageInstallerSession> childSessions)
throws PackageManagerException {
...
mPm.installStage(committingSession);
...
}
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
void installStage(ActiveInstallSession activeInstallSession) {
...
final Message msg = mHandler.obtainMessage(INIT_COPY);
...
mHandler.sendMessage(msg); // handler到HandlerParams.startCopy
}
// InstallParams extends HandlerParams
// InstallParams單個(gè)應(yīng)用安裝
private abstract class HandlerParams {
final void startCopy() {
handleStartCopy(); // 最重要的工作就是計(jì)算應(yīng)用安裝的位置
handleReturnCode();
}
}
class InstallParams extends HandlerParams {
void handleStartCopy() {
...
final InstallArgs args = createInstallArgs(this);
...
}
void handleReturnCode() {
...
// FileInstallArgs.copyApk
// FileInstallArgs.doCopyApk
// PackageManagerServiceUtils.copyPackage
// PackageParser.parsePackageLite
// copyFile(pkg.baseCodePath, targetDir, "base.apk");
mRet = mArgs.copyApk();
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
if (args.mMultiPackageInstallParams != null) {
args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
} else {
PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
processInstallRequestsAsync(
res.returnCode == PackageManager.INSTALL_SUCCEEDED,
Collections.singletonList(new InstallRequest(args, res)));
}
}
private void processInstallRequestsAsync(boolean success,
List<InstallRequest> installRequests) {
...
request.args.doPreInstall(request.installResult.returnCode); // 準(zhǔn)備工作
...
installPackagesTracedLI(installRequests);
...
request.args.doPostInstall(...); // 清理工作
...
restoreAndPostInstall(...); // 后續(xù)工作(比如發(fā)送應(yīng)用變化相關(guān)的廣播)
}
private void installPackagesTracedLI(List<InstallRequest> requests) {
...
// -> preparePackageLI
// -> scanPackageTracedLI
// -> reconcilePackagesLocked
// -> commitPackagesLocked
// -> executePostCommitSteps
installPackagesLI(requests);// 具體安裝過(guò)程
...
}
2播掷、preparePackageLI
1、準(zhǔn)備scanFlags
SCAN_NEW_INSTALL
SCAN_UPDATE_SIGNATURE
SCAN_INITIAL(已經(jīng)初始化過(guò), args.move != null)
SCAN_DONT_KILL_APP(不需要?dú)⒌? (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0)
SCAN_AS_INSTANT_APP(instantApp)
SCAN_AS_FULL_APP(fullApp)
SCAN_AS_VIRTUAL_PRELOAD(虛擬預(yù)加載, virtualPreload)
2撼班、instantApp不能安裝在外置存儲(chǔ)
if (instantApp && onExternal) throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
3歧匈、解析Package
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
4、instantApp校驗(yàn)
instantApp只能在android O及以上使用
5砰嘁、重命名庫(kù)
renameStaticSharedLibraryPackage
名字上添加版本號(hào)件炉,方便多版本共存
6、替換安裝檢測(cè)
檢測(cè)是否安裝過(guò)(mOriginalPackages和非mOriginalPackages)
有父包禁止安裝
檢查targetSDK
禁止PERSISTENT 非 stage安裝
synchronized (mPackages) {
// Check if installing already existing package
...
}
7矮湘、與老版本簽名比對(duì)
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
}
...
}
8妻率、權(quán)限處理
非系統(tǒng)應(yīng)用移除PROTECTION_FLAG_INSTANT
替換安裝有升級(jí)Key,驗(yàn)證升級(jí)Key(checkUpgradeKeySetLocked)
替換安裝沒(méi)有升級(jí)Key板祝,匹配證書(checkCapability)
9、系統(tǒng)應(yīng)用不支持instantApp和安裝在外置存儲(chǔ)
10走净、abi處理
move:更新primaryCpuAbi 和 secondaryCpuAbi
非Move:derivePackageAbi
11券时、覆蓋安裝
if (replace) {
targetVolumeUuid = null;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
// Static libs have a synthetic package name containing the version
// and cannot be updated as an update would get a new package name,
// unless this is the exact same version code which is useful for
// development.
...
靜態(tài)共享庫(kù)禁止同版本升級(jí)
驗(yàn)證簽名(checkUpgradeKeySetLocked、checkCapability)
升級(jí)限制驗(yàn)證(升級(jí)哈希匹配才能升級(jí))
檢查shared user id
禁止 instant app替換full app
更新后被移除的子包
系統(tǒng)包設(shè)置FLAG_UPDATED_SYSTEM_APP
12伏伯、新安裝
檢查系統(tǒng)是否已存在
3橘洞、scanPackageTracedLI
主要用于生成PackageSetting數(shù)據(jù)結(jié)構(gòu)。
執(zhí)行完scanPackageTrackLI之后Pms的兩大核心數(shù)據(jù)結(jié)構(gòu)都已經(jīng)準(zhǔn)備好了:
final ArrayMap<String, PackageParser.Package> mPackages = new ArrayMap<>()
mSettings.mPackages的PackageSetting
PackageParser.Package為靜態(tài)數(shù)據(jù)说搅,掃描完成后就不會(huì)發(fā)生變化炸枣。PackageSetting用于存儲(chǔ)安裝應(yīng)用的動(dòng)態(tài)數(shù)據(jù),如權(quán)限授予情況等弄唧。PackageParser.Package由于是靜態(tài)數(shù)據(jù)适肠,掃描apk就可以獲取。PackageSetting生成之后會(huì)被記錄到文件中候引,以后每次系統(tǒng)啟動(dòng)都會(huì)重新加載侯养。
4、reconcilePackagesLocked
生成PackageSetting和PackageParser.Package數(shù)據(jù)結(jié)構(gòu)后澄干,還需要對(duì)多個(gè)安裝apk結(jié)果進(jìn)行核對(duì)逛揩,這就是reconcilePackagesLocked函數(shù)柠傍。
1、復(fù)制現(xiàn)有包以便與傳入包合并(combinedPackages.putAll(request.allPackages))
2辩稽、用傳入包替換現(xiàn)有包(combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg))
3惧笛、根據(jù)版本號(hào)添加靜態(tài)共享庫(kù)(addSharedLibraryToPackageVersionMap)
4、刪除非系統(tǒng)應(yīng)用的現(xiàn)有包(mayDeletePackageLocked)
5逞泄、驗(yàn)證簽名(checkUpgradeKeySetLocked患整、verifySignatures)
5、commitPackagesLocked
經(jīng)過(guò)上述幾個(gè)步驟炭懊,兩個(gè)核心數(shù)據(jù)結(jié)構(gòu)雖然已經(jīng)生成并级,但是并沒(méi)有添加到容器中去(PackageManagerService.mPackages 和 PackageManagerService.mSettings.mPackage), 所以該包里面的組件等還不能查詢到,也不能啟動(dòng)侮腹。 所以需要commitPackagesLocked來(lái)進(jìn)行提交嘲碧, 提交之后該應(yīng)用就算完整發(fā)布了。
1父阻、覆蓋安裝
1愈涩、設(shè)置安裝和更新時(shí)間(setInstallAndUpdateTime)
2、系統(tǒng)應(yīng)用-移除現(xiàn)有包(removePackageLI)
3加矛、系統(tǒng)應(yīng)用-記錄現(xiàn)有包需要?jiǎng)h除的覆蓋安裝的應(yīng)用
4履婉、系統(tǒng)應(yīng)用-處理子包
4、非系統(tǒng)應(yīng)用-刪除包(executeDeletePackageLIF)
2斟览、commitReconciledScanResultLocked
1毁腿、shared user改變,移除old shared user
2苛茂、PackageSetting更新
3已烤、更新共享庫(kù)(executeSharedLibrariesUpdateLPr)
4、更新簽名信息(pkgSetting.signatures.mSigningDetails)
5妓羊、采用另一個(gè)package的權(quán)限所有權(quán)(mSettings.mPermissions.transferPermissions)
6胯究、更新AbiCodePath(mInstaller.rmdex)
7、commitPackageSettings
3躁绸、commitPackageSettings
1裕循、更新靜態(tài)共享庫(kù)(commitSharedLibraryInfoLocked、updateSharedLibrariesLocked)
2净刮、更新庫(kù)時(shí)殺掉依賴程序(killApplication)
3剥哑、添加組件、權(quán)限組庭瑰、權(quán)限(addAllComponents星持、addAllPermissionGroups、addAllPermissions)
4弹灭、更新mInstrumentation
5督暂、更新mProtectedBroadcasts
6揪垄、撤銷需要撤銷的權(quán)限(revokeRuntimePermissionsIfGroupChanged)
6、executePostCommitSteps
1逻翁、準(zhǔn)備APP數(shù)據(jù)(prepareAppDataAfterInstallLIF)
2饥努、notifyPackageUpdated
3、prepareAppProfiles
4八回、編譯布局資源(compileLayouts)
5酷愧、執(zhí)行Dex優(yōu)化(performDexOpt)
7、restoreAndPostInstall
1缠诅、備份恢復(fù)(restoreAtInstallForUser)
2溶浴、使用rollbackMnaager恢復(fù)數(shù)據(jù)(snapshotAndRestoreUserData)
3、安裝成功(POST_INSTALL, 沒(méi)有doRestore)
8管引、handlePackagePostInstall
1士败、發(fā)送移除廣播(sendPackageRemovedBroadcasts)
2、設(shè)置白名單限制權(quán)限(setWhitelistedRestrictedPermissions)
3褥伴、運(yùn)行時(shí)權(quán)限(grantRequestedRuntimePermissions谅将、grantRuntimePermissionsGrantedToDisabledPackage)
4、ACTION_PACKAGE_ADDED重慢、ACTION_PACKAGE_REPLACED廣播