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

Commit e971d05c authored by Andy Mast's avatar Andy Mast
Browse files

Themes: Fix bad idmaps for system themes

For a system installed theme or a user who cleared his resource-cache,
there were empty idmaps for some packages.

[Details]
During startup PM could reach the theme package first before the target app was scanned in yet. This
would cause aapt to be skipped. Then when the target app is being installed in startup,
PM would try to create idmap pairs but it would fail since the resources from the theme
were not compiled for that target app.

Also cleaned up PM idmap/aapt creation a little bit more

Change-Id: I6a7dbd7c5d51a2d1336e3289c1e03bb3ed5d762e
parent 94186f84
Loading
Loading
Loading
Loading
+58 −43
Original line number Diff line number Diff line
@@ -100,8 +100,6 @@ import android.content.pm.ThemeUtils;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.res.Configuration;
import android.content.res.CustomTheme;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Binder;
@@ -143,7 +141,6 @@ import android.view.Display;
import android.view.WindowManager;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
@@ -179,9 +176,6 @@ import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
@@ -309,7 +303,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     * 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 = 1;
    private static final byte IDMAP_HASH_VERSION = 2;
    final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
            Process.THREAD_PRIORITY_BACKGROUND);
@@ -5375,50 +5369,30 @@ public class PackageManagerService extends IPackageManager.Stub {
            pkgSetting.setTimeStamp(scanFileTime);
            // Generate Idmaps if pkg is not a theme
            // Generate resources & idmaps if pkg is NOT a theme
            // We must compile resources here because during the initial boot process we may get
            // here before a default theme has had a chance to compile its resources
            if (pkg.mOverlayTargets.isEmpty() && mOverlays.containsKey(pkg.packageName)) {
                if (!createIdmapsForPackageLI(pkg)) {
                    Log.w(TAG, "Failed to create idmaps for " + pkg);
                }
            }
            // Generate Idmaps and res tables if pkg is a theme
            for(String target : pkg.mOverlayTargets) {
                insertIntoOverlayMap(target, pkg);
                if (!shouldCreateIdmap(mPackages.get(target), pkg)) {
                    continue;
                }
                if (pkg.mIsLegacyThemeApk) {
                    if (target != null) {
                HashMap<String, PackageParser.Package> themes = mOverlays.get(pkg.packageName);
                for(PackageParser.Package themePkg : themes.values()) {
                    try {
                            generateIdmapForLegacyTheme(target, pkg);
                        compileResourcesAndIdmapIfNeeded(pkg, themePkg);
                    } catch(Exception e) {
                            mLastScanError = PackageManager.INSTALL_FAILED_THEME_IDMAP_ERROR;
                            uninstallThemeForAllApps(pkg);
                            deletePackageLI(pkg.packageName, null, true,
                                    null, null, 0, null, false);
                            return null;
                        // Do not stop a pkg installation just because of one bad theme
                        // Also we don't break here because we should try to compile other themes
                        Log.e(TAG, "Unable to compile " + themePkg.packageName
                                + " for target " + pkg.packageName, e);
                    }
                }
                    continue;
            }
                // pkg is a theme and not legacy
            // Generate Idmaps and res tables if pkg is a theme
            for(String target : pkg.mOverlayTargets) {
                Exception failedException = null;
                insertIntoOverlayMap(target, pkg);
                try {
                    ThemeUtils.createCacheDirIfNotExists();
                    if (hasCommonResources(pkg)
                            && shouldCompileCommonResources(pkg)) {
                        ThemeUtils.createCacheDirIfNotExists();
                        ThemeUtils.createResourcesDirIfNotExists(COMMON_OVERLAY,
                                pkg.applicationInfo.publicSourceDir);
                        compileResources(COMMON_OVERLAY, pkg);
                        mAvailableCommonResources.put(pkg.packageName, System.currentTimeMillis());
                    }
                    ThemeUtils.createResourcesDirIfNotExists(target,
                            pkg.applicationInfo.publicSourceDir);
                    compileResources(target, pkg);
                    generateIdmap(target, pkg);
                    compileResourcesAndIdmapIfNeeded(mPackages.get(target), pkg);
                } catch(IdmapException e) {
                    failedException = e;
                    mLastScanError = PackageManager.INSTALL_FAILED_THEME_IDMAP_ERROR;
@@ -5440,6 +5414,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            }
            //Icon Packs need aapt too
            //TODO: No need to run aapt on icons for every startup...
            if (pkg.hasIconPack) {
                try {
                    ThemeUtils.createCacheDirIfNotExists();
@@ -5456,6 +5431,46 @@ public class PackageManagerService extends IPackageManager.Stub {
        return pkg;
    }
    private void compileResourcesAndIdmapIfNeeded(PackageParser.Package targetPkg,
                                               PackageParser.Package themePkg)
            throws IdmapException, AaptException, IOException, Exception
    {
        if (!shouldCreateIdmap(targetPkg, themePkg)) {
            return;
        }
        if (themePkg.mIsLegacyThemeApk) {
            generateIdmapForLegacyTheme(targetPkg.packageName, themePkg);
            return;
        }
        compileResourcesIfNeeded(targetPkg.packageName, themePkg);
        generateIdmap(targetPkg.packageName, themePkg);
    }
    private void compileResourcesIfNeeded(String target, PackageParser.Package pkg)
        throws AaptException, IOException, Exception
    {
        // Legacy themes are already compiled by aapt
        if (pkg.mIsLegacyThemeApk) {
            return;
        }
        ThemeUtils.createCacheDirIfNotExists();
        if (hasCommonResources(pkg)
                && shouldCompileCommonResources(pkg)) {
            ThemeUtils.createResourcesDirIfNotExists(COMMON_OVERLAY,
                    pkg.applicationInfo.publicSourceDir);
            compileResources(COMMON_OVERLAY, pkg);
            mAvailableCommonResources.put(pkg.packageName, System.currentTimeMillis());
        }
        ThemeUtils.createResourcesDirIfNotExists(target,
                pkg.applicationInfo.publicSourceDir);
        compileResources(target, pkg);
    }
    private void compileResources(String target, PackageParser.Package pkg) throws Exception {
        if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Compile resource table for " + pkg.packageName);
        //TODO: cleanup this hack. Modify aapt? Aapt uses the manifests package name