目录如上所示~~↑↑↑
PMS入口
PMS从/frameworks/base/services/java/com/android/server/SystemServer.java中的startBootstrapServices()启动
private void startBootstrapServices(){
Installer installer = mSystemServiceManager.startService(Installer.class);
// Install是pm路径下面的一个单独的类,主要用于通过InstallerConnection建立和installd的链接
// 然后Installd会进行创建一些系统关键目录的作用,所以我们要等待Installd的结束,才可以继续进行其它的创建
...
// Start the package manager.
Slog.i(TAG, "Package Manager");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//第二个参数installer负责和native层中的installd守护进程进行socket通信。
//第四个参数mOnlyCore用于判断是否仅仅扫描系统的目录,只有在与data分区加解密时才会设置为true,其他情况一般都为false。
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
...
}
PMS的main函数如下:
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
main函数主要做了两件事:
1.创建PackageManagerService对象2.将PMS向SMS中注册,即加入SMS中,方便后续其他进程或者app通过SMS获得PMS服务
时序图如下:
PMS构造函数分析
PMS构造函数的工作,总结起来就是扫描Android系统中的apk,并且建立相应的数据结构去管理Package的信息,四大组件的信息,权限信息等内容。
1.获取系统默认配置
主要获取ro.build.type和debug.separate_processes两个参数
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis());
if (mSdkVersion <= 0) { //先去检查rom的sdk版本,让apk知道运行于哪个版本
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
//ro.build.type有三种:user,userdebug,eng。连接机器后可以通过 getprop ro.build.type 来查看
long dexOptLRUThresholdInMinutes;
if (mLazyDexOpt) {//如果为eng,则mLazyDexOpt为true,只对30分钟内所使用的APP做优化。
dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
} else {
dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
}
mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;
//SystemServer.startOtherServices()->PkMS.performBootDexOpt()->filterRecentlyUsedApps()里用到
mMetrics = new DisplayMetrics();
//new一个DisplayMetrics对象,用于保存屏幕像素参数,匹配APK中的asset和resource
String separateProcesses = SystemProperties.get("debug.separate_processes");
...
//debug.separate_processes:用于标记是否在独立进程中运行某个程序。
//根据该值设置PkMS.mDefParseFlags和PkMS.mSeparateProcesses两个全局变量,后续scanDirLi扫描并安装APK时用到。
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
+ separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}
...
}
2.创建Settings对象并添加共享ID
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
...
mSettings = new Settings(context);// ---见2.1
//new一个Settings对象,这个settings是pm里面的,主要是保存系统apk的相关设置,互相之间关系等内容
//下面是创建6个共享uid
// ---见2.2、2.3
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
...
}
2.1Setting分析
源码路径:/frameworks/base/services/core/java/com/android/server/pm/Settings.java
创建了/data/system的目录,创建了如package.xml等5个文件,设置权限。构造函数如下:
Settings(Object lock) {
this(Environment.getDataDirectory(), lock);
}
Settings(File dataDir, Object lock) {
mLock = lock;
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
mSystemDir = new File(dataDir, "system");
// dataDir为/data mSystemDir为/data/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");//保存了系统所有的Package信息
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");//packages.xml的备份,防止在写packages.xml突然断电
mPackageListFilename = new File(mSystemDir, "packages.list");//保存了系统中已经安装的apk,以及对应的data/data/下面的对应关系
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");//用于记录系统中强制停止运行的Package信息
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
//packages-stopped.xml的备份,防止在写packages-stopped-backup的时候突然断电
}
2.2 UID
UID是User ID的缩写,系统定义的UID/GID在/frameworks/base/core/java/android/os/Process.java文件中,部分如下:
public static final int VPN_UID = 1016;
public static final int NFC_UID = 1027;
public static final int BLUETOOTH_UID = 1002;
2.3 addSharedUserLPw
addSharedUserLPw方法,主要是创建共享UID的相关信息:
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
SharedUserSetting s = mSharedUsers.get(name);
//先以name为key,在mSharedUsers中查看找是否已经有名为name的共享UID
if (s != null) {//找得到
if (s.userId == uid) {//判断此UID和传入的uid是否相等
return s;
}
PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate shared user, keeping first: " + name);
//不相等就报错,即不能对已有的共享UID信息,绑定新的uid。
return null;
}
//没找到,就new一个SharedUserSetting,并将其加入mSharedUsers中去。
s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
//pkgPrivateFlags为ApplicationInfo.PRIVATE_FLAG_PRIVILEGED表明具备system权限。
//pkgFlags为ApplicationInfo.FLAG_SYSTEM表明该app是system app。
s.userId = uid;
if (addUserIdLPw(uid, s, name)) { // ---见2.3.1
mSharedUsers.put(name, s);
return s;
}
return null;
}
mSharedUsers是一个hashmap,HashMap<String, SharedUserSetting>。
其是SharedUserSetting类的实例,该类继承自GrantedPermissions,包含了如下的五个内部变量:
final String name;
int userId;
// flags that are associated with this uid, regardless of any package flags
int uidFlags;
final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
final PackageSignatures signatures = new PackageSignatures();
其中第四个变量PackageSetting继承自PackageSettingBase,其主要有下面的三个成员变量:
int appId;
PackageParser.Package pkg;
SharedUserSetting sharedUser;
2.3.1 addUserIdLPw方法
private boolean addUserIdLPw(int uid, Object obj, Object name) {
if (uid > Process.LAST_APPLICATION_UID) {
// 系统为app分配的UID为10000 - 19999,如果超出了这个范围就会报错
return false;
}
if (uid >= Process.FIRST_APPLICATION_UID) {
int N = mUserIds.size();
final int index = uid - Process.FIRST_APPLICATION_UID;
while (index >= N) {
mUserIds.add(null);
N++;
}
if (mUserIds.get(index) != null) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate user id: " + uid
+ " name=" + name);
return false;
}
mUserIds.set(index, obj);
} else {
if (mOtherUserIds.get(uid) != null) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate shared id: " + uid
+ " name=" + name);
return false;
}
mOtherUserIds.put(uid, obj);
}
return true;
}
android为每一个app都分配了一个UID,每个app从Linux的层面上面,都是一个独立的用户。
该方法主要针对普通uid和system uid进行不同处理。普通的app的uid加入mUsrIds,其他的加入mOtherUserIds。
mUserIds是一个ArrayList,也就是一