Merge changes Ie3c8ca8d,Ia175b36d into jb-mr1-dev

* changes:
  Try to free cache before giving up on install
  Robustly add symlink and add for non-primary users
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a276225..8e4d7ed 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -36,6 +36,7 @@
     char pkgdir[PKG_PATH_MAX];
     char libsymlink[PKG_PATH_MAX];
     char applibdir[PKG_PATH_MAX];
+    struct stat libStat;
 
     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
@@ -67,6 +68,25 @@
         return -1;
     }
 
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
+            return -1;
+        }
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
+                return -1;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
+                return -1;
+            }
+        }
+    }
+
     if (symlink(applibdir, libsymlink) < 0) {
         ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
                 strerror(errno));
@@ -140,7 +160,7 @@
     if (stat(pkgdir, &s) < 0) return -1;
 
     if (s.st_uid != 0 || s.st_gid != 0) {
-        ALOGE("fixing uid of non-root pkg: %s %d %d\n", pkgdir, s.st_uid, s.st_gid);
+        ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
         return -1;
     }
 
@@ -165,18 +185,30 @@
     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
         return -1;
 
-    /* delete contents, excluding "lib", but not the directory itself */
-    return delete_dir_contents(pkgdir, 0, "lib");
+    /* delete contents AND directory, no exceptions */
+    return delete_dir_contents(pkgdir, 1, NULL);
 }
 
 int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
 {
     char pkgdir[PKG_PATH_MAX];
+    char applibdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
+    struct stat libStat;
 
     // Create the data dir for the package
     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
         return -1;
     }
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+        ALOGE("cannot create package lib symlink origin path\n");
+        return -1;
+    }
+    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
+        ALOGE("cannot create package lib symlink dest path\n");
+        return -1;
+    }
+
     if (mkdir(pkgdir, 0751) < 0) {
         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
         return -errno;
@@ -186,8 +218,41 @@
         unlink(pkgdir);
         return -errno;
     }
+
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
+            unlink(pkgdir);
+            return -1;
+        }
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                ALOGE("couldn't delete lib directory during install for non-primary: %s",
+                        libsymlink);
+                unlink(pkgdir);
+                return -1;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib directory during install for non-primary: %s",
+                        libsymlink);
+                unlink(pkgdir);
+                return -1;
+            }
+        }
+    }
+
+    if (symlink(applibdir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
+                applibdir, strerror(errno));
+        unlink(pkgdir);
+        return -1;
+    }
+
     if (chown(pkgdir, uid, uid) < 0) {
         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
         unlink(pkgdir);
         return -errno;
     }
@@ -195,6 +260,7 @@
 #ifdef HAVE_SELINUX
     if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
+        unlink(libsymlink);
         unlink(pkgdir);
         return -errno;
     }
@@ -254,7 +320,7 @@
                 /* Get the file stat */
                 if (stat(pkg_path, &s) < 0) continue;
                 /* Get the uid of the package */
-                ALOGI("Adding datadir for uid = %d\n", s.st_uid);
+                ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
                 uid = (uid_t) s.st_uid % PER_USER_RANGE;
                 /* Create the directory for the target */
                 make_user_data(name, uid + target_persona * PER_USER_RANGE,
@@ -991,75 +1057,71 @@
     return 0;
 }
 
-int linklib(const char* dataDir, const char* asecLibDir)
+int linklib(const char* pkgname, const char* asecLibDir, int userId)
 {
-    char libdir[PKG_PATH_MAX];
+    char pkgdir[PKG_PATH_MAX];
+    char libsymlink[PKG_PATH_MAX];
     struct stat s, libStat;
     int rc = 0;
 
-    const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
-    if (libdirLen >= PKG_PATH_MAX) {
-        ALOGE("library dir len too large");
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
+        ALOGE("cannot create package path\n");
+        return -1;
+    }
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
+        ALOGE("cannot create package lib symlink origin path\n");
         return -1;
     }
 
-    if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
-        ALOGE("library dir not written successfully: %s\n", strerror(errno));
+    if (stat(pkgdir, &s) < 0) return -1;
+
+    if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
+        ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
         return -1;
     }
 
-    if (stat(dataDir, &s) < 0) return -1;
-
-    if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) {
-        ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno));
-        return -1;
-    }
-
-    if (chmod(dataDir, 0700) < 0) {
-        ALOGE("linklib() 1: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+    if (chmod(pkgdir, 0700) < 0) {
+        ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
         rc = -1;
         goto out;
     }
 
-    if (lstat(libdir, &libStat) < 0) {
-        ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (S_ISDIR(libStat.st_mode)) {
-        if (delete_dir_contents(libdir, 1, 0) < 0) {
+    if (lstat(libsymlink, &libStat) < 0) {
+        if (errno != ENOENT) {
+            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
             rc = -1;
             goto out;
         }
-    } else if (S_ISLNK(libStat.st_mode)) {
-        if (unlink(libdir) < 0) {
-            rc = -1;
-            goto out;
+    } else {
+        if (S_ISDIR(libStat.st_mode)) {
+            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
+                rc = -1;
+                goto out;
+            }
+        } else if (S_ISLNK(libStat.st_mode)) {
+            if (unlink(libsymlink) < 0) {
+                ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
+                rc = -1;
+                goto out;
+            }
         }
     }
 
-    if (symlink(asecLibDir, libdir) < 0) {
-        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno));
-        rc = -errno;
-        goto out;
-    }
-
-    if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
-        unlink(libdir);
+    if (symlink(asecLibDir, libsymlink) < 0) {
+        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
+                strerror(errno));
         rc = -errno;
         goto out;
     }
 
 out:
-    if (chmod(dataDir, s.st_mode) < 0) {
-        ALOGE("linklib() 2: failed to chmod '%s': %s\n", dataDir, strerror(errno));
+    if (chmod(pkgdir, s.st_mode) < 0) {
+        ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
         rc = -errno;
     }
 
-    if (chown(dataDir, s.st_uid, s.st_gid) < 0) {
-        ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno));
+    if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
+        ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
         return -errno;
     }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 19298a3..21d674a 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -123,7 +123,7 @@
 
 static int do_linklib(char **arg, char reply[REPLY_MAX])
 {
-    return linklib(arg[0], arg[1]);
+    return linklib(arg[0], arg[1], atoi(arg[2]));
 }
 
 struct cmdinfo {
@@ -146,7 +146,7 @@
     { "getsize",              5, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
-    { "linklib",              2, do_linklib },
+    { "linklib",              3, do_linklib },
     { "mkuserdata",           3, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "cloneuserdata",        3, do_clone_user_data },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 2540dbe..0500c23 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -188,6 +188,7 @@
 char *build_string3(char *s1, char *s2, char *s3);
 
 int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
+int ensure_media_user_dirs(userid_t userid);
 
 /* commands.c */
 
@@ -209,4 +210,4 @@
 int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
-int linklib(const char* target, const char* source);
+int linklib(const char* target, const char* source, int userId);
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index c82834f7..03d3b22 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -36,4 +36,5 @@
     /** Return file system stats: [0] is total bytes, [1] is available bytes */
     long[] getFileSystemStats(in String path);
     void clearDirectory(in String directory);
+    long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
 }
diff --git a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
index fe4dd8e..76f0fe5 100644
--- a/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
+++ b/core/tests/coretests/apks/install_bad_dex/AndroidManifest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_loc">
+        package="com.android.frameworks.coretests.install_bad_dex">
 
     <application android:hasCode="true">
         <activity
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 56070ee..04f8009 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -981,19 +981,22 @@
         try {
             DeleteObserver observer = new DeleteObserver(pkgName);
 
-            getPm().deletePackage(pkgName, observer, flags);
+            getPm().deletePackage(pkgName, observer, flags | PackageManager.DELETE_ALL_USERS);
             observer.waitForCompletion(MAX_WAIT_TIME);
 
             assertUninstalled(info);
 
             // Verify we received the broadcast
-            long waitTime = 0;
-            while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
-                receiver.wait(WAIT_TIME_INCR);
-                waitTime += WAIT_TIME_INCR;
-            }
-            if (!receiver.isDone()) {
-                throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+            // TODO replace this with a CountDownLatch
+            synchronized (receiver) {
+                long waitTime = 0;
+                while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
+                    receiver.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if (!receiver.isDone()) {
+                    throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+                }
             }
             return receiver.received;
         } finally {
@@ -1331,7 +1334,7 @@
         }
 
         DeleteObserver observer = new DeleteObserver(packageName);
-        getPm().deletePackage(packageName, observer, 0);
+        getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
         observer.waitForCompletion(MAX_WAIT_TIME);
 
         try {
@@ -1357,7 +1360,7 @@
 
             if (info != null) {
                 DeleteObserver observer = new DeleteObserver(pkgName);
-                getPm().deletePackage(pkgName, observer, 0);
+                getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
                 observer.waitForCompletion(MAX_WAIT_TIME);
                 assertUninstalled(info);
             }
@@ -3126,7 +3129,7 @@
             int rawResId = apk2;
             Uri packageURI = getInstallablePackage(rawResId, outFile);
             PackageParser.Package pkg = parsePackage(packageURI);
-            getPm().deletePackage(pkg.packageName, null, 0);
+            getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
             // Check signatures now
             int match = mContext.getPackageManager().checkSignatures(
                     ip1.pkg.packageName, pkg.packageName);
@@ -3265,7 +3268,7 @@
             PackageManager pm = mContext.getPackageManager();
             // Delete app2
             PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
-            getPm().deletePackage(pkg.packageName, null, 0);
+            getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
             // Check signatures now
             int match = mContext.getPackageManager().checkSignatures(
                     ip1.pkg.packageName, pkg.packageName);
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 76b1ec6..cf56cba 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -259,6 +259,21 @@
                 eraseFiles(directory);
             }
         }
+
+        @Override
+        public long calculateInstalledSize(String packagePath, boolean isForwardLocked)
+                throws RemoteException {
+            final File packageFile = new File(packagePath);
+            try {
+                return calculateContainerSize(packageFile, isForwardLocked) * 1024 * 1024;
+            } catch (IOException e) {
+                /*
+                 * Okay, something failed, so let's just estimate it to be 2x
+                 * the file size. Note this will be 0 if the file doesn't exist.
+                 */
+                return packageFile.length() * 2;
+            }
+        }
     };
 
     public DefaultContainerService() {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 8b1e80f..71a6a01 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -369,7 +369,7 @@
      * @param nativeLibPath target native library path
      * @return -1 on error
      */
-    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
+    public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
         if (dataPath == null) {
             Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
             return -1;
@@ -382,6 +382,8 @@
         builder.append(dataPath);
         builder.append(' ');
         builder.append(nativeLibPath);
+        builder.append(' ');
+        builder.append(userId);
 
         return execute(builder.toString());
     }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index f59e30d..977437b 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -4088,39 +4088,42 @@
                         Log.i(TAG, "removed obsolete native libraries for system package "
                                 + path);
                     }
-                } else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
-                    // Update native library dir if it starts with /data/data
-                    if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
-                        setInternalAppNativeLibraryPath(pkg, pkgSetting);
-                        nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
-                    }
+                } else {
+                    if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+                        /*
+                         * Update native library dir if it starts with
+                         * /data/data
+                         */
+                        if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
+                            setInternalAppNativeLibraryPath(pkg, pkgSetting);
+                            nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+                        }
 
-                    try {
-                        if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
-                            Slog.e(TAG, "Unable to copy native libraries");
+                        try {
+                            if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+                                Slog.e(TAG, "Unable to copy native libraries");
+                                mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                                return null;
+                            }
+                        } catch (IOException e) {
+                            Slog.e(TAG, "Unable to copy native libraries", e);
                             mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                             return null;
                         }
-                    } catch (IOException e) {
-                        Slog.e(TAG, "Unable to copy native libraries", e);
-                        mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-                        return null;
                     }
 
-                    if (mInstaller.linkNativeLibraryDirectory(dataPathString,
-                            pkg.applicationInfo.nativeLibraryDir) == -1) {
-                        Slog.e(TAG, "Unable to link native library directory");
-                        mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-                        return null;
-                    }
-                } else {
                     Slog.i(TAG, "Linking native library dir for " + path);
-                    int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
-                            pkg.applicationInfo.nativeLibraryDir);
-                    if (ret < 0) {
-                        Slog.w(TAG, "Failed linking native library dir for " + path);
-                        mLastScanError = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                        return null;
+                    final int[] userIds = sUserManager.getUserIds();
+                    synchronized (mInstallLock) {
+                        for (int userId : userIds) {
+                            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+                                    pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
+                                Slog.w(TAG, "Failed linking native library dir (user=" + userId
+                                        + ")");
+                                mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                                return null;
+                            }
+                        }
                     }
                 }
             } catch (IOException ioe) {
@@ -6327,8 +6330,23 @@
 
                     if (packageFile != null) {
                         // Remote call to find out default install location
-                        pkgLite = mContainerService.getMinimalPackageInfo(
-                                packageFile.getAbsolutePath(), flags, lowThreshold);
+                        final String packageFilePath = packageFile.getAbsolutePath();
+                        pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
+                                lowThreshold);
+
+                        /*
+                         * If we have too little free space, try to free cache
+                         * before giving up.
+                         */
+                        if (pkgLite.recommendedInstallLocation
+                                == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
+                            final long size = mContainerService.calculateInstalledSize(
+                                    packageFilePath, isForwardLocked());
+                            if (mInstaller.freeCache(size + lowThreshold) >= 0) {
+                                pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
+                                        flags, lowThreshold);
+                            }
+                        }
                     }
                 } finally {
                     mContext.revokeUriPermission(mPackageURI,
@@ -6350,12 +6368,12 @@
                     ret = PackageManager.INSTALL_FAILED_INVALID_URI;
                 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
                     ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
-                } else if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
-                    ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
                 } else {
                     // Override with defaults if needed.
                     loc = installLocationPolicy(pkgLite, flags);
-                    if (!onSd && !onInt) {
+                    if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
+                        ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
+                    } else if (!onSd && !onInt) {
                         // Override install location with flags
                         if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                             // Set the flag to install on external media.
@@ -9959,20 +9977,14 @@
                                     final File newNativeDir = new File(newNativePath);
 
                                     if (!isForwardLocked(pkg) && !isExternal(pkg)) {
-                                        synchronized (mInstallLock) {
-                                            if (mInstaller.linkNativeLibraryDirectory(
-                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
-                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                            }
-                                        }
-                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
-                                                newCodePath), newNativeDir);
-                                    } else {
-                                        synchronized (mInstallLock) {
-                                            if (mInstaller.linkNativeLibraryDirectory(
-                                                    pkg.applicationInfo.dataDir, newNativePath) < 0) {
-                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                            }
+                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+                                                new File(newCodePath), newNativeDir);
+                                    }
+                                    final int[] users = sUserManager.getUserIds();
+                                    for (int user : users) {
+                                        if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+                                                newNativePath, user) < 0) {
+                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
                                         }
                                     }