OSDN Git Service

Special handling of priv-apps in PMS.
authorNicolas Geoffray <ngeoffray@google.com>
Fri, 8 Sep 2017 12:01:40 +0000 (13:01 +0100)
committerNicolas Geoffray <ngeoffray@google.com>
Fri, 22 Sep 2017 14:54:10 +0000 (15:54 +0100)
If pm.dexopt.priv-apps is set to false, don't do any dexopt on it, and
check the APKs have uncompressed and aligned code.

bug: 30972906
bug: 63920015

Test: works as expected when pm.dexopt.priv-apps is true or false
Change-Id: I72a322defb459549617028e030f1aec997223af5

services/core/java/com/android/server/pm/PackageDexOptimizer.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/PackageManagerServiceUtils.java

index 5021f2f..7e9596a 100644 (file)
@@ -25,6 +25,7 @@ import android.os.Environment;
 import android.os.FileUtils;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.util.Log;
@@ -101,7 +102,17 @@ public class PackageDexOptimizer {
     }
 
     static boolean canOptimizePackage(PackageParser.Package pkg) {
-        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        // We do not dexopt a package with no code.
+        if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) {
+            return false;
+        }
+
+        // We do not dexopt a priv-app package when pm.dexopt.priv-apps is false.
+        if (pkg.isPrivilegedApp()) {
+            return SystemProperties.getBoolean("pm.dexopt.priv-apps", true);
+        }
+
+        return true;
     }
 
     /**
index 9f518c3..6f9c5cb 100644 (file)
@@ -10137,6 +10137,12 @@ public class PackageManagerService extends IPackageManager.Stub
 
         assertPackageIsValid(pkg, policyFlags, scanFlags);
 
+        if (Build.IS_DEBUGGABLE &&
+                pkg.isPrivilegedApp() &&
+                !SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) {
+            PackageManagerServiceUtils.logPackageHasUncompressedCode(pkg);
+        }
+
         // Initialize package source and resource directories
         final File scanFile = new File(pkg.codePath);
         final File destCodeFile = new File(pkg.applicationInfo.getCodePath());
index 9feee8c..ec9aa63 100644 (file)
@@ -19,6 +19,8 @@ package com.android.server.pm;
 import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
 import static com.android.server.pm.PackageManagerService.TAG;
 
+import com.android.internal.util.ArrayUtils;
+
 import android.annotation.NonNull;
 import android.app.AppGlobals;
 import android.content.Intent;
@@ -30,6 +32,8 @@ import android.os.UserHandle;
 import android.system.ErrnoException;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
+import android.util.jar.StrictJarFile;
 import dalvik.system.VMRuntime;
 import libcore.io.Libcore;
 
@@ -38,9 +42,11 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Predicate;
+import java.util.zip.ZipEntry;
 
 /**
  * Class containing helper methods for the PackageManagerService.
@@ -213,4 +219,59 @@ public class PackageManagerServiceUtils {
         }
         return false;
     }
+
+    /**
+     * Checks that the archive located at {@code fileName} has uncompressed dex file and so
+     * files that can be direclty mapped.
+     */
+    public static void logApkHasUncompressedCode(String fileName) {
+        StrictJarFile jarFile = null;
+        try {
+            jarFile = new StrictJarFile(fileName,
+                    false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/);
+            Iterator<ZipEntry> it = jarFile.iterator();
+            while (it.hasNext()) {
+                ZipEntry entry = it.next();
+                if (entry.getName().endsWith(".dex")) {
+                    if (entry.getMethod() != ZipEntry.STORED) {
+                        Slog.wtf(TAG, "APK " + fileName + " has compressed dex code " +
+                                entry.getName());
+                    } else if ((entry.getDataOffset() & 0x3) != 0) {
+                        Slog.wtf(TAG, "APK " + fileName + " has unaligned dex code " +
+                                entry.getName());
+                    }
+                } else if (entry.getName().endsWith(".so")) {
+                    if (entry.getMethod() != ZipEntry.STORED) {
+                        Slog.wtf(TAG, "APK " + fileName + " has compressed native code " +
+                                entry.getName());
+                    } else if ((entry.getDataOffset() & (0x1000 - 1)) != 0) {
+                        Slog.wtf(TAG, "APK " + fileName + " has unaligned native code " +
+                                entry.getName());
+                    }
+                }
+            }
+        } catch (IOException ignore) {
+            Slog.wtf(TAG, "Error when parsing APK " + fileName);
+        } finally {
+            try {
+                if (jarFile != null) {
+                    jarFile.close();
+                }
+            } catch (IOException ignore) {}
+        }
+        return;
+    }
+
+    /**
+     * Checks that the APKs in the given package have uncompressed dex file and so
+     * files that can be direclty mapped.
+     */
+    public static void logPackageHasUncompressedCode(PackageParser.Package pkg) {
+        logApkHasUncompressedCode(pkg.baseCodePath);
+        if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
+            for (int i = 0; i < pkg.splitCodePaths.length; i++) {
+                logApkHasUncompressedCode(pkg.splitCodePaths[i]);
+            }
+        }
+    }
 }