当前位置:   article > 正文

PackageManagerService分析之一_ipackagemanager.stub.asinterfac

ipackagemanager.stub.asinterfac

1, 基本概念

PackageManagerService(简称PMS), 是android系统中一个核心的服务,

它负责系统中Package的管理,应该程序的安装、卸载等.在SystemServer的startBootstrapServices方法启动。

  1. mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
  2. mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
PMS的main方法如下,
  1. public static PackageManagerService main(Context context, Installer installer,
  2. boolean factoryTest, boolean onlyCore) {
  3. PackageManagerService m = new PackageManagerService(context, installer,
  4. factoryTest, onlyCore);
  5. ServiceManager.addService("package", m); // 注册
  6. return m;
  7. }

看来所有动作都在PMS的构造方法中完成的。

再看看PMS的结构可知,PMS服务也是一个Binder服务,

public class PackageManagerService extends IPackageManager.Stub {

在ActivityThread的getPackageManager方法中,可以获取PMS服务。

  1. if (sPackageManager != null) {
  2. //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
  3. return sPackageManager;
  4. }
  5. IBinder b = ServiceManager.getService("package");
  6. //Slog.v("PackageManager", "default service binder = " + b);
  7. sPackageManager = IPackageManager.Stub.asInterface(b);
  8. //Slog.v("PackageManager", "default service = " + sPackageManager);
  9. return sPackageManager;
  10. }

PMS的构造方法很长很长,主要包括以下逻辑

  • 扫描目标文件夹之前的准备工作。
  • 扫描目标文件夹。
  • 扫描之后的工作。

 

2, 准备工作

PMS的构造方法关于Settings部分代码如下,

  1. mSettings = new Settings(mPackages);
  2. mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
  3. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
  4. mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
  5. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
  6. mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
  7. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
  8. mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
  9. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
  10. mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
  11. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
  12. mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
  13. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

mPackages是一个ArrayMap变量,

  1. @GuardedBy("mPackages")
  2. final ArrayMap<String, PackageParser.Package> mPackages =
  3. new ArrayMap<String, PackageParser.Package>();

流程图如下,


2.1 Settings

Settings的构造方法如下,

  1. Settings(Object lock) {
  2. this(Environment.getDataDirectory(), lock);
  3. }
  4. Settings(File dataDir, Object lock) {
  5. mLock = lock;
  6. mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
  7. mSystemDir = new File(dataDir, "system");
  8. mSystemDir.mkdirs();
  9. FileUtils.setPermissions(mSystemDir.toString(),
  10. FileUtils.S_IRWXU|FileUtils.S_IRWXG
  11. |FileUtils.S_IROTH|FileUtils.S_IXOTH,
  12. -1, -1);
  13. mSettingsFilename = new File(mSystemDir, "packages.xml");
  14. mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
  15. mPackageListFilename = new File(mSystemDir, "packages.list");
  16. FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
  17. // Deprecated: Needed for migration
  18. mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
  19. mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
  20. }

新建了5个文件夹,

  1. private final File mSettingsFilename;
  2. private final File mBackupSettingsFilename;
  3. private final File mPackageListFilename;
  4. private final File mStoppedPackagesFilename;
  5. private final File mBackupStoppedPackagesFilename;

Environment.getDataDirectory()返回/data目录,然后创建/data/system/目录,并设置它的权限,

并 在/data/system目录中创建5个文件。packages.xml就是保存了系统所有的Package信息,

packages-backup.xml是packages.xml的备份,防止在写packages.xml突然断电等问题。

2.2 addSharedUserLPw

  1. mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
  2. ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

调用addSharedUserLPw将几种SharedUserId的名字和它对应的UID对应写到Settings当中。

关于 SharedUserId的使用,在后面介绍APK的安装过程中再来分析. Process中提供的UID列表如下,

  1. public static final int ROOT_UID = 0;
  2. public static final int SYSTEM_UID = 1000; // system
  3. public static final int PHONE_UID = 1001;// telephony
  4. public static final int SHELL_UID = 2000;// user shell
  5. public static final int LOG_UID = 1007;// log group
  6. public static final int WIFI_UID = 1010;// WIFI
  7. •••

Settings中的addSharedUserLPw方法如下,

  1. SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
  2. SharedUserSetting s = mSharedUsers.get(name);
  3. if (s != null) {
  4. if (s.userId == uid) {
  5. return s;
  6. }
  7. PackageManagerService.reportSettingsProblem(Log.ERROR,
  8. "Adding duplicate shared user, keeping first: " + name);
  9. return null;
  10. }
  11. s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
  12. s.userId = uid;
  13. if (addUserIdLPw(uid, s, name)) {
  14. mSharedUsers.put(name, s);
  15. return s;
  16. }
  17. return null;
  18. }

首先根据name, pkgFlags, pkgPrivateFlags等信息构造SharedUserSetting,然后添加到mSharedUsers的ArrayMap中。

  1. final ArrayMap<String, SharedUserSetting> mSharedUsers =
  2. new ArrayMap<String, SharedUserSetting>();

例如在SystemUI.apk的AndroidManifest.xml文件中,有关键代码:

  1. <mainfest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="com.android.systemui"
  3. coreApp="true"
  4. android:sharedUserId="android.uid.system"
  5. android:process="system">

在该标签中,声明了一个android:sharedUserId的属性,其值为“android.uid.system”。sharedUserId和UID有关,它的作用是

1,两个或者多个声明了同一种sharedUserid的APK可共享彼此的数据,并且可运行在同一进程中。

2,通过声明特定的sharedUserId,该APK所在的进程将被赋予指定UID。

例如SystemUI声明了system的uid,运行SystemUI的进程就可享有system用户所对应的权限了,实际上就是将该进程的UID设置为system的uid了

2.3 XML文件扫描

接下来是扫描系统目录下与系统权限相关的xml文件,新建文件,处理线程和Handler等。

  1. String separateProcesses = SystemProperties.get("debug.separate_processes");
  2. if (separateProcesses != null && separateProcesses.length() > 0) {
  3. if ("*".equals(separateProcesses)) {
  4. mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
  5. mSeparateProcesses = null;
  6. Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
  7. } else {
  8. mDefParseFlags = 0;
  9. mSeparateProcesses = separateProcesses.split(",");
  10. Slog.w(TAG, "Running with debug.separate_processes: "
  11. + separateProcesses);
  12. }
  13. } else {
  14. mDefParseFlags = 0;
  15. mSeparateProcesses = null;
  16. }
  17. mInstaller = installer;
  18. mPackageDexOptimizer = new PackageDexOptimizer(this);
  19. mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
  20. mOnPermissionChangeListeners = new OnPermissionChangeListeners(
  21. FgThread.get().getLooper());
  22. getDefaultDisplayMetrics(context, mMetrics);
  23. SystemConfig systemConfig = SystemConfig.getInstance();
  24. mGlobalGids = systemConfig.getGlobalGids();
  25. mSystemPermissions = systemConfig.getSystemPermissions();
  26. mAvailableFeatures = systemConfig.getAvailableFeatures();

新建文件

  1. File dataDir = Environment.getDataDirectory();
  2. mAppDataDir = new File(dataDir, "data");
  3. mAppInstallDir = new File(dataDir, "app");
  4. mAppLib32InstallDir = new File(dataDir, "app-lib");
  5. mAsecInternalPath = new File(dataDir, "app-asec").getPath();
  6. mUserAppDataDir = new File(dataDir, "user");
  7. mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
  8. mRegionalizationAppInstallDir = new File(dataDir, "app-regional");

解析系统权限文件, 主要是解析系统目录下xml文件,获得设备相关的权限.

 例如该设备是否支持蓝牙,wifi等

  1. ArrayMap<String, SystemConfig.PermissionEntry> permConfig
  2. = systemConfig.getPermissions();
  3. for (int i=0; i<permConfig.size(); i++) {
  4. SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
  5. BasePermission bp = mSettings.mPermissions.get(perm.name);
  6. if (bp == null) {
  7. bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
  8. mSettings.mPermissions.put(perm.name, bp);
  9. }
  10. if (perm.gids != null) {
  11. bp.setGids(perm.gids, perm.perUser);
  12. }
  13. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/199099
推荐阅读
  

闽ICP备14008679号