diff options
author | Kenny Root <kroot@google.com> | 2012-10-19 16:37:43 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-10-19 16:37:55 -0700 |
commit | 9bef3294d3660a85442829a25c9777e25d3c3cc8 (patch) | |
tree | e4ac279be0fcd872af6329c49239d2a70b40b582 | |
parent | 7e1664d44be6174c772fc3d2dc8ef9f5f5824390 (diff) | |
parent | cea3743499f4bb8e5f28a2e57686d7af313169c5 (diff) | |
download | frameworks_base-9bef3294d3660a85442829a25c9777e25d3c3cc8.zip frameworks_base-9bef3294d3660a85442829a25c9777e25d3c3cc8.tar.gz frameworks_base-9bef3294d3660a85442829a25c9777e25d3c3cc8.tar.bz2 |
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
9 files changed, 200 insertions, 104 deletions
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 @@ int install(const char *pkgname, uid_t uid, gid_t gid) 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 @@ int install(const char *pkgname, uid_t uid, gid_t gid) 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 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid) 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 @@ int delete_user_data(const char *pkgname, uid_t persona) 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 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) 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 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona) #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 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy) /* 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 @@ done: 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 (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { - ALOGE("library dir not written successfully: %s\n", strerror(errno)); + if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) { + ALOGE("cannot create package lib symlink origin path\n"); return -1; } - if (stat(dataDir, &s) < 0) return -1; + if (stat(pkgdir, &s) < 0) return -1; - if (chown(dataDir, AID_INSTALL, AID_INSTALL) < 0) { - ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); + if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { + ALOGE("failed to chown '%s': %s\n", pkgdir, 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_movefiles(char **arg, char reply[REPLY_MAX]) 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 @@ struct cmdinfo cmds[] = { { "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_string2(char *s1, char *s2); 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 get_size(const char *pkgname, int persona, const char *apkpath, const char * 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 @@ interface IMediaContainerService { /** 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { } 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class DefaultContainerService extends IntentService { 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 @@ public final class Installer { * @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 @@ public final class Installer { 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } } |