在\frameworks\base\services\java\com\android\server\pm目录下的Settings.java中,提供了隐藏apk的方法。
被隐藏的apk存储在mDisabledSysPackages中:
// List of replaced system applications
private final HashMap<String, PackageSetting> mDisabledSysPackages =
new HashMap<String, PackageSetting>();
disableSystemPackageLPw方法可以隐藏apk,它会根据packagename去隐藏对应的apk:
boolean disableSystemPackageLPw(String name) {
//一定能在mPackages中找到需要隐藏的apk对应的PackageSetting
final PackageSetting p = mPackages.get(name);
if(p == null) {
Log.w(PackageManagerService.TAG, "Package:"+name+" is not an installed package");
return false;
}
//在mDisabledSysPackages中不能找到这个apk的信息
final PackageSetting dp = mDisabledSysPackages.get(name);
// always make sure the system package code and resource paths dont change
if (dp == null) {
//设置标志位FLAG_UPDATED_SYSTEM_APP
if((p.pkg != null) && (p.pkg.applicationInfo != null) &&
((p.pkgFlags & ApplicationInfo.FLAG_UNINSTALL_APP) != 0)) {
p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
//添加到mDisabledSysPackages中
mDisabledSysPackages.put(name, p);
// a little trick... when we install the new package, we don't
// want to modify the existing PackageSetting for the built-in
// version. so at this point we need a new PackageSetting that
// is okay to muck with.
PackageSetting newp = new PackageSetting(p);
replacePackageLPw(name, newp);
return true;
}
return false;
}
PackageSetting enableSystemPackageLPw(String name) {
//在mDisabledSysPackages中查找,必须能查找到
PackageSetting p = mDisabledSysPackages.get(name);
if(p == null) {
Log.w(PackageManagerService.TAG, "Package:"+name+" is not disabled");
return null;
}
// 清除标志位FLAG_UPDATED_SYSTEM_APP
if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
//add package
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags);
//从mDisabledSysPackages中删除改apk
mDisabledSysPackages.remove(name);
return ret;
}
boolean isDisabledSystemPackageLPr(String name) {
return mDisabledSysPackages.containsKey(name);
}
void removeDisabledSystemPackageLPw(String name) {
mDisabledSysPackages.remove(name);
}
writeDisabledSysPackageLPr方法会把mDisabledSysPackages写入到packages.xml文件中,以updated-package开始和结束,标记这是被隐藏的apk。
for (final PackageSetting pkg : mDisabledSysPackages.values()) {
writeDisabledSysPackageLPr(serializer, pkg);
}
void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg)
throws java.io.IOException {
serializer.startTag(null, "updated-package");
serializer.attribute(null, ATTR_NAME, pkg.name);
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
serializer.attribute(null, "codePath", pkg.codePathString);
serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
/// M: [Vendor] Add package flags recording in disabled pacakge element
serializer.attribute(null, "flags", String.valueOf(pkg.pkgFlags));
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
if (pkg.nativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
}
if (pkg.sharedUser == null) {
serializer.attribute(null, "userId", Integer.toString(pkg.appId));
} else {
serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId));
}
serializer.startTag(null, "perms");
if (pkg.sharedUser == null) {
// If this is a shared user, the permissions will
// be written there. We still need to write an
// empty permissions list so permissionsFixed will
// be set.
for (final String name : pkg.grantedPermissions) {
BasePermission bp = mPermissions.get(name);
if (bp != null) {
// We only need to write signature or system permissions but
// this wont
// match the semantics of grantedPermissions. So write all
// permissions.
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.endTag(null, TAG_ITEM);
}
}
}
serializer.endTag(null, "perms");
serializer.endTag(null, "updated-package");
}