am 2e7d0cb5: Merge "Move native libraries to /data/app-lib" into jb-mr1-dev

* commit '2e7d0cb592381e2efd9b86d5ee38d8ec657b6a1a':
  Move native libraries to /data/app-lib
This commit is contained in:
Kenny Root
2012-09-10 17:07:42 -07:00
committed by Android Git Automerger
3 changed files with 151 additions and 48 deletions

View File

@@ -72,6 +72,8 @@ public class PackageManagerTests extends AndroidTestCase {
public final long WAIT_TIME_INCR = 5 * 1000; public final long WAIT_TIME_INCR = 5 * 1000;
private static final String APP_LIB_DIR_PREFIX = "/data/app-lib/";
private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/"; private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/";
private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO; private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
@@ -433,7 +435,7 @@ public class PackageManagerTests extends AndroidTestCase {
assertEquals(srcPath, appInstallPath); assertEquals(srcPath, appInstallPath);
assertEquals(publicSrcPath, appInstallPath); assertEquals(publicSrcPath, appInstallPath);
assertStartsWith("Native library should point to shared lib directory", assertStartsWith("Native library should point to shared lib directory",
dataDir.getPath(), new File(APP_LIB_DIR_PREFIX, info.packageName).getPath(),
info.nativeLibraryDir); info.nativeLibraryDir);
assertDirOwnerGroupPerms( assertDirOwnerGroupPerms(
"Native library directory should be owned by system:system and 0755", "Native library directory should be owned by system:system and 0755",

View File

@@ -359,6 +359,14 @@ class Installer {
return execute("movefiles"); return execute("movefiles");
} }
/**
* Links the native library directory in an application's directory to its
* real location.
*
* @param dataPath data directory where the application is
* @param nativeLibPath target native library path
* @return -1 on error
*/
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) { public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
if (dataPath == null) { if (dataPath == null) {
Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null"); Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");

View File

@@ -25,6 +25,11 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt; import static com.android.internal.util.ArrayUtils.removeInt;
import static libcore.io.OsConstants.S_ISLNK; import static libcore.io.OsConstants.S_ISLNK;
import static libcore.io.OsConstants.S_IRWXU;
import static libcore.io.OsConstants.S_IRGRP;
import static libcore.io.OsConstants.S_IXGRP;
import static libcore.io.OsConstants.S_IROTH;
import static libcore.io.OsConstants.S_IXOTH;
import com.android.internal.app.IMediaContainerService; import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity; import com.android.internal.app.ResolverActivity;
@@ -147,6 +152,7 @@ import java.util.Set;
import libcore.io.ErrnoException; import libcore.io.ErrnoException;
import libcore.io.IoUtils; import libcore.io.IoUtils;
import libcore.io.Libcore; import libcore.io.Libcore;
import libcore.io.OsConstants;
import libcore.io.StructStat; import libcore.io.StructStat;
/** /**
@@ -276,7 +282,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// This is the object monitoring mDrmAppPrivateInstallDir. // This is the object monitoring mDrmAppPrivateInstallDir.
final FileObserver mDrmAppInstallObserver; final FileObserver mDrmAppInstallObserver;
// Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
// LOCK HELD. Can be called with mInstallLock held. // LOCK HELD. Can be called with mInstallLock held.
final Installer mInstaller; final Installer mInstaller;
@@ -286,6 +292,12 @@ public class PackageManagerService extends IPackageManager.Stub {
final File mAppInstallDir; final File mAppInstallDir;
final File mDalvikCacheDir; final File mDalvikCacheDir;
/**
* Directory to which applications installed internally have native
* libraries copied.
*/
private File mAppLibInstallDir;
// Directory containing the private parts (e.g. code and non-resource assets) of forward-locked // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
// apps. // apps.
final File mDrmAppPrivateInstallDir; final File mDrmAppPrivateInstallDir;
@@ -1215,6 +1227,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
mAppInstallDir = new File(dataDir, "app"); mAppInstallDir = new File(dataDir, "app");
mAppLibInstallDir = new File(dataDir, "app-lib");
//look for any incomplete package installations //look for any incomplete package installations
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr(); ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//clean up list //clean up list
@@ -3607,6 +3620,13 @@ public class PackageManagerService extends IPackageManager.Stub {
res = resInner; res = resInner;
} }
} }
final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
if (!nativeLibraryFile.delete()) {
Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
}
return res; return res;
} }
@@ -4048,9 +4068,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/ */
if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
if (pkgSetting.nativeLibraryPathString == null) { if (pkgSetting.nativeLibraryPathString == null) {
final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath(); setInternalAppNativeLibraryPath(pkg, pkgSetting);
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
pkgSetting.nativeLibraryPathString = nativeLibraryPath;
} else { } else {
pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
} }
@@ -4072,7 +4090,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/ */
if (pkg.applicationInfo.nativeLibraryDir != null) { if (pkg.applicationInfo.nativeLibraryDir != null) {
try { try {
final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir); File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
final String dataPathString = dataPath.getCanonicalPath(); final String dataPathString = dataPath.getCanonicalPath();
if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) { if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
@@ -4087,30 +4105,31 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.i(TAG, "removed obsolete native libraries for system package " Log.i(TAG, "removed obsolete native libraries for system package "
+ path); + path);
} }
} else if (nativeLibraryDir.getParentFile().getCanonicalPath() } else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
.equals(dataPathString)) { // Update native library dir if it starts with /data/data
/* if (nativeLibraryDir.getParent().startsWith(dataPathString)) {
* Make sure the native library dir isn't a symlink to setInternalAppNativeLibraryPath(pkg, pkgSetting);
* something. If it is, ask installd to remove it and create nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
* a directory so we can copy to it afterwards.
*/
boolean isSymLink;
try {
isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
} catch (ErrnoException e) {
// This shouldn't happen, but we'll fail-safe.
isSymLink = true;
}
if (isSymLink) {
mInstaller.unlinkNativeLibraryDirectory(dataPathString);
} }
/* try {
* If this is an internal application or our if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
* nativeLibraryPath points to our data directory, unpack Slog.e(TAG, "Unable to copy native libraries");
* the libraries if necessary. mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
*/ return null;
NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); }
} 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 { } else {
Slog.i(TAG, "Linking native library dir for " + path); Slog.i(TAG, "Linking native library dir for " + path);
int ret = mInstaller.linkNativeLibraryDirectory(dataPathString, int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
@@ -4122,7 +4141,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
} }
} catch (IOException ioe) { } catch (IOException ioe) {
Log.e(TAG, "Unable to get canonical file " + ioe.toString()); Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
} }
} }
pkg.mScanPath = path; pkg.mScanPath = path;
@@ -4437,6 +4456,37 @@ public class PackageManagerService extends IPackageManager.Stub {
return pkg; return pkg;
} }
private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
PackageSetting pkgSetting) {
final String apkLibPath = getApkName(pkgSetting.codePathString);
final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
pkgSetting.nativeLibraryPathString = nativeLibraryPath;
}
private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
throws IOException {
if (!nativeLibraryDir.isDirectory()) {
nativeLibraryDir.delete();
if (!nativeLibraryDir.mkdir()) {
throw new IOException("Cannot create " + nativeLibraryDir.getPath());
}
try {
Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
| S_IXOTH);
} catch (ErrnoException e) {
throw new IOException("Cannot chmod native library directory "
+ nativeLibraryDir.getPath(), e);
}
}
/*
* If this is an internal application or our nativeLibraryPath points to
* the app-lib directory, unpack the libraries if necessary.
*/
return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
}
private void killApplication(String pkgName, int appId) { private void killApplication(String pkgName, int appId) {
// Request the ActivityManager to kill the process(only for existing packages) // Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older // so that we do not end up in a confused state while the user is still using the older
@@ -6737,7 +6787,7 @@ public class PackageManagerService extends IPackageManager.Stub {
String apkName = getNextCodePath(null, pkgName, ".apk"); String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath(); codeFileName = new File(installDir, apkName + ".apk").getPath();
resourceFileName = getResourcePathFromCodePath(); resourceFileName = getResourcePathFromCodePath();
libraryPath = new File(dataDir, LIB_DIR_NAME).getPath(); libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
} }
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -6774,6 +6824,7 @@ public class PackageManagerService extends IPackageManager.Stub {
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
codeFileName = createTempPackageFile(installDir).getPath(); codeFileName = createTempPackageFile(installDir).getPath();
resourceFileName = getResourcePathFromCodePath(); resourceFileName = getResourcePathFromCodePath();
libraryPath = getLibraryPathFromCodePath();
created = true; created = true;
} }
@@ -6828,6 +6879,23 @@ public class PackageManagerService extends IPackageManager.Stub {
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
} }
} }
final File nativeLibraryFile = new File(getNativeLibraryPath());
Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
if (nativeLibraryFile.exists()) {
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
nativeLibraryFile.delete();
}
try {
int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
}
return ret; return ret;
} }
@@ -6845,6 +6913,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else { } else {
final File oldCodeFile = new File(getCodePath()); final File oldCodeFile = new File(getCodePath());
final File oldResourceFile = new File(getResourcePath()); final File oldResourceFile = new File(getResourcePath());
final File oldLibraryFile = new File(getNativeLibraryPath());
// Rename APK file based on packageName // Rename APK file based on packageName
final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk"); final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
@@ -6859,7 +6928,20 @@ public class PackageManagerService extends IPackageManager.Stub {
if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) { if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
return false; return false;
} }
resourceFileName = getResourcePathFromCodePath(); resourceFileName = newResFile.getPath();
// Rename library path
final File newLibraryFile = new File(getLibraryPathFromCodePath());
if (newLibraryFile.exists()) {
NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
newLibraryFile.delete();
}
if (!oldLibraryFile.renameTo(newLibraryFile)) {
Slog.e(TAG, "Cannot rename native library directory "
+ oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
return false;
}
libraryPath = newLibraryFile.getPath();
// Attempt to set permissions // Attempt to set permissions
if (!setPermissions()) { if (!setPermissions()) {
@@ -6910,8 +6992,15 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
} }
private String getLibraryPathFromCodePath() {
return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
}
@Override @Override
String getNativeLibraryPath() { String getNativeLibraryPath() {
if (libraryPath == null) {
libraryPath = getLibraryPathFromCodePath();
}
return libraryPath; return libraryPath;
} }
@@ -6937,6 +7026,15 @@ public class PackageManagerService extends IPackageManager.Stub {
publicSourceFile.delete(); publicSourceFile.delete();
} }
} }
if (libraryPath != null) {
File nativeLibraryFile = new File(libraryPath);
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
if (!nativeLibraryFile.delete()) {
Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
}
}
return ret; return ret;
} }
@@ -9779,31 +9877,26 @@ public class PackageManagerService extends IPackageManager.Stub {
final String newNativePath = mp.targetArgs final String newNativePath = mp.targetArgs
.getNativeLibraryPath(); .getNativeLibraryPath();
try { final File newNativeDir = new File(newNativePath);
final File newNativeDir = new File(newNativePath);
final String libParentDir = newNativeDir.getParentFile() if (!isForwardLocked(pkg) && !isExternal(pkg)) {
.getCanonicalPath(); synchronized (mInstallLock) {
if (newNativeDir.getParentFile().getCanonicalPath() if (mInstaller.linkNativeLibraryDirectory(
.equals(pkg.applicationInfo.dataDir)) { pkg.applicationInfo.dataDir, newNativePath) < 0) {
if (mInstaller returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
.unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { }
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; }
} else { NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
NativeLibraryHelper.copyNativeBinariesIfNeededLI( newCodePath), newNativeDir);
new File(newCodePath), newNativeDir); } else {
} synchronized (mInstallLock) {
} else {
if (mInstaller.linkNativeLibraryDirectory( if (mInstaller.linkNativeLibraryDirectory(
pkg.applicationInfo.dataDir, newNativePath) < 0) { pkg.applicationInfo.dataDir, newNativePath) < 0) {
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
} }
} }
} catch (IOException e) {
returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
} }
if (returnCode == PackageManager.MOVE_SUCCEEDED) { if (returnCode == PackageManager.MOVE_SUCCEEDED) {
pkg.mPath = newCodePath; pkg.mPath = newCodePath;
// Move dex files around // Move dex files around