Android6.0 PackageManagerService(PMS)-构造函数

目录如上所示~~↑↑↑PMS入口PMS从/frameworks/base/services/java/com/android/server/SystemServer.java中的startBootstrapServices()启动private void startBootstrapServices(){ Installer installer = mSystemServiceManager.s
摘要由CSDN通过智能技术生成

目录如上所示~~↑↑↑

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,也就是一
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值