Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36006740 authored by d34d's avatar d34d Committed by Clark Scheff
Browse files

Store manifest hash code in PackageParser.Package

Optimize the way we calculate the manifest hash code and also store
this value in PackageParser.Package for faster lookups.  The manifest
hash code value will also be updated when packages are updated.

Change-Id: I111e8831c5b96d847e886071e99b1cefd075befc
parent a7a7c5ac
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1140,6 +1140,7 @@ public class PackageParser {
                final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
                if (je != null) {
                    pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je));
                    pkg.manifestHashCode = ThemeUtils.getPackageHashCode(pkg);
                }
            } finally {
                jarFile.close();
@@ -4594,6 +4595,7 @@ public class PackageParser {
        public boolean mTrustedOverlay;

        public boolean hasIconPack;
        public int manifestHashCode;

        /**
         * Data used to feed the KeySetManagerService
+18 −0
Original line number Diff line number Diff line
@@ -121,6 +121,13 @@ public class ThemeUtils {
            "/data/data/com.android.providers.settings/databases/settings.db";
    private static final String SETTINGS_SECURE_TABLE = "secure";

    /**
     * IDMAP hash version code used to alter the resulting hash and force recreating
     * of the idmap.  This value should be changed whenever there is a need to force
     * an update to all idmaps.
     */
    private static final byte IDMAP_HASH_VERSION = 3;

    // Actions in manifests which identify legacy icon packs
    public static final String[] sSupportedActions = new String[] {
            "org.adw.launcher.THEMES",
@@ -758,4 +765,15 @@ public class ThemeUtils {
                || ThemeConfig.SYSTEMUI_STATUS_BAR_PKG.equals(component)
                || ThemeConfig.SYSTEMUI_NAVBAR_PKG.equals(component));
    }

    /**
     * Get a 32 bit hashcode for the given package.
     * @param pkg
     * @return
     */
    public static int getPackageHashCode(PackageParser.Package pkg) {
        int hash = pkg.manifestDigest != null ? pkg.manifestDigest.hashCode() : 0;
        hash = 31 * hash + IDMAP_HASH_VERSION;
        return hash;
    }
}
+23 −60
Original line number Diff line number Diff line
@@ -452,16 +452,8 @@ public class PackageManagerService extends IPackageManager.Stub {
    private static final String COMMON_OVERLAY = ThemeUtils.COMMON_RES_TARGET;
    private static final long PACKAGE_HASH_EXPIRATION = 3*60*1000; // 3 minutes
    private static final long COMMON_RESOURCE_EXPIRATION = 3*60*1000; // 3 minutes
    /**
     * IDMAP hash version code used to alter the resulting hash and force recreating
     * of the idmap.  This value should be changed whenever there is a need to force
     * an update to all idmaps.
     */
    private static final byte IDMAP_HASH_VERSION = 3;
    /**
     * The offset in bytes to the beginning of the hashes in an idmap
     */
@@ -875,9 +867,6 @@ public class PackageManagerService extends IPackageManager.Stub {
    private IconPackHelper mIconPackHelper;
    private Map<String, Pair<Integer, Long>> mPackageHashes =
            new ArrayMap<String, Pair<Integer, Long>>();
    private Map<String, Long> mAvailableCommonResources = new ArrayMap<String, Long>();
    private ThemeConfig mBootThemeConfig;
@@ -5727,7 +5716,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final String cachePath =
                ThemeUtils.getTargetCacheDir(pkgName, opkg.packageName);
        if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, cachePath, sharedGid,
                getPackageHashCode(pkg), getPackageHashCode(opkg)) != 0) {
                pkg.manifestHashCode, opkg.manifestHashCode) != 0) {
            Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath +
                    " and " + opkg.baseCodePath);
            return false;
@@ -5849,6 +5838,12 @@ public class PackageManagerService extends IPackageManager.Stub {
                // if the package appears to be unchanged.
                pkg.mSignatures = ps.signatures.mSignatures;
                pkg.mSigningKeys = signingKs;
                // Collect manifest digest
                try{
                    pp.collectManifestDigest(pkg);
                } catch (PackageParserException e) {
                    throw PackageManagerException.from(e);
                }
                return;
            }
@@ -6803,6 +6798,16 @@ public class PackageManagerService extends IPackageManager.Stub {
            pkg.mAdoptPermissions = null;
        }
        // collect manifest digest which includes getting manifest hash code for themes
        if (pkg.manifestDigest == null || pkg.manifestHashCode == 0) {
            PackageParser pp = new PackageParser();
            try {
                pp.collectManifestDigest(pkg);
            } catch (PackageParserException e) {
                Slog.w(TAG, "Unable to collect manifest digest", e);
            }
        }
        // writer
        synchronized (mPackages) {
            if (pkg.mSharedUserId != null) {
@@ -8066,7 +8071,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            in = new FileInputStream(hashFile);
            dataInput = new DataInputStream(in);
            int storedHashCode = dataInput.readInt();
            int actualHashCode = getPackageHashCode(pkg);
            int actualHashCode = pkg.manifestHashCode;
            return storedHashCode != actualHashCode;
        } catch(IOException e) {
            // all is good enough for government work here,
@@ -8135,7 +8140,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        DataOutputStream dataOut = null;
        try {
            createTempManifest(pkg.packageName);
            int code = getPackageHashCode(pkg);
            int code = pkg.manifestHashCode;
            String hashFile = ThemeUtils.getIconHashFile(pkg.packageName);
            out = new FileOutputStream(hashFile);
            dataOut = new DataOutputStream(out);
@@ -8294,13 +8299,14 @@ public class PackageManagerService extends IPackageManager.Stub {
                                      PackageParser.Package overlayPkg) {
        if (targetPkg == null || targetPkg.baseCodePath == null || overlayPkg == null) return false;
        int targetHash = getPackageHashCode(targetPkg);
        int overlayHash = getPackageHashCode(overlayPkg);
        int targetHash = targetPkg.manifestHashCode;
        int overlayHash = overlayPkg.manifestHashCode;
        File idmap =
                new File(ThemeUtils.getIdmapPath(targetPkg.packageName, overlayPkg.packageName));
        if (!idmap.exists())
        if (!idmap.exists()) {
            return true;
        }
        int[] hashes;
        try {
@@ -8353,49 +8359,6 @@ public class PackageManagerService extends IPackageManager.Stub {
        return times;
    }
    /**
     * Get a 32 bit hashcode for the given package.
     * @param pkg
     * @return
     */
    private int getPackageHashCode(PackageParser.Package pkg) {
        Pair<Integer, Long> p = mPackageHashes.get(pkg.packageName);
        if (p != null && (System.currentTimeMillis() - p.second < PACKAGE_HASH_EXPIRATION)) {
            return p.first;
        }
        if (p != null) {
            mPackageHashes.remove(p);
        }
        byte[] crc = getFileCrC(pkg.baseCodePath);
        if (crc == null) return 0;
        p = new Pair(Arrays.hashCode(ByteBuffer.wrap(crc).put(IDMAP_HASH_VERSION).array()),
                System.currentTimeMillis());
        mPackageHashes.put(pkg.packageName, p);
        return p.first;
    }
    private byte[] getFileCrC(String path) {
        ZipFile zfile = null;
        try {
            zfile = new ZipFile(path);
            ZipEntry entry = zfile.getEntry("META-INF/MANIFEST.MF");
            if (entry == null) {
                Log.e(TAG, "Unable to get MANIFEST.MF from " + path);
                return null;
            }
            long crc = entry.getCrc();
            if (crc == -1) Log.e(TAG, "Unable to get CRC for " + path);
            return ByteBuffer.allocate(8).putLong(crc).array();
        } catch (Exception e) {
        } finally {
            IoUtils.closeQuietly(zfile);
        }
        return null;
    }
    private void setUpCustomResolverActivity(PackageParser.Package pkg) {
        synchronized (mPackages) {
            mResolverReplaced = true;