关键词:
本文基于Android10.0
主要从以下几个方面着手:
PKMS启动
PKMS安装APK
PKMS卸载APK
PKMS启动
这里我简单的将其分为以下几个步骤:
- 1.SystemServer通过PKMS的main方法启动PKMS
- 2.PKMS构造方法中初始化Settings
- 3.扫描各个系统目录下APP相关信息
1.SystemServer通过PKMS的main方法启动PKMS
PKMS启动是在SystemServer.startBootstrapServices:
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
PackageManagerService.main方法:
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore)
.....
//构造方法
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
final PackageManagerNative pmn = m.new PackageManagerNative();
ServiceManager.addService("package_native", pmn);
return m;
2.PKMS构造方法中初始化Settings
PackageManagerService.PackageManagerService
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore)
......
//Settings的初始化
mSettings = new Settings(Environment.getDataDirectory(),
mPermissionManager.getPermissionSettings(), mPackages);
mSettings是全局的,它主要协助PMS保存系统中安装APP包名,权限,四大组件等相关信息的存储,Settings会在/data/system目录下创建相关的文件来保存这些APP相关的信息
frameworks\\base\\services\\core\\java\\com\\android\\server\\pm\\Settings.java
查看Settings.Settings方法:
Settings(File dataDir, PermissionSettings permission,
Object lock)
......
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
final File kernelDir = new File("/config/sdcardfs");
mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
我们大概看一下/data/system生成的文件信息:
packages.xml----主要是包括包的权限信息:
<package name="com.sohu.inputmethod.sogou.oem" codePath="/system/priv-app/SogouInput" nativeLibraryPath="/system/priv-app/SogouInput/lib" primaryCpuAbi="armeabi" publicFlags="945307205" privateFlags="8" ft="179aac28790" it="179aac28790" ut="179aac28790" version="1312" userId="10076" isOrphaned="true">
<sigs count="1" schemeVersion="1">
<cert index="0" key="30820248308201b102045a3eccafc07082c70bb30ef4" />
</sigs>
<perms>
<item name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" granted="true" flags="0" />
<item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
......
<item name="com.android.launcher.permission.INSTALL_SHORTCUT" granted="true" flags="0" />
<item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
</perms>
<proper-signing-keyset identifier="8" />
</package>
packages-backup.xml
packages.list------------------应用列表
com.android.soundrecorder 10135 0 /data/user/0/com.android.soundrecorder platform:targetSdkVersion=29 1023,3003 0 63
packages-stopped.xml
packages-stopped-backup.xml
3.扫描各个系统目录下APP相关信息
PackageManagerService.PackageManagerService:
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore)
......
// Collect vendor/product/product_services overlay packages. (Do this before scanning
// any apps.)
// For security and version matching reason, only consider overlay packages if they
// reside in the right directory.
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT,
0);
......
scanDirTracedLI(productServicesAppDir,
mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_PRODUCT_SERVICES,
0);
从Android 10,0的代码来看,扫描路径的顺序为:
/vendor/overlay
/product/overlay
/product_services/overlay
/odm/overlay
/oem/overlay
/system/framework
/system/priv-app
/system/app
/vendor/priv-app
/vendor/app
/odm/priv-app
/odm/app
/oem/app
/product/priv-app
/product/app
/product_services/priv-app
/product_services/app
PKMS安装APK
adb install命令 安装apk
我们使用adb install 命令来安装apk:
先来看PackageManagerService的消息定义:
static final int SEND_PENDING_BROADCAST = 1;
static final int INIT_COPY = 5; //此是在安装apk前,copy apk的消息
static final int POST_INSTALL = 9; //安装前的消息
static final int WRITE_SETTINGS = 13;
static final int WRITE_PACKAGE_RESTRICTIONS = 14;
static final int PACKAGE_VERIFIED = 15;
static final int CHECK_PENDING_VERIFICATION = 16;
static final int START_INTENT_FILTER_VERIFICATIONS = 17; //intent filter 的校验消息
static final int INTENT_FILTER_VERIFIED = 18;
static final int WRITE_PACKAGE_LIST = 19;
static final int INSTANT_APP_RESOLUTION_PHASE_TWO = 20;
static final int ENABLE_ROLLBACK_STATUS = 21;
static final int ENABLE_ROLLBACK_TIMEOUT = 22;
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
static final int NEED_UPDATAE_APPLICATION = 25;
static final int NEED_UPDATAE_ACTIVITYINFO = 26;
我们先确认系统是如何发送消息MSG_COMMIT:
我们在PackageInstallerSession.commit添加日志信息:
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer)
......
Slog.v(TAG, "commit " , new Throwable());
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
这个是日志信息输出:
com.android.server.pm.PackageInstallerSession.commit(PackageInstallerSession.java:920)
android.content.pm.PackageInstaller$Session.commit(PackageInstaller.java:1079)
com.android.server.pm.PackageManagerShellCommand.doCommitSession(PackageManagerShellCommand.java:2851)
com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:1082)
com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:169)
android.os.ShellCommand.exec(ShellCommand.java:104)
com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:22266)
android.os.Binder.shellCommand(Binder.java:881)
android.os.Binder.onTransact(Binder.java:765)
android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:4923)
com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:4141)
android.os.Binder.execTransactInternal(Binder.java:1021)
android.os.Binder.execTransact(Binder.java:994)
查看PackageManagerShellCommand.onCommand:
public int onCommand(String cmd)
......
switch(cmd)
case "path":
return runPath();
case "dump":
return runDump();
case "list":
return runList();
case "resolve-activity":
return runResolveActivity();
case "query-activities":
return runQueryIntentActivities();
case "query-services":
return runQueryIntentServices();
case "query-receivers":
return runQueryIntentReceivers();
case "install":
return runInstall();//安装apk
......
可以看出adb shell pm command命令的入口就是在这个方法中添加,而我们执行adb install命令,后面就会来到此处的runInstall方法。
最后,就会来到PackageInstallerSession.commit:
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer)
......
mHandler.obtainMessage(MSG_COMMIT).sendToTarget();//发送MSG_COMMIT消息
然后,我们在PackageManagerService$PackageHandler.doHandleMessage就可以接受到消息MSG_COMMIT:
void doHandleMessage(Message msg)
......
switch (msg.what)
case INIT_COPY:
HandlerParams params = (HandlerParams) msg.obj;
if (params != null)
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
params.startCopy();//执行copy操作
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
break;
查看日志,我们就知道,会将此apk复现/data/app/vmdl2019169999.tmp:
PackageManager: init_copy: InstallParams78e22b5 file=/data/app/vmdl2019169999.tmp
PackageManager: startCopy UserHandle0: InstallParams78e22b5 file=/data/app/vmdl2019169999.tmp
PackageManagerService$HandlerParams.startCopy
final void startCopy()
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
handleStartCopy();
handleReturnCode();
再查看日志:
PackageManager: Renaming /data/app/vmdl2019169999.tmp to /data/app/flipboard.cn-MArVEpS9MmEGIfVhBcSfbg==
我们发现有一个对复制过来的文件进行重命名的操作
再查看日志:
PackageManager: installNewPackageLI: Package2dbf84 flipboard.cn
在PackageManagerService.preparePackageLI添加日志信息:
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure
........
// Remember this for later, in case we need to rollback this install
String pkgName1 = pkg.packageName;
Slog.v(TAG, "preparePackageLI installNewPackageLI" , new Throwable());
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
可以看到日志信息:
com.android.server.pm.PackageManagerService.preparePackageLI(PackageManagerService.java:18268)
com.android.server.pm.PackageManagerService.installPackagesLI(PackageManagerService.java:17328)
com.android.server.pm.PackageManagerService.installPackagesTracedLI(PackageManagerService.java:16675)
com.android.server.pm.PackageManagerService.lambda$processInstallRequestsAsync$13$PackageManagerService(PackageManagerService.java:14919)
再查看,发现日志信息:
PackageManager: Activities: flipboard.activities.LaunchActivity flipboard.activities.BriefingLaunchFlipboardAlias flipboard.activities.LaunchActivityAlias
PackageManager: Receivers: flipboard.receivers.FirstLaunchReminderReceiver flipboard.notifications.NotificationExpirationReceiver
PackageManager: Registered content provider: flipboard.remoteservice.feeds.china, className = flipboard.remoteservice.FLFeedItemContentProvider, isSyncable = false
也就是需要添加要安装的应用中四大组件activity,receiver,content provider,services信息:
我们在ComponentResolver.addProvidersLocked添加打印日志信息:
private void addProvidersLocked(PackageParser.Package pkg, boolean chatty)
Slog.v(TAG, "addProvidersLocked" , new Throwable());
其打印日志为:
com.android.server.pm.ComponentResolver.addProvidersLocked(ComponentResolver.java:557)
com.android.server.pm.ComponentResolver.addAllComponents(ComponentResolver.java:375)
com.android.server.pm.PackageManagerService.commitPackageSettings(PackageManagerService.java:12483)
com.android.server.pm.PackageManagerService.commitReconciledScanResultLocked(PackageManagerService.java:11366)
com.android.server.pm.PackageManagerService.commitPackagesLocked(PackageManagerService.java:17263)
com.android.server.pm.PackageManagerService.installPackagesLI(PackageManagerService.java:17400)
com.android.server.pm.PackageManagerService.installPackagesTracedLI(PackageManagerService.java:16675)
com.android.server.pm.PackageManagerService.lambda$processInstallRequestsAsync$13$PackageManagerService(PackageManagerService.java:14919)
查看ComponentResolver.addAllComponents:
void addAllComponents(PackageParser.Package pkg, boolean chatty)
final ArrayList<PackageParser.ActivityIntentInfo> newIntents = new ArrayList<>();
synchronized (mLock)
addActivitiesLocked(pkg, newIntents, chatty);//添加activity
addReceiversLocked(pkg, chatty); //添加Receiver
addProvidersLocked(pkg, chatty); //添加Provider
addServicesLocked(pkg, chatty); //添加Service
其ComponentResolver类中定义四大组件的信息为:
/** All available activities, for your resolving pleasure. */
@GuardedBy("mLock")
private final ActivityIntentResolver mActivities = new ActivityIntentResolver();
/** All available providers, for your resolving pleasure. */
@GuardedBy("mLock")
private final ProviderIntentResolver mProviders = new ProviderIntentResolver();
/** All available receivers, for your resolving pleasure. */
@GuardedBy("mLock")
private final ActivityIntentResolver mReceivers = new ActivityIntentResolver();
/** All available services, for your resolving pleasure. */
@GuardedBy("mLock")
private final ServiceIntentResolver mServices 查看详情
android开发浅谈之写在前面的话
...相关的职业选择了2011年8月----2013年8月深圳康佳通信科技androidapp开发刚入行,有点怕怕。带我的领导是一位北大的美女,智商碾压绝大部分人 查看详情
android开发浅谈之inputmethodmanagerservice(代码片段)
...应用–InputMethodService我们先讨论输入法应用部分:以android内置的输入法LatinIME为例,先看LatinIME输入的AndroidManifest.xml对其定义:<serviceandroid:name="LatinIME"android:label="@st 查看详情
android开发浅谈之写在前面的话
...相关的职业选择了2011年8月----2013年8月深圳康佳通信科技androidapp开发刚入行,有点怕怕。带我的领导是一位北大的美女,智商碾压绝大部分人,公司要求比较高,比较严,技术开发特别规范。本以后这会是我... 查看详情
浅谈之merge-sort-join
初接触执行计划,做练习时执行sql(如图一)图一:查看其执行计划(如图二)图二:看到上面这个执行计划用到mergesortjoin(排序合并联合查询),刚开始没有理解为什么这条执行计划里还有sortjoin,emp表里deptno字段不是已经有... 查看详情
qt浅谈之二:钟表(时分秒针),qsplitter实现自由伸缩滑动窗口good
http://blog.csdn.net/taiyang1987912/article/details/30272105http://blog.csdn.net/taiyang1987912/article/details/50717179http://blog.csdn.net/taiyang1987912/article/category/2314763 查看详情
qt浅谈之二十一log调试日志
一、简单介绍 近期因调试code时,想了解程序的流程,但苦于没有一个简易的日志记录,不停使用qDebug打印输出,而终于提交代码时得去多次删除信息打印,有时还会出现新改动的代码分不清是哪些部分。... 查看详情
设计模式浅谈之----设计模式简介
1.何为设计模式设计模式是一个通过定义、使用和测试去解决特定问题的方法,并且由于设计模式是在面向对象之后为人所知的,基本思想与面向对象不可分割。在软件工程中,设计模式是一般只在给定条件下会重复性... 查看详情
qt浅谈之四十二钟表摆动显示百分比
一、简介 Qt下利用定时器实现指针指示百分比的钟摆的动态显示效果,可以适用于显示百分比或进度条的进度或时间的刻度值(在圆形进度条上的一种改进)。效果如下:二、详解1、代码(1)Dashb... 查看详情
llvm每日谈之五十五浅谈对pass的错误认知及其原因
Pass作为LLVM的一个重要的组成部分,在LLVMIR层面和LLVMBackend层面都发挥了重要的作用。很多LLVM的使用者容易将Pass理解为LLVMIR层面的analysis和transform,而忽略了Pass在LLVMBackend层面的作用。而实际上,Pass在LLVMBackend层面发... 查看详情
python实例浅谈之五python守护进程和脚本单例运行(代码片段)
一、简介守护进程最重要的特性是后台运行;它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等;它可以在系统启动时从启动脚本/etc/rc.d... 查看详情
如何使用 packageManager 在 android java 中获取克隆的应用程序?
】如何使用packageManager在androidjava中获取克隆的应用程序?【英文标题】:HowcanIgettheclonedappsinandroidjavausingpackageManager?【发布时间】:2019-09-1919:13:43【问题描述】:我正在开发一个新的android启动器应用程序,并且我成功地能够使... 查看详情
浅谈混合开发与android,js数据交互
本文是作者原创,如转载请注明出处!一.概论现在时代已经走过了移动互联网的超级火爆阶段,市场上移动开发人员已经趋于饱和,显然,只会原生APP的开发已不能满足市场的需求,随着H5的兴起与火爆,H5在原生APP中的使用越来越广泛,... 查看详情
android开发应用版本升级怎么实现
...应用的版本号。 要怎么获取PackageInfo对象呢?可以通过PackageManager对象来获取。PackageManager是一个检索当前已安装在设备上的相关应用程序包的各种信息的类。PackageManager对象中的getPackageInfo方法可以获取PackageInfo对象,该方法... 查看详情
PackageManager#installPackage 不适用于 Android N
】PackageManager#installPackage不适用于AndroidN【英文标题】:PackageManager#installPackagedoesn\'tworkforAndroidN【发布时间】:2016-11-1408:52:14【问题描述】:当使用版本24的构建工具和带有N映像(npd56n)的Android设备时,我无法使用PackageManager#install... 查看详情
llvm每日谈之五十七tablegen(代码片段)
...m-tblgen。通常在build目录下的bin目录里。TableGen主要是帮助开发者开发和维护特定领域的信息记录,方便开发者更好的构建这些信息记录,避免错误。尤其是在面对大量的信息记录的时候,用起来比较方便。TableGen 查看详情
浅谈android,以及android程序的helloworld
前言我本是做服务器开发,有时候工作需要和基于Android、Windows等系统进行协同开发,为了知己知彼,我花了一段时间研究了一下Android。至此,站在一个后台开发者的角度,总结一下Android,以及Android和后... 查看详情
Android:PackageManager.getSystemAvailableFeatures() 在 Nexus9 上没有按预期工作
】Android:PackageManager.getSystemAvailableFeatures()在Nexus9上没有按预期工作【英文标题】:Android:PackageManager.getSystemAvailableFeatures()isnotworkingasexpectedonNexus9【发布时间】:2015-03-2021:48:21【问题描述】:我正在尝试使用PackageManager.getSystemAv 查看详情