PackageManagerService构造函数
Settings
下面我们主要分析PackageManagerService的构造函数:
- mSettings = new Settings(context);//新建Settings
- mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,//往Settings中添加SharedUserSetting
- 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);
我们还是挑主要的讲,在构造函数中新建了Setting类,然后又调用了addSharedUserLPw函数。
我们先看Settings类:
- Settings(Context context) {
- this(context, Environment.getDataDirectory());
- }
- Settings(Context context, File dataDir) {
- 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);
- // Deprecated: Needed for migration
- mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
- mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
- }
Settings类在data目录下创建了system目录,然后分别保存了下面文件。
1.packages.xml:记录系统中所有安装的应用的信息, 我们来看下这个文件关于一个package
- <package name="com.android.providers.media" codePath="/system/priv-app/MediaProvider" nativeLibraryPath="/system/priv-app/MediaProvider/lib" publicFlags="944291397" privateFlags="8" ft="15659d595e8" it="15659d595e8" ut="15659d595e8" version="800" sharedUserId="10006">
- <sigs count="1">
- <cert index="2" key="308204a830820390a003020102020900f2b98e6123572c4e300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f6964311
- </sigs>
- <perms>
- <item name="android.permission.ACCESS_CACHE_FILESYSTEM" granted="true" flags="0" />
- <item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />
- <item name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" granted="true" flags="0" />
- <item name="android.permission.RECEIVE_BOOT_COMPLETED" granted="true" flags="0" />
- <item name="android.permission.WRITE_MEDIA_STORAGE" granted="true" flags="0" />
- <item name="android.permission.INTERNET" granted="true" flags="0" />
- <item name="android.permission.UPDATE_DEVICE_STATS" granted="true" flags="0" />
- <item name="android.permission.ACCESS_ALL_DOWNLOADS" granted="true" flags="0" />
- <item name="android.permission.ACCESS_DOWNLOAD_MANAGER" granted="true" flags="0" />
- <item name="android.permission.MANAGE_USERS" granted="true" flags="0" />
- <item name="android.permission.ACCESS_NETWORK_STATE" granted="true" flags="0" />
- <item name="android.permission.ACCESS_MTP" granted="true" flags="0" />
- <item name="android.permission.INTERACT_ACROSS_USERS" granted="true" flags="0" />
- <item name="android.permission.CLEAR_APP_CACHE" granted="true" flags="0" />
- <item name="android.permission.CONNECTIVITY_INTERNAL" granted="true" flags="0" />
- <item name="android.permission.MODIFY_NETWORK_ACCOUNTING" granted="true" flags="0" />
- <item name="android.permission.WAKE_LOCK" granted="true" flags="0" />
- <item name="android.permission.UPDATE_APP_OPS_STATS" granted="true" flags="0" />
- </perms>
- <proper-signing-keyset identifier="4" />
- </package>
2.packages-backup.xml:上面文件的备份
3.packages-stopped.xml:被强制停止运行的应用信息
4.packages-stopped-backup.xml:上面文件的备份
5.packages.list:保存普通应用的数据目录和uid信息等
- ......
- com.android.managedprovisioning 10009 0 /data/data/com.android.managedprovisioning platform 3003
- com.android.gifviewer 10042 0 /data/data/com.android.gifviewer default none
- com.android.dreams.phototable 10054 0 /data/data/com.android.dreams.phototable default none
- com.leadcore.telassistant 1000 0 /data/data/com.leadcore.telassistant platform 3002,1023,1015,3003,3001
- com.android.noisefield 10049 0 /data/data/com.android.noisefield default none
- com.android.smspush 10064 0 /data/data/com.android.smspush default none
- com.leadcore.codescan 10029 0 /data/data/com.leadcore.codescan platform 3003
- com.android.wallpaper.livepicker 10046 0 /data/data/com.android.wallpaper.livepicker platform none
- jp.co.omronsoft.openwnn 10051 0 /data/data/jp.co.omronsoft.openwnn default none
- com.android.settings 1000 0 /data/data/com.android.settings platform 3002,1023,1015,3003,3001
- com.leadcore.logservice 1000 0 /data/data/com.leadcore.logservice platform 3002,1023,1015,3003,3001
- com.android.calculator2 10032 0 /data/data/com.android.calculator2 default none
- com.leadcore.userfeedback 10062 0 /data/data/com.leadcore.userfeedback platform 3003
- com.leadcore.filesearch 10035 0 /data/data/com.leadcore.filesearch default none
- com.iflytek.inputmethod 10041 0 /data/data/com.iflytek.inputmethod default 3002,3003,3001
- org.simalliance.openmobileapi.uiccterminal 10061 0 /data/data/org.simalliance.openmobileapi.uiccterminal platform none
- com.android.wallpaper 10045 0 /data/data/com.android.wallpaper default none
- com.android.vpndialogs 10018 0 /data/data/com.android.vpndialogs platform none
- com.android.email 10031 0 /data/data/com.android.email default 3003
- com.android.music 10048 0 /data/data/com.android.music platform 3002,1023,1015,3003
- com.android.phone 1001 0 /data/data/com.android.phone platform 3002,3003,3001
- com.android.shell 2000 0 /data/data/com.android.shell platform 3002,1023,1015,3008
- com.android.video 10063 0 /data/data/com.android.video platform 1023,1015,3003
- com.android.providers.userdictionary 10000 0 /data/data/com.android.providers.userdictionary default 3003
- com.android.location.fused 1000 0 /data/data/com.android.location.fused platform 3002,1023,1015,3003,3001
- com.android.deskclock 1000 0 /data/data/com.android.deskclock platform 3002,1023,1015,3003,3001
- com.android.systemui 10017 0 /data/data/com.android.systemui platform 3002,1023,1015,3001,3006
- ......
当Android对文件packages.xml和packages-stopped.xml写之前,会先把它们备份,如果写文件成功了,再把备份文件删除掉。如果写的时候,系统出问题重启了,重启后会读取这两个文件时,发现有备份文件,会使用备份文件的内容,因为这个时候原文件已经损坏了。
每个应用的信息会保存在PackageSetting中,而所有的PackageSetting对象会保存在Settings的成员变量mPackages中。
回到构造函数,在Settings添加了SharedUserSetting,6种系统的uid:system radio log nfc bluetooth shell。相同shareUserId的包可以运行在一个进程中。
SystemConfig
继续分析构造函数:
- SystemConfig systemConfig = SystemConfig.getInstance();
- mGlobalGids = systemConfig.getGlobalGids();
- mSystemPermissions = systemConfig.getSystemPermissions();
- mAvailableFeatures = systemConfig.getAvailableFeatures();
SystemConfig构造函数中会去读取etc下面的各个文件分析
- SystemConfig() {
- // Read configuration from system
- readPermissions(Environment.buildPath(
- Environment.getRootDirectory(), "etc", "sysconfig"), false);
- // Read configuration from the old permissions dir
- readPermissions(Environment.buildPath(
- Environment.getRootDirectory(), "etc", "permissions"), false);
- // Only read features from OEM config
- readPermissions(Environment.buildPath(
- Environment.getOemDirectory(), "etc", "sysconfig"), true);
- readPermissions(Environment.buildPath(
- Environment.getOemDirectory(), "etc", "permissions"), true);
- }
分析完了后,会保存在各个成员变量中。
我们看下system/etc/permissions/platform.xml的一部分内容
- ......
- <permission name="android.permission.MANAGE_VOICE_KEYPHRASES">
- <group gid="audio" />
- </permission>
- <permission name="android.permission.ACCESS_FM_RADIO" >
- <group gid="media" />
- </permission>
- <!-- ================================================================== -->
- <!-- ================================================================== -->
- <!-- ================================================================== -->
- <!-- The following tags are assigning high-level permissions to specific
- user IDs. These are used to allow specific core system users to
- perform the given operations with the higher-level framework. For
- example, we give a wide variety of permissions to the shell user
- since that is the user the adb shell runs under and developers and
- others should have a fairly open environment in which to
- interact with the system. -->
- <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
- <assign-permission name="android.permission.WAKE_LOCK" uid="media" />
- <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" />
- <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
- <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
- ......
继续分析,会创建一个消息线程,会创建一些目录
- mHandlerThread = new ServiceThread(TAG,
- Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
- mHandlerThread.start();
- mHandler = new PackageHandler(mHandlerThread.getLooper());
- Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
- File dataDir = Environment.getDataDirectory();//存放应用数据目录
- mAppDataDir = new File(dataDir, "data");
- mAppInstallDir = new File(dataDir, "app");//放应用
- mAppLib32InstallDir = new File(dataDir, "app-lib");//native库
- mAsecInternalPath = new File(dataDir, "app-asec").getPath();
- mUserAppDataDir = new File(dataDir, "user");//存放用户数据
- mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
前面systemconfig解析etc下的文件,然后将Permissions放在mSettings的mPermission,以及共享库放在mSharedLibraries中
- ArrayMap<String, SystemConfig.PermissionEntry> permConfig
- = systemConfig.getPermissions();
- for (int i=0; i<permConfig.size(); i++) {
- SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
- BasePermission bp = mSettings.mPermissions.get(perm.name);
- if (bp == null) {
- bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
- mSettings.mPermissions.put(perm.name, bp);
- }
- if (perm.gids != null) {
- bp.gids = appendInts(bp.gids, perm.gids);
- }
- }
- ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
- for (int i=0; i<libConfig.size(); i++) {
- mSharedLibraries.put(libConfig.keyAt(i),
- new SharedLibraryEntry(libConfig.valueAt(i), null));
- }
readLPw函数
继续分析,调用了Settings的readLPw函数。
- mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false),
- mSdkVersion, mOnlyCore);
我们来详细分析,先会去看packages-backup.xml有没有,有这个文件说明在写packages.xml的时候系统出问题了,所以在系统启动的时候就要读备份的想xml文件内容。如果没有这个备份文件再去看packages.xml, 然后再去解析xml文件,把解析出来的内容封装在各个对象中保存在mSettings中各个变量中。
- boolean readLPw(PackageManagerService service, List<UserInfo> users, int sdkVersion,
- boolean onlyCore) {
- FileInputStream str = null;
- if (mBackupSettingsFilename.exists()) {//是否有备份文件
- try {
- str = new FileInputStream(mBackupSettingsFilename);
- mReadMessages.append("Reading from backup settings file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from backup settings file");
- if (mSettingsFilename.exists()) {
- // If both the backup and settings file exist, we
- // ignore the settings since it might have been
- // corrupted.
- Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
- + mSettingsFilename);
- mSettingsFilename.delete();
- }
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
- }
- }
- mPendingPackages.clear();
- mPastSignatures.clear();
- try {
- if (str == null) {//这里为空,代表没有备份文件,就看packages.xml文件
- if (!mSettingsFilename.exists()) {
- mReadMessages.append("No settings file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "No settings file; creating initial state");
- mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
- mFingerprint = Build.FINGERPRINT;
- return false;
- }
- str = new FileInputStream(mSettingsFilename);
- }
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(str, null);
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
- if (type != XmlPullParser.START_TAG) {
- mReadMessages.append("No start tag found in settings file\n");
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "No start tag found in package manager settings");
- Slog.wtf(PackageManagerService.TAG,
- "No start tag found in package manager settings");
- return false;
- }
- int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- String tagName = parser.getName();
- if (tagName.equals("package")) {
- readPackageLPw(parser);//解析packages.xml中的各内容
- } else if (tagName.equals("permissions")) {
- readPermissionsLPw(mPermissions, parser);
- } else if (tagName.equals("permission-trees")) {
- readPermissionsLPw(mPermissionTrees, parser);
- } else if (tagName.equals("shared-user")) {
- readSharedUserLPw(parser);
- } else if (tagName.equals("preferred-packages")) {
- // no longer used.
- } else if (tagName.equals("preferred-activities")) {
- // Upgrading from old single-user implementation;
- // these are the preferred activities for user 0.
- readPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readPersistentPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readCrossProfileIntentFiltersLPw(parser, 0);
- } else if (tagName.equals("updated-package")) {
- readDisabledSysPackageLPw(parser);
- } else if (tagName.equals("cleaning-package")) {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- String userStr = parser.getAttributeValue(null, ATTR_USER);
- String codeStr = parser.getAttributeValue(null, ATTR_CODE);
- if (name != null) {
- int userId = 0;
- boolean andCode = true;
- try {
- if (userStr != null) {
- userId = Integer.parseInt(userStr);
- }
- } catch (NumberFormatException e) {
- }
- if (codeStr != null) {
- andCode = Boolean.parseBoolean(codeStr);
- }
- addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
- }
- } else if (tagName.equals("renamed-package")) {
- String nname = parser.getAttributeValue(null, "new");
- String oname = parser.getAttributeValue(null, "old");
- if (nname != null && oname != null) {
- mRenamedPackages.put(nname, oname);
- }
- } else if (tagName.equals("last-platform-version")) {
- mInternalSdkPlatform = mExternalSdkPlatform = 0;
- try {
- String internal = parser.getAttributeValue(null, "internal");
- if (internal != null) {
- mInternalSdkPlatform = Integer.parseInt(internal);
- }
- String external = parser.getAttributeValue(null, "external");
- if (external != null) {
- mExternalSdkPlatform = Integer.parseInt(external);
- }
- } catch (NumberFormatException e) {
- }
- mFingerprint = parser.getAttributeValue(null, "fingerprint");
- } else if (tagName.equals("database-version")) {
- mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
- try {
- String internalDbVersionString = parser.getAttributeValue(null, "internal");
- if (internalDbVersionString != null) {
- mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString);
- }
- String externalDbVersionString = parser.getAttributeValue(null, "external");
- if (externalDbVersionString != null) {
- mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString);
- }
- } catch (NumberFormatException ignored) {
- }
- } else if (tagName.equals("verifier")) {
- final String deviceIdentity = parser.getAttributeValue(null, "device");
- try {
- mVerifierDeviceIdentity = VerifierDev
- ......
scanDirLI函数
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = dir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + dir + " scanFlags=" + scanFlags
+ " flags=0x" + Integer.toHexString(parseFlags));
}
long startScan, endScan;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
try {
startScan = SystemClock.uptimeMillis();
Log.d(TAG," scan package: " + file.toString() + " , start at: " + startScan + "ms.");
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
endScan = SystemClock.uptimeMillis();
Log.d(TAG," scan package: " + file.toString() + " , end at: " + endScan + "ms. elapsed time = " + (endScan - startScan) + "ms.");
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
if (file.isDirectory()) {
mInstaller.rmPackageDir(file.getAbsolutePath());
} else {
file.delete();
}
}
}
}
}
scanPackageLI函数
/*
* Scan a package and return the newly parsed package.
* Returns null in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
/*
* 各个参数的值如下:
mSeparateProcesses = null,因为前面初始化值的时候separateProcesses为null
mOnlyCore = false 正常情况下mOnlyCore为flase
mMetrics 为前面获取到的手机的分辨率
mDefParseFlags 的值为0
parseFlags的值会随着scanFile的变化而变化
*/
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
final PackageParser.Package pkg;
try {
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
}
PackageSetting ps = null;
PackageSetting updatedPkg;
// reader
synchronized (mPackages) {
// Look to see if we already know about this package.
String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
// This package has been renamed to its original name. Let's
// use that.
ps = mSettings.peekPackageLPr(oldName);
}
// If there was no original package, see one for the real package name.
if (ps == null) {
ps = mSettings.peekPackageLPr(pkg.packageName);
}
// Check to see if this package could be hiding/updating a system
// package. Must look for it either under the original or real
// package name depending on our state.
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
}
boolean updatedPkgBetter = false;
// First check if this is a system package that may involve an update
if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// If new package is not located in "/system/priv-app" (e.g. due to an OTA),
// it needs to drop FLAG_PRIVILEGED.
if (locationIsPrivileged(scanFile)) {
updatedPkg.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
} else {
updatedPkg.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
if (ps != null && !ps.codePath.equals(scanFile)) {
// The path has changed from what was last scanned... check the
// version of the new path against what we have stored to determine
// what to do.
if (DEBUG_INSTALL) Slog.d(TAG, "Path changing from " + ps.codePath);
if (pkg.mVersionCode <= ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
if (DEBUG_INSTALL) Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
if (!updatedPkg.codePath.equals(scanFile)) {
Slog.w(PackageManagerService.TAG, "Code path for hidden system pkg : "
+ ps.name + " changing from " + updatedPkg.codePathString
+ " to " + scanFile);
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
updatedPkg.resourcePath = scanFile;
updatedPkg.resourcePathString = scanFile.toString();
}
updatedPkg.pkg = pkg;
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
"Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
} else {
// The current app on the system partition is better than
// what we have updated to on the data partition; switch
// back to the system partition version.
// At this point, its safely assumed that package installation for
// apps in system partition will go through. If not there won't be a working
// version of the app
// writer
synchronized (mPackages) {
// Just remove the loaded entries from package lists.
mPackages.remove(ps.name);
}
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(ps.name);
}
updatedPkgBetter = true;
}
}
}
if (updatedPkg != null) {
// An updated system app will not have the PARSE_IS_SYSTEM flag set
// initially
parseFlags |= PackageParser.PARSE_IS_SYSTEM;
// An updated privileged app will not have the PARSE_IS_PRIVILEGED
// flag set initially
if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
// Verify certificates against what was last scanned
collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);
/*
* A new system app appeared, but we already had a non-system one of the
* same name installed earlier.
*/
boolean shouldHideSystemApp = false;
if (updatedPkg == null && ps != null
&& (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
/*
* Check to make sure the signatures match first. If they don't,
* wipe the installed application and its data.
*/
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
+ " signatures don't match existing userdata copy; removing");
deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
ps = null;
} else {
/*
* If the newly-added system app is an older version than the
* already installed version, hide it. It will be scanned later
* and re-added like an update.
*/
if (pkg.mVersionCode <= ps.versionCode) {
shouldHideSystemApp = true;
logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
+ " but new version " + pkg.mVersionCode + " better than installed "
+ ps.versionCode + "; hiding system");
} else {
/*
* The newly found system app is a newer version that the
* one previously installed. Simply remove the
* already-installed application and replace it with our own
* while keeping the application data.
*/
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ " reverting from " + ps.codePathString + ": new version "
+ pkg.mVersionCode + " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
}
}
}
// The apk is forward locked (not public) if its code and resources
// are kept in different files. (except for app in either system or
// vendor path).
// TODO grab this value from PackageSettings
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
}
// TODO: extend to support forward-locked splits
String resourcePath = null;
String baseResourcePath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
resourcePath = ps.resourcePathString;
baseResourcePath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
resourcePath = pkg.codePath;
baseResourcePath = pkg.baseCodePath;
}
// Set application objects path explicitly.
pkg.applicationInfo.volumeUuid = pkg.volumeUuid;
pkg.applicationInfo.setCodePath(pkg.codePath);
pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
pkg.applicationInfo.setResourcePath(resourcePath);
pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
/*
* If the system app should be overridden by a previously installed
* data, hide the system app now and let the /data/app scan pick it up
* again.
*/
if (shouldHideSystemApp) {
synchronized (mPackages) {
mSettings.disableSystemPackageLPw(pkg.packageName);
}
}
return scannedPkg;
}
updatePermissionsLPw函数
private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,
int flags) {
final String volumeUuid = (pkgInfo != null) ? getVolumeUuidForPackage(pkgInfo) : null;
updatePermissionsLPw(changingPkg, pkgInfo, volumeUuid, flags);
}
private void updatePermissionsLPw(String changingPkg,
PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) {
// Make sure there are no dangling permission trees.
Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
while (it.hasNext()) {
final BasePermission bp = it.next();
if (bp.packageSetting == null) {
// We may not yet have parsed the package, so just see if
// we still know about its settings.
bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
}
if (bp.packageSetting == null) {
Slog.w(TAG, "Removing dangling permission tree: " + bp.name
+ " from package " + bp.sourcePackage);
it.remove();
} else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
Slog.i(TAG, "Removing old permission tree: " + bp.name
+ " from package " + bp.sourcePackage);
flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
}
}
// Make sure all dynamic permissions have been assigned to a package,
// and make sure there are no dangling permissions.
it = mSettings.mPermissions.values().iterator();
while (it.hasNext()) {
final BasePermission bp = it.next();
if (bp.type == BasePermission.TYPE_DYNAMIC) {
if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
+ bp.name + " pkg=" + bp.sourcePackage
+ " info=" + bp.pendingInfo);
if (bp.packageSetting == null && bp.pendingInfo != null) {
final BasePermission tree = findPermissionTreeLP(bp.name);
if (tree != null && tree.perm != null) {
bp.packageSetting = tree.packageSetting;
bp.perm = new PackageParser.Permission(tree.perm.owner,
new PermissionInfo(bp.pendingInfo));
bp.perm.info.packageName = tree.perm.info.packageName;
bp.perm.info.name = bp.name;
bp.uid = tree.uid;
}
}
}
if (bp.packageSetting == null) {
// We may not yet have parsed the package, so just see if
// we still know about its settings.
bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
}
if (bp.packageSetting == null) {
Slog.w(TAG, "Removing dangling permission: " + bp.name
+ " from package " + bp.sourcePackage);
it.remove();
} else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
Slog.i(TAG, "Removing old permission: " + bp.name
+ " from package " + bp.sourcePackage);
flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
}
}
// Now update the permissions for all packages, in particular
// replace the granted permissions of the system packages.
if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
for (PackageParser.Package pkg : mPackages.values()) {
if (pkg != pkgInfo) {
// Only replace for packages on requested volume
final String volumeUuid = getVolumeUuidForPackage(pkg);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
grantPermissionsLPw(pkg, replace, changingPkg);
}
}
}
if (pkgInfo != null) {
// Only replace for packages on requested volume
final String volumeUuid = getVolumeUuidForPackage(pkgInfo);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
grantPermissionsLPw(pkgInfo, replace, changingPkg);
}
}
grantPermissionsLPw函数
private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
String packageOfInterest) {
// IMPORTANT: There are two types of permissions: install and runtime.
// Install time permissions are granted when the app is installed to
// all device users and users added in the future. Runtime permissions
// are granted at runtime explicitly to specific users. Normal and signature
// protected permissions are install time permissions. Dangerous permissions
// are install permissions if the app's target SDK is Lollipop MR1 or older,
// otherwise they are runtime permissions. This function does not manage
// runtime permissions except for the case an app targeting Lollipop MR1
// being upgraded to target a newer SDK, in which case dangerous permissions
// are transformed from install time to runtime ones.
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
PermissionsState permissionsState = ps.getPermissionsState();
PermissionsState origPermissions = permissionsState;
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
boolean runtimePermissionsRevoked = false;
int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
boolean changedInstallPermission = false;
if (replace) {
ps.installPermissionsFixed = false;
if (!ps.isSharedUser()) {
origPermissions = new PermissionsState(permissionsState);
permissionsState.reset();
} else {
// We need to know only about runtime permission changes since the
// calling code always writes the install permissions state but
// the runtime ones are written only if changed. The only cases of
// changed runtime permissions here are promotion of an install to
// runtime and revocation of a runtime from a shared user.
changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw(
ps.sharedUser, UserManagerService.getInstance().getUserIds());
if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) {
runtimePermissionsRevoked = true;
}
}
}
permissionsState.setGlobalGids(mGlobalGids);
final int N = pkg.requestedPermissions.size();
for (int i=0; i<N; i++) {
final String name = pkg.requestedPermissions.get(i);
final BasePermission bp = mSettings.mPermissions.get(name);
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
}
if (bp == null || bp.packageSetting == null) {
if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
Slog.w(TAG, "Unknown permission " + name
+ " in package " + pkg.packageName);
}
continue;
}
final String perm = bp.name;
boolean allowedSig = false;
int grant = GRANT_DENIED;
// Keep track of app op permissions.
if ((bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name);
if (pkgs == null) {
pkgs = new ArraySet<>();
mAppOpPermissionPackages.put(bp.name, pkgs);
}
pkgs.add(pkg.packageName);
}
final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
switch (level) {
case PermissionInfo.PROTECTION_NORMAL: {
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} break;
case PermissionInfo.PROTECTION_DANGEROUS: {
if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1){
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL_LEGACY;
} else if (origPermissions.hasInstallPermission(bp.name)) {
// For legacy apps that became modern, install becomes runtime.
grant = GRANT_UPGRADE;
} else if (mPromoteSystemApps
&& isSystemApp(ps)
&& mExistingSystemPackages.contains(ps.name)) {
// For legacy system apps, install becomes runtime.
// We cannot check hasInstallPermission() for system apps since those
// permissions were granted implicitly and not persisted pre-M.
grant = GRANT_UPGRADE;
} else {
// For modern apps keep runtime permissions unchanged.
grant = GRANT_RUNTIME;
}
} break;
case PermissionInfo.PROTECTION_SIGNATURE: {
// For all apps signature permissions are install time ones.
allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
if (allowedSig) {
grant = GRANT_INSTALL;
}
} break;
}
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
}
if (grant != GRANT_DENIED) {
if (!isSystemApp(ps) && ps.installPermissionsFixed) {
// If this is an existing, non-system package, then
// we can't add any new permissions to it.
if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
// Except... if this is a permission that was added
// to the platform (note: need to only do this when
// updating the platform).
if (!isNewPlatformPermissionForPackage(perm, pkg)) {
grant = GRANT_DENIED;
}
}
}
switch (grant) {
case GRANT_INSTALL: {
// Revoke this as runtime permission to handle the case of
// a runtime permission being downgraded to an install one.
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (origPermissions.getRuntimePermissionState(
bp.name, userId) != null) {
// Revoke the runtime permission and clear the flags.
origPermissions.revokeRuntimePermission(bp, userId);
origPermissions.updatePermissionFlags(bp, userId,
PackageManager.MASK_PERMISSION_FLAGS, 0);
// If we revoked a permission permission, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
// Grant an install permission.
if (permissionsState.grantInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
changedInstallPermission = true;
}
} break;
case GRANT_INSTALL_LEGACY: {
// Grant an install permission.
if (permissionsState.grantInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
changedInstallPermission = true;
}
} break;
case GRANT_RUNTIME: {
// Grant previously granted runtime permissions.
for (int userId : UserManagerService.getInstance().getUserIds()) {
PermissionState permissionState = origPermissions
.getRuntimePermissionState(bp.name, userId);
final int flags = permissionState != null
? permissionState.getFlags() : 0;
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
if (permissionsState.grantRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// If we cannot put the permission as it was, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
// Propagate the permission flags.
permissionsState.updatePermissionFlags(bp, userId, flags, flags);
}
} break;
case GRANT_UPGRADE: {
// Grant runtime permissions for a previously held install permission.
PermissionState permissionState = origPermissions
.getInstallPermissionState(bp.name);
final int flags = permissionState != null ? permissionState.getFlags() : 0;
if (origPermissions.revokeInstallPermission(bp)
!= PermissionsState.PERMISSION_OPERATION_FAILURE) {
// We will be transferring the permission flags, so clear them.
origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
}
// If the permission is not to be promoted to runtime we ignore it and
// also its other flags as they are not applicable to install permissions.
if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
for (int userId : currentUserIds) {
if (permissionsState.grantRuntimePermission(bp, userId) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// Transfer the permission flags.
permissionsState.updatePermissionFlags(bp, userId,
flags, flags);
// If we granted the permission, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
}
}
} break;
default: {
if (packageOfInterest == null
|| packageOfInterest.equals(pkg.packageName)) {
Slog.w(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " because it was previously installed without");
}
} break;
}
} else {
if (permissionsState.revokeInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// Also drop the permission flags.
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
PackageManager.MASK_PERMISSION_FLAGS, 0);
changedInstallPermission = true;
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
} else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {
// Don't print warning for app op permissions, since it is fine for them
// not to be granted, there is a UI for the user to decide.
if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
Slog.w(TAG, "Not granting permission " + perm
+ " to package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
+ " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
+ ")");
}
}
}
}
String value = SystemProperties.get("persist.sys.vidoo.applist", null);
if(null != value){
String appList[] = value.split(",");
//String[] appList = {"com.sharpnow.vidoo.vrplayer", "com.dk.startbootfirst"};
if(Arrays.asList(appList).contains(pkg.packageName)) {
final int permsSize = pkg.requestedPermissions.size();
for (int i=0; i<permsSize; i++) {
final String name = pkg.requestedPermissions.get(i);
final BasePermission bp = mSettings.mPermissions.get(name);
if(null != bp && permissionsState.grantInstallPermission(bp) != PermissionsState.PERMISSION_OPERATION_FAILURE) {
Slog.d(TAG, "---perm&package grant permission " + name
+ " to package " + pkg.packageName);
changedInstallPermission = true;
}
}
}
}
if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&
!isSystemApp(ps) || isUpdatedSystemApp(ps)){
// This is the first that we have heard about this package, so the
// permissions we have now selected are fixed until explicitly
// changed.
ps.installPermissionsFixed = true;
}
// Persist the runtime permissions state for users with changes. If permissions
// were revoked because no app in the shared user declares them we have to
// write synchronously to avoid losing runtime permissions state.
for (int userId : changedRuntimePermissionUserIds) {
mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);
}
}