Skip to content

Commit 2e7d0cb

Browse files
krutonAndroid (Google) Code Review
authored andcommitted
Merge "Move native libraries to /data/app-lib" into jb-mr1-dev
2 parents 6625389 + ddbe50d commit 2e7d0cb

File tree

3 files changed

+148
-45
lines changed

3 files changed

+148
-45
lines changed

core/tests/coretests/src/android/content/pm/PackageManagerTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public class PackageManagerTests extends AndroidTestCase {
7272

7373
public final long WAIT_TIME_INCR = 5 * 1000;
7474

75+
private static final String APP_LIB_DIR_PREFIX = "/data/app-lib/";
76+
7577
private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec/";
7678

7779
private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
@@ -433,7 +435,7 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
433435
assertEquals(srcPath, appInstallPath);
434436
assertEquals(publicSrcPath, appInstallPath);
435437
assertStartsWith("Native library should point to shared lib directory",
436-
dataDir.getPath(),
438+
new File(APP_LIB_DIR_PREFIX, info.packageName).getPath(),
437439
info.nativeLibraryDir);
438440
assertDirOwnerGroupPerms(
439441
"Native library directory should be owned by system:system and 0755",

services/java/com/android/server/pm/Installer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,14 @@ public int moveFiles() {
359359
return execute("movefiles");
360360
}
361361

362+
/**
363+
* Links the native library directory in an application's directory to its
364+
* real location.
365+
*
366+
* @param dataPath data directory where the application is
367+
* @param nativeLibPath target native library path
368+
* @return -1 on error
369+
*/
362370
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath) {
363371
if (dataPath == null) {
364372
Slog.e(TAG, "unlinkNativeLibraryDirectory dataPath is null");

services/java/com/android/server/pm/PackageManagerService.java

Lines changed: 137 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
import static com.android.internal.util.ArrayUtils.appendInt;
2626
import static com.android.internal.util.ArrayUtils.removeInt;
2727
import static libcore.io.OsConstants.S_ISLNK;
28+
import static libcore.io.OsConstants.S_IRWXU;
29+
import static libcore.io.OsConstants.S_IRGRP;
30+
import static libcore.io.OsConstants.S_IXGRP;
31+
import static libcore.io.OsConstants.S_IROTH;
32+
import static libcore.io.OsConstants.S_IXOTH;
2833

2934
import com.android.internal.app.IMediaContainerService;
3035
import com.android.internal.app.ResolverActivity;
@@ -147,6 +152,7 @@
147152
import libcore.io.ErrnoException;
148153
import libcore.io.IoUtils;
149154
import libcore.io.Libcore;
155+
import libcore.io.OsConstants;
150156
import libcore.io.StructStat;
151157

152158
/**
@@ -276,7 +282,7 @@ public class PackageManagerService extends IPackageManager.Stub {
276282
// This is the object monitoring mDrmAppPrivateInstallDir.
277283
final FileObserver mDrmAppInstallObserver;
278284

279-
// Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
285+
// Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
280286
// LOCK HELD. Can be called with mInstallLock held.
281287
final Installer mInstaller;
282288

@@ -286,6 +292,12 @@ public class PackageManagerService extends IPackageManager.Stub {
286292
final File mAppInstallDir;
287293
final File mDalvikCacheDir;
288294

295+
/**
296+
* Directory to which applications installed internally have native
297+
* libraries copied.
298+
*/
299+
private File mAppLibInstallDir;
300+
289301
// Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
290302
// apps.
291303
final File mDrmAppPrivateInstallDir;
@@ -1215,6 +1227,7 @@ public PackageManagerService(Context context, boolean factoryTest, boolean onlyC
12151227
}
12161228

12171229
mAppInstallDir = new File(dataDir, "app");
1230+
mAppLibInstallDir = new File(dataDir, "app-lib");
12181231
//look for any incomplete package installations
12191232
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
12201233
//clean up list
@@ -3607,6 +3620,13 @@ private int removeDataDirsLI(String packageName) {
36073620
res = resInner;
36083621
}
36093622
}
3623+
3624+
final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
3625+
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
3626+
if (!nativeLibraryFile.delete()) {
3627+
Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
3628+
}
3629+
36103630
return res;
36113631
}
36123632

@@ -4048,9 +4068,7 @@ private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
40484068
*/
40494069
if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
40504070
if (pkgSetting.nativeLibraryPathString == null) {
4051-
final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
4052-
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
4053-
pkgSetting.nativeLibraryPathString = nativeLibraryPath;
4071+
setInternalAppNativeLibraryPath(pkg, pkgSetting);
40544072
} else {
40554073
pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
40564074
}
@@ -4072,7 +4090,7 @@ private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
40724090
*/
40734091
if (pkg.applicationInfo.nativeLibraryDir != null) {
40744092
try {
4075-
final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
4093+
File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
40764094
final String dataPathString = dataPath.getCanonicalPath();
40774095

40784096
if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
@@ -4087,30 +4105,31 @@ private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
40874105
Log.i(TAG, "removed obsolete native libraries for system package "
40884106
+ path);
40894107
}
4090-
} else if (nativeLibraryDir.getParentFile().getCanonicalPath()
4091-
.equals(dataPathString)) {
4092-
/*
4093-
* Make sure the native library dir isn't a symlink to
4094-
* something. If it is, ask installd to remove it and create
4095-
* a directory so we can copy to it afterwards.
4096-
*/
4097-
boolean isSymLink;
4098-
try {
4099-
isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
4100-
} catch (ErrnoException e) {
4101-
// This shouldn't happen, but we'll fail-safe.
4102-
isSymLink = true;
4108+
} else if (!isForwardLocked(pkg) && !isExternal(pkg)) {
4109+
// Update native library dir if it starts with /data/data
4110+
if (nativeLibraryDir.getParent().startsWith(dataPathString)) {
4111+
setInternalAppNativeLibraryPath(pkg, pkgSetting);
4112+
nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
41034113
}
4104-
if (isSymLink) {
4105-
mInstaller.unlinkNativeLibraryDirectory(dataPathString);
4114+
4115+
try {
4116+
if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
4117+
Slog.e(TAG, "Unable to copy native libraries");
4118+
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4119+
return null;
4120+
}
4121+
} catch (IOException e) {
4122+
Slog.e(TAG, "Unable to copy native libraries", e);
4123+
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4124+
return null;
41064125
}
41074126

4108-
/*
4109-
* If this is an internal application or our
4110-
* nativeLibraryPath points to our data directory, unpack
4111-
* the libraries if necessary.
4112-
*/
4113-
NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
4127+
if (mInstaller.linkNativeLibraryDirectory(dataPathString,
4128+
pkg.applicationInfo.nativeLibraryDir) == -1) {
4129+
Slog.e(TAG, "Unable to link native library directory");
4130+
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4131+
return null;
4132+
}
41144133
} else {
41154134
Slog.i(TAG, "Linking native library dir for " + path);
41164135
int ret = mInstaller.linkNativeLibraryDirectory(dataPathString,
@@ -4122,7 +4141,7 @@ private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
41224141
}
41234142
}
41244143
} catch (IOException ioe) {
4125-
Log.e(TAG, "Unable to get canonical file " + ioe.toString());
4144+
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
41264145
}
41274146
}
41284147
pkg.mScanPath = path;
@@ -4437,6 +4456,37 @@ private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
44374456
return pkg;
44384457
}
44394458

4459+
private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
4460+
PackageSetting pkgSetting) {
4461+
final String apkLibPath = getApkName(pkgSetting.codePathString);
4462+
final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
4463+
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
4464+
pkgSetting.nativeLibraryPathString = nativeLibraryPath;
4465+
}
4466+
4467+
private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
4468+
throws IOException {
4469+
if (!nativeLibraryDir.isDirectory()) {
4470+
nativeLibraryDir.delete();
4471+
if (!nativeLibraryDir.mkdir()) {
4472+
throw new IOException("Cannot create " + nativeLibraryDir.getPath());
4473+
}
4474+
try {
4475+
Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
4476+
| S_IXOTH);
4477+
} catch (ErrnoException e) {
4478+
throw new IOException("Cannot chmod native library directory "
4479+
+ nativeLibraryDir.getPath(), e);
4480+
}
4481+
}
4482+
4483+
/*
4484+
* If this is an internal application or our nativeLibraryPath points to
4485+
* the app-lib directory, unpack the libraries if necessary.
4486+
*/
4487+
return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
4488+
}
4489+
44404490
private void killApplication(String pkgName, int appId) {
44414491
// Request the ActivityManager to kill the process(only for existing packages)
44424492
// so that we do not end up in a confused state while the user is still using the older
@@ -6737,7 +6787,7 @@ class FileInstallArgs extends InstallArgs {
67376787
String apkName = getNextCodePath(null, pkgName, ".apk");
67386788
codeFileName = new File(installDir, apkName + ".apk").getPath();
67396789
resourceFileName = getResourcePathFromCodePath();
6740-
libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
6790+
libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
67416791
}
67426792

67436793
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -6774,6 +6824,7 @@ void createCopyFile() {
67746824
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
67756825
codeFileName = createTempPackageFile(installDir).getPath();
67766826
resourceFileName = getResourcePathFromCodePath();
6827+
libraryPath = getLibraryPathFromCodePath();
67776828
created = true;
67786829
}
67796830

@@ -6828,6 +6879,23 @@ int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
68286879
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
68296880
}
68306881
}
6882+
6883+
final File nativeLibraryFile = new File(getNativeLibraryPath());
6884+
Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
6885+
if (nativeLibraryFile.exists()) {
6886+
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
6887+
nativeLibraryFile.delete();
6888+
}
6889+
try {
6890+
int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
6891+
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
6892+
return copyRet;
6893+
}
6894+
} catch (IOException e) {
6895+
Slog.e(TAG, "Copying native libraries failed", e);
6896+
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
6897+
}
6898+
68316899
return ret;
68326900
}
68336901

@@ -6845,6 +6913,7 @@ boolean doRename(int status, final String pkgName, String oldCodePath) {
68456913
} else {
68466914
final File oldCodeFile = new File(getCodePath());
68476915
final File oldResourceFile = new File(getResourcePath());
6916+
final File oldLibraryFile = new File(getNativeLibraryPath());
68486917

68496918
// Rename APK file based on packageName
68506919
final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
@@ -6859,7 +6928,20 @@ boolean doRename(int status, final String pkgName, String oldCodePath) {
68596928
if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
68606929
return false;
68616930
}
6862-
resourceFileName = getResourcePathFromCodePath();
6931+
resourceFileName = newResFile.getPath();
6932+
6933+
// Rename library path
6934+
final File newLibraryFile = new File(getLibraryPathFromCodePath());
6935+
if (newLibraryFile.exists()) {
6936+
NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
6937+
newLibraryFile.delete();
6938+
}
6939+
if (!oldLibraryFile.renameTo(newLibraryFile)) {
6940+
Slog.e(TAG, "Cannot rename native library directory "
6941+
+ oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
6942+
return false;
6943+
}
6944+
libraryPath = newLibraryFile.getPath();
68636945

68646946
// Attempt to set permissions
68656947
if (!setPermissions()) {
@@ -6910,8 +6992,15 @@ private String getResourcePathFromCodePath() {
69106992
}
69116993
}
69126994

6995+
private String getLibraryPathFromCodePath() {
6996+
return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
6997+
}
6998+
69136999
@Override
69147000
String getNativeLibraryPath() {
7001+
if (libraryPath == null) {
7002+
libraryPath = getLibraryPathFromCodePath();
7003+
}
69157004
return libraryPath;
69167005
}
69177006

@@ -6937,6 +7026,15 @@ private boolean cleanUp() {
69377026
publicSourceFile.delete();
69387027
}
69397028
}
7029+
7030+
if (libraryPath != null) {
7031+
File nativeLibraryFile = new File(libraryPath);
7032+
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
7033+
if (!nativeLibraryFile.delete()) {
7034+
Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
7035+
}
7036+
}
7037+
69407038
return ret;
69417039
}
69427040

@@ -9779,31 +9877,26 @@ public void run() {
97799877
final String newNativePath = mp.targetArgs
97809878
.getNativeLibraryPath();
97819879

9782-
try {
9783-
final File newNativeDir = new File(newNativePath);
9880+
final File newNativeDir = new File(newNativePath);
97849881

9785-
final String libParentDir = newNativeDir.getParentFile()
9786-
.getCanonicalPath();
9787-
if (newNativeDir.getParentFile().getCanonicalPath()
9788-
.equals(pkg.applicationInfo.dataDir)) {
9789-
if (mInstaller
9790-
.unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
9882+
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
9883+
synchronized (mInstallLock) {
9884+
if (mInstaller.linkNativeLibraryDirectory(
9885+
pkg.applicationInfo.dataDir, newNativePath) < 0) {
97919886
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9792-
} else {
9793-
NativeLibraryHelper.copyNativeBinariesIfNeededLI(
9794-
new File(newCodePath), newNativeDir);
97959887
}
9796-
} else {
9888+
}
9889+
NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
9890+
newCodePath), newNativeDir);
9891+
} else {
9892+
synchronized (mInstallLock) {
97979893
if (mInstaller.linkNativeLibraryDirectory(
97989894
pkg.applicationInfo.dataDir, newNativePath) < 0) {
97999895
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
98009896
}
98019897
}
9802-
} catch (IOException e) {
9803-
returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
98049898
}
98059899

9806-
98079900
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
98089901
pkg.mPath = newCodePath;
98099902
// Move dex files around

0 commit comments

Comments
 (0)