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: 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(android开发浅谈之InputMethodManagerService

android开发浅谈之InputMethodManagerService

android开发浅谈之PackageManagerService(pkms)

android开发浅谈之PackageManagerService(pkms)

android开发浅谈之InputMethodManagerService

android开发浅谈之PackageManagerService部分一(pkms)