OSDN Git Service

Handle /oem and /vendor as well
authorChristopher Tate <ctate@google.com>
Fri, 18 Apr 2014 19:24:57 +0000 (12:24 -0700)
committerNarayan Kamath <narayan@google.com>
Thu, 1 May 2014 13:51:33 +0000 (13:51 +0000)
Bug 13170859

(cherry-picked from commit 740888f62eae158d5775be716620f0d56d87f587)

Change-Id: I7b5e206697fcbec146cac6cd83fca5c583a8cbd7

core/java/android/os/Environment.java
services/java/com/android/server/pm/PackageManagerService.java

index b5413db..7bf7367 100644 (file)
@@ -42,6 +42,8 @@ public class Environment {
     private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE";
     private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE";
     private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
+    private static final String ENV_OEM_ROOT = "OEM_ROOT";
+    private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -56,6 +58,8 @@ public class Environment {
     public static final String DIRECTORY_ANDROID = DIR_ANDROID;
 
     private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
+    private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
+    private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");
 
     private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
@@ -244,6 +248,25 @@ public class Environment {
     }
 
     /**
+     * Return root directory of the "oem" partition holding OEM customizations,
+     * if any. If present, the partition is mounted read-only.
+     *
+     * @hide
+     */
+    public static File getOemDirectory() {
+        return DIR_OEM_ROOT;
+    }
+
+    /**
+     * Return root directory of the "vendor" partition that holds vendor-provided
+     * software that should persist across simple reflashing of the "system" partition.
+     * @hide
+     */
+    public static File getVendorDirectory() {
+        return DIR_VENDOR_ROOT;
+    }
+
+    /**
      * Gets the system directory available for secure storage.
      * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
      * Otherwise, it returns the unencrypted /data/system directory.
index 2a16d89..be2bd18 100755 (executable)
@@ -4322,17 +4322,6 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         // writer
         synchronized (mPackages) {
-            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
-                // Check all shared libraries and map to their actual file path.
-                // We only do this here for apps not on a system dir, because those
-                // are the only ones that can fail an install due to this.  We
-                // will take care of the system apps by updating all of their
-                // library paths after the scan is done.
-                if (!updateSharedLibrariesLPw(pkg, null)) {
-                    return null;
-                }
-            }
-
             if (pkg.mSharedUserId != null) {
                 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
                 if (suid == null) {
@@ -4443,6 +4432,17 @@ public class PackageManagerService extends IPackageManager.Stub {
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
+            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                // Check all shared libraries and map to their actual file path.
+                // We only do this here for apps not on a system dir, because those
+                // are the only ones that can fail an install due to this.  We
+                // will take care of the system apps by updating all of their
+                // library paths after the scan is done.
+                if (!updateSharedLibrariesLPw(pkg, null)) {
+                    return null;
+                }
+            }
+
             if (mFoundPolicyFile) {
                 SELinuxMMAC.assignSeinfoValue(pkg);
             }
@@ -5241,6 +5241,37 @@ public class PackageManagerService extends IPackageManager.Stub {
         }
     }
 
+    private String calculateApkRoot(final File codePath) {
+        final File codeRoot;
+        if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
+            codeRoot = Environment.getRootDirectory();
+        } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) {
+            codeRoot = Environment.getRootDirectory();
+        } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
+            codeRoot = Environment.getVendorDirectory();
+        } else {
+            // Unrecognized code path; take its top real segment as the apk root:
+            // e.g. /something/app/blah.apk => /something
+            try {
+                File f = codePath.getCanonicalFile();
+                File parent = f.getParentFile();    // non-null because codePath is a file
+                File tmp;
+                while ((tmp = parent.getParentFile()) != null) {
+                    f = parent;
+                    parent = tmp;
+                }
+                codeRoot = f;
+                Slog.w(TAG, "Unrecognized code path "
+                        + codePath + " - using " + codeRoot);
+            } catch (IOException e) {
+                // Can't canonicalize the lib path -- shenanigans?
+                Slog.w(TAG, "Can't canonicalize code path " + codePath);
+                return Environment.getRootDirectory().getPath();
+            }
+        }
+        return codeRoot.getPath();
+    }
+
     // This is the initial scan-time determination of how to handle a given
     // package for purposes of native library location.
     private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
@@ -5252,11 +5283,10 @@ public class PackageManagerService extends IPackageManager.Stub {
         if (bundledApk) {
             // If "/system/lib64/apkname" exists, assume that is the per-package
             // native library directory to use; otherwise use "/system/lib/apkname".
-            File lib64 = new File(Environment.getRootDirectory(), LIB64_DIR_NAME);
+            String apkRoot = calculateApkRoot(pkgSetting.codePath);
+            File lib64 = new File(apkRoot, LIB64_DIR_NAME);
             File packLib64 = new File(lib64, apkName);
-            libDir = (packLib64.exists())
-                    ? lib64
-                    : new File(Environment.getRootDirectory(), LIB_DIR_NAME);
+            libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
         } else {
             libDir = mAppLibInstallDir;
         }