android开发浅谈之PackageManagerService部分一(pkms)
Posted hfreeman2008
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android开发浅谈之PackageManagerService部分一(pkms)相关的知识,希望对你有一定的参考价值。
本文基于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: InstallParams{78e22b5 file=/data/app/vmdl2019169999.tmp}
PackageManager: startCopy UserHandle{0}: InstallParams{78e22b5 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: Package{2dbf84 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(android开发浅谈之InputMethodManagerService
android开发浅谈之InputMethodManagerService
android开发浅谈之PackageManagerService(pkms)
android开发浅谈之PackageManagerService(pkms)