在\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"); }