1、adb install xxx
会响应到adb_commandline,本文重点讲解单个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); // 安装单个应用,本文重点讲解
} 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) {
// 这块较为繁琐,原理是是通过socket传递到frameworks/native/cmds/cmd/cmd.cpp中
}
// frameworks/native/cmds/cmd/cmd.cpp
int cmdMain(const std::vector& 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 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 {
// 这里会根据不同服务传递到不服务对应的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 {
...
// 创建session
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);
...
// 把apk信息写入到sessionID对应的session中
if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
// 提交session,执行安装
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 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单个应用安装
private abstract class HandlerParams {
final void startCopy() {
handleStartCopy(); // 最重要的工作就是计算应用安装的位置
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 installRequests) {
...
request.args.doPreInstall(request.installResult.returnCode); // 准备工作
...
installPackagesTracedLI(installRequests);
...
request.args.doPostInstall(...); // 清理工作
...
restoreAndPostInstall(...); // 后续工作(比如发送应用变化相关的广播)
}
private void installPackagesTracedLI(List requests) {
...
// -> preparePackageLI
// -> scanPackageTracedLI
// -> reconcilePackagesLocked
// -> commitPackagesLocked
// -> executePostCommitSteps
installPackagesLI(requests);// 具体安装过程
...
}
2、preparePackageLI
1、准备scanFlags
SCAN_NEW_INSTALL
SCAN_UPDATE_SIGNATURE
SCAN_INITIAL(已经初始化过, args.move != null)
SCAN_DONT_KILL_APP(不需要杀掉, (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0)
SCAN_AS_INSTANT_APP(instantApp)
SCAN_AS_FULL_APP(fullApp)
SCAN_AS_VIRTUAL_PRELOAD(虚拟预加载, virtualPreload)
2、instantApp不能安装在外置存储
if (instantApp && onExternal) throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
3、解析Package
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
4、instantApp校验
instantApp只能在android O及以上使用
5、重命名库
renameStaticSharedLibraryPackage
名字上添加版本号,方便多版本共存
6、替换安装检测
检测是否安装过(mOriginalPackages和非mOriginalPackages)
有父包禁止安装
检查targetSDK
禁止PERSISTENT 非 stage安装
synchronized (mPackages) {
// Check if installing already existing package
...
}
7、与老版本签名比对
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
}
...
}
8、权限处理
非系统应用移除PROTECTION_FLAG_INSTANT
替换安装有升级Key,验证升级Key(checkUpgradeKeySetLocked)
替换安装没有升级Key,匹配证书(checkCapability)
9、系统应用不支持instantApp和安装在外置存储
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.
...
静态共享库禁止同版本升级
验证签名(checkUpgradeKeySetLocked、checkCapability)
升级限制验证(升级哈希匹配才能升级)
检查shared user id
禁止 instant app替换full app
更新后被移除的子包
系统包设置FLAG_UPDATED_SYSTEM_APP
12、新安装
检查系统是否已存在
3、scanPackageTracedLI
主要用于生成PackageSetting数据结构。
执行完scanPackageTrackLI之后Pms的两大核心数据结构都已经准备好了:
final ArrayMap
mPackages = new ArrayMap<>()
mSettings.mPackages的PackageSetting
PackageParser.Package为静态数据,扫描完成后就不会发生变化。PackageSetting用于存储安装应用的动态数据,如权限授予情况等。PackageParser.Package由于是静态数据,扫描apk就可以获取。PackageSetting生成之后会被记录到文件中,以后每次系统启动都会重新加载。
4、reconcilePackagesLocked
生成PackageSetting和PackageParser.Package数据结构后,还需要对多个安装apk结果进行核对,这就是reconcilePackagesLocked函数。
1、复制现有包以便与传入包合并(combinedPackages.putAll(request.allPackages))
2、用传入包替换现有包(combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg))
3、根据版本号添加静态共享库(addSharedLibraryToPackageVersionMap)
4、删除非系统应用的现有包(mayDeletePackageLocked)
5、验证签名(checkUpgradeKeySetLocked、verifySignatures)
5、commitPackagesLocked
经过上述几个步骤,两个核心数据结构虽然已经生成,但是并没有添加到容器中去(PackageManagerService.mPackages 和 PackageManagerService.mSettings.mPackage), 所以该包里面的组件等还不能查询到,也不能启动。 所以需要commitPackagesLocked来进行提交, 提交之后该应用就算完整发布了。
1、覆盖安装
1、设置安装和更新时间(setInstallAndUpdateTime)
2、系统应用-移除现有包(removePackageLI)
3、系统应用-记录现有包需要删除的覆盖安装的应用
4、系统应用-处理子包
4、非系统应用-删除包(executeDeletePackageLIF)
2、commitReconciledScanResultLocked
1、shared user改变,移除old shared user
2、PackageSetting更新
3、更新共享库(executeSharedLibrariesUpdateLPr)
4、更新签名信息(pkgSetting.signatures.mSigningDetails)
5、采用另一个package的权限所有权(mSettings.mPermissions.transferPermissions)
6、更新AbiCodePath(mInstaller.rmdex)
7、commitPackageSettings
3、commitPackageSettings
1、更新静态共享库(commitSharedLibraryInfoLocked、updateSharedLibrariesLocked)
2、更新库时杀掉依赖程序(killApplication)
3、添加组件、权限组、权限(addAllComponents、addAllPermissionGroups、addAllPermissions)
4、更新mInstrumentation
5、更新mProtectedBroadcasts
6、撤销需要撤销的权限(revokeRuntimePermissionsIfGroupChanged)
6、executePostCommitSteps
1、准备APP数据(prepareAppDataAfterInstallLIF)
2、notifyPackageUpdated
3、prepareAppProfiles
4、编译布局资源(compileLayouts)
5、执行Dex优化(performDexOpt)
7、restoreAndPostInstall
1、备份恢复(restoreAtInstallForUser)
2、使用rollbackMnaager恢复数据(snapshotAndRestoreUserData)
3、安装成功(POST_INSTALL, 没有doRestore)
8、handlePackagePostInstall
1、发送移除广播(sendPackageRemovedBroadcasts)
2、设置白名单限制权限(setWhitelistedRestrictedPermissions)
3、运行时权限(grantRequestedRuntimePermissions、grantRuntimePermissionsGrantedToDisabledPackage)
4、ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REPLACED广播