android 命令pm 全称 packagemanager,关于android:PackageManager安装应用笔记

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));

}

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

......

–>而后会调用到

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值