Android 9 平台
装置利用个别有三种形式:
命令, PackageManager.installPackage(), 发Intent形式
1.命令装置
之前是用adb shell pm ...命令
当初是用adb shell cmd package ...命令,
也可用adb install 命令装置利用。
cmd package命令通过binder的shell cmd 调用
frameworks/native/cmds/cmd/cmd.cppIBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
参数service即传入的package服务,通过Binder的一些传递(CPP 通过binder调用JAVA Binder服务)最终调用onShellCommand()
frameworks/base/core/java/android/os/Binder.javapublic void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,......{ onShellCommand(in, out, err, args, callback, resultReceiver); }
对用package来说,即调用到
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java@Overridepublic 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);}
PackageManagerShellCommand.java 继承 ShellCommand.java,其exec()代码位于ShellCommand.java最初调到 onCommand(mCmd);
也即
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java onCommand(String cmd)
对于install命令来说, 调用 runInstall()而后与PackageInstaller交互,CreateSession, commit
private int runInstall() throws RemoteException {...... final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId);...... if (doCommitSession(sessionId, false /*logSuccess*/)
命令行装置大体流程
IBinder::shellCommand()/cmd.cpp --> .... --> onShellCommand()/PackageManagerService.java --> exec()/ShellCommand.java--> onCommand()/PackageManagerShellCommand.java -->runInstall() +--> doCreateSession() | +--> mInterface.getPackageInstaller().createSession(params, installerPackageName, userId); +--> doCommitSession() +--> new PackageInstaller.Session(mInterface.getPackageInstaller().openSession(sessionId)); +--> session.commit(receiver.getIntentSender())
2 PackageManager installPackage()
2.1 利用getPackageManager()
mContext.getPackageManager();
frameworks/base/core/java/android/content/ ContextWrapper.javaContextWrapper extends Context Context mBase;public PackageManager getPackageManager() { return mBase.getPackageManager();}
Context.java
public abstract PackageManager getPackageManager();
最终实现
frameworks/base/core/java/android/app/ContextImpl.javaContextImpl extends Contextpublic PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. return (mPackageManager = new ApplicationPackageManager(this, pm)); <--- ApplicationPackageManager() } return null;}
即:
mContext.getPackageManager(); --> ApplicationPackageManager()
frameworks/base/core/java/android/app/ApplicationPackageManager.java
ApplicationPackageManager extends PackageManager
2.2 installPackage()
从Android 7开始
PackageManager.java installPackage()标注被 PackageInstaller 代替, 9.0里已找不到该接口.
PackageInstaller地位:
frameworks/base/core/java/android/content/pm/PackageManager.java
public abstract @NonNull PackageInstaller getPackageInstaller();
ApplicationPackageManager.javapublic PackageInstaller getPackageInstaller() {...... mInstaller = new PackageInstaller(mPM.getPackageInstaller(), mContext.getPackageName(), mContext.getUserId());......}
3 通过Intent装置新利用
示例: development/samples/ApiDemos/src/com/example/android/apis/content/InstallApk.java
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
...
startActivity(intent);
-->该intent接收者定义在
packages/apps/PackageInstaller/AndroidManifest.xml<activity android:name=".InstallStart"...... <action android:name="android.intent.action.INSTALL_PACKAGE"
-->而后会调用到
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
--> 须要权限确认是 PackageInstallerActivity.class
-->
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java --> startInstall() { newIntent.setClass(this, InstallInstalling.class); --> packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java onResume() mStagingTask = new StagingAsyncTask(); mStagingTask.execute(getIntent().getData()); --> session.commit(pendingIntent.getIntentSender());
4 session.commit()
cmd package命令装置和点击装置最初都调到session.commit(),间接看commit(), 之前的create session创立会话略过
且只剖析新装置, 不剖析降级。
其最终的实现是在
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.javacommit() +--> MSG_COMMIT +--> commitLocked() +--> extractNativeLibraries() +--> mPm.installStage() +--> frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java +-> installStage() +--> sendMessage INIT_COPYcase INIT_COPY: +--> mBound connectToService() 查看是否bind了 DefaultContainerService 服务 +--> mPendingInstalls.add() 增加到Pending中排个队 +--> sendMessage MCS_BOUNDcase MCS_BOUND: +--> params.startCopy() +--> handleStartCopy() +--> 一大堆查看,错误处理,验证 +--> args.copyApk() --> 注4.1 +--> handleReturnCode() +--> processPendingInstall() +--> args.doPreInstall(res.returnCode); +--> installPackageTracedLI(args, res); +--> installPackageLI(args, res); --> 注4.2 +--> args.doPostInstall(res.returnCode, res.uid); --> 播送 + 如果还有pending的,发个MCS_BOUND音讯,这样loop解决下一个
注4.1:
copyApk()同样是调用DefaultContainerService的copyPackage()将利用的文件复制到/data/app 下。
如果利用中还有native的动静库,也会把包在apk文件中的动静库的文件提取进去。
执行完copyApk()后,装置的第一阶段的工作就实现了,利用装置到了/data/app目录下
注4.2:
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {...... PackageParser pp = new PackageParser();...... // 1. 解析apk pkg = pp.parsePackage(tmpPackageFile, parseFlags);...... // 2. 收集签名 PackageParser.collectCertificates(pkg, false /* skipVerify */);...... // 3. 一大堆的查看 // Check if installing already existing package...... permissions查看 int N = pkg.permissions.size(); for (int i = N-1; i >= 0; i--) {...... // 4. 如果是降级,调用 replacePackageLIF() 否则 installNewPackageLIF() if (replace) {...... replacePackageLIF(pkg, parseFlags, scanFlags, args.user, installerPackageName, res, args.installReason); } else { installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,..... // 5. performDexopt if (performDexopt) {...... mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.getPackageUseInfoOrDefault(pkg.packageName), dexoptOptions);......
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,....... PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user); --> 扫描包信息, 解析AndroidManifest.xml等 updateSettingsLI(newPackage, installerPackageName, null, res, user); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { prepareAppDataAfterInstallLIF(newPackage); --> mInstaller.createAppData() } 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); }
5. PMS初始化
startBootstrapServices() SystemServer.java --> PackageManagerService.main()public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { // 1. PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); // 2. m.enableSystemUserPackages(); // 3. ServiceManager.addService("package", m); final PackageManagerNative pmn = m.new PackageManagerNative(); //4 . ServiceManager.addService("package_native", pmn); return m;}
看似简略,即new PMS类和Native类,而后退出到ServiceManager服务中,然而正文1和正文3干的事也挺多的,之前用思维导图整顿了下,可保留下来放大看看