关于android:PackageManager安装应用笔记

6次阅读

共计 7129 个字符,预计需要花费 18 分钟才能阅读完成。

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.cpp
IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,

参数 service 即传入的 package 服务, 通过 Binder 的一些传递 (CPP 通过 binder 调用 JAVA Binder 服务) 最终调用 onShellCommand()

frameworks/base/core/java/android/os/Binder.java
public 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
@Override
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);
}

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.java
ContextWrapper extends Context 
Context mBase;
public PackageManager getPackageManager() {return mBase.getPackageManager();
}

Context.java
public abstract PackageManager getPackageManager();
最终实现

frameworks/base/core/java/android/app/ContextImpl.java
ContextImpl extends Context
public 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.java
public 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.java
commit() 
  +--> MSG_COMMIT
         +--> commitLocked()
                +--> extractNativeLibraries()
                +--> mPm.installStage()
                       +--> frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
                       +-> installStage()
                             +--> sendMessage INIT_COPY

case INIT_COPY:
  +--> mBound connectToService() 查看是否 bind 了 DefaultContainerService 服务
  +--> mPendingInstalls.add() 增加到 Pending 中排个队
  +--> sendMessage MCS_BOUND

case 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 干的事也挺多的,之前用思维导图整顿了下,可保留下来放大看看

正文完
 0