OSDN Git Service

Handle '&' in DexoptUtils#encodeClassLoader
authorShubham Ajmera <shubhamajmera@google.com>
Tue, 5 Sep 2017 17:20:41 +0000 (10:20 -0700)
committerAndreas Gampe <agampe@google.com>
Fri, 3 Nov 2017 02:31:09 +0000 (19:31 -0700)
For system apps, we pass '&' for CLC.
The method was treating this as a path as a result we were getting
wrong encoding for CLC.
This was causing dexopt failures for A/B OTA.

Removed the secondary dex file dexopt till we fixed it.

(cherry picked from commit 727aaa36b6914be3f340c97c991c93314d25c617)

Bug: 65067046
Test: runtest.py -x \
  frameworks/base/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
(cherry-picked from commit 557c054935c0864b42ce49541d12d32ae6a797bc)
Merged-In: I9aa440750c811676c86d8c6d0d451077d0edf5a0
Change-Id: I9aa440750c811676c86d8c6d0d451077d0edf5a0

services/core/java/com/android/server/pm/OtaDexoptService.java
services/core/java/com/android/server/pm/dex/DexoptUtils.java
services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java

index da6e26e..73ac057 100644 (file)
@@ -53,7 +53,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
     private final static boolean DEBUG_DEXOPT = true;
 
     // The synthetic library dependencies denoting "no checks."
-    private final static String[] NO_LIBRARIES = new String[] { "&" };
+    private final static String[] NO_LIBRARIES =
+            new String[] { PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK };
 
     // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
     // not bulk-delete unused apps' odex files.
@@ -325,7 +326,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
         mPackageManagerService.getDexManager().dexoptSecondaryDex(
                 new DexoptOptions(pkg.packageName, compilationReason,
                         DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX |
-                        DexoptOptions.DEXOPT_BOOT_COMPLETE));
+                                DexoptOptions.DEXOPT_BOOT_COMPLETE));
 
         return commands;
     }
index 6a7779a..c23b031 100644 (file)
@@ -20,6 +20,8 @@ import android.content.pm.ApplicationInfo;
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.server.pm.PackageDexOptimizer;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -236,10 +238,15 @@ public final class DexoptUtils {
     /**
      * Encodes a single class loader dependency starting from {@param path} and
      * {@param classLoaderName}.
+     * When classpath is {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns
+     * the same. This special property is used only during OTA.
      * NOTE: Keep this in sync with the dexopt expectations! Right now that is either "PCL[path]"
      * for a PathClassLoader or "DLC[path]" for a DelegateLastClassLoader.
      */
-    private static String encodeClassLoader(String classpath, String classLoaderName) {
+    /*package*/ static String encodeClassLoader(String classpath, String classLoaderName) {
+        if (classpath.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+            return classpath;
+        }
         String classLoaderDexoptEncoding = classLoaderName;
         if ("dalvik.system.PathClassLoader".equals(classLoaderName)) {
             classLoaderDexoptEncoding = "PCL";
@@ -251,10 +258,17 @@ public final class DexoptUtils {
 
     /**
      * Links to dependencies together in a format accepted by dexopt.
+     * For the special case when either of cl1 or cl2 equals
+     * {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns the same. This
+     * property is used only during OTA.
      * NOTE: Keep this in sync with the dexopt expectations! Right now that is a list of split
      * dependencies {@see encodeClassLoader} separated by ';'.
      */
-    private static String encodeClassLoaderChain(String cl1, String cl2) {
+    /*package*/ static String encodeClassLoaderChain(String cl1, String cl2) {
+        if (cl1.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK) ||
+                cl2.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+            return PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
+        }
         if (cl1.isEmpty()) return cl2;
         if (cl2.isEmpty()) return cl1;
         return cl1 + ";" + cl2;
index f0ac14d..34dc1ad 100644 (file)
 
 package com.android.server.pm.dex;
 
+import com.android.server.pm.PackageDexOptimizer;
+
+import static com.android.server.pm.PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.pm.ApplicationInfo;
 import android.support.test.filters.SmallTest;
@@ -368,4 +372,49 @@ public class DexoptUtilsTest {
         }
         assertTrue(gotException);
     }
+
+    @Test
+    public void testEncodeClassLoader() {
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.PathClassLoader"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DexClassLoader"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DelegateLastClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.PathClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.DexClassLoader"));
+        assertEquals("DLC[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.DelegateLastClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz", null));
+        assertEquals("abc[xyz]", DexoptUtils.encodeClassLoader("xyz", "abc"));
+
+        try {
+            DexoptUtils.encodeClassLoader(null, "abc");
+            fail(); // Exception should be caught.
+        } catch (NullPointerException expected) {}
+    }
+
+    @Test
+    public void testEncodeClassLoaderChain() {
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain(
+                SKIP_SHARED_LIBRARY_CHECK, "PCL[a]"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                SKIP_SHARED_LIBRARY_CHECK));
+        assertEquals("PCL[a];DLC[b]", DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                "DLC[b]"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                SKIP_SHARED_LIBRARY_CHECK));
+
+        try {
+            DexoptUtils.encodeClassLoaderChain("a", null);
+            fail(); // exception is expected
+        } catch (NullPointerException expected) {}
+
+        try {
+            DexoptUtils.encodeClassLoaderChain(null, "b");
+            fail(); // exception is expected
+        } catch (NullPointerException expected) {}
+    }
 }