diff options
3 files changed, 131 insertions, 30 deletions
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 8a5f8bb..77e4986 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -1229,9 +1229,8 @@ public class PackageManagerTests extends AndroidTestCase { installFromRawResource("install.apk", R.raw.install_loc_unspecified, PackageManager.INSTALL_FORWARD_LOCK | - PackageManager.INSTALL_EXTERNAL, true, true, - PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION, - PackageInfo.INSTALL_LOCATION_UNSPECIFIED); + PackageManager.INSTALL_EXTERNAL, true, false, -1, + PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL); } @LargeTest @@ -1626,8 +1625,8 @@ public class PackageManagerTests extends AndroidTestCase { int installFlags = PackageManager.INSTALL_FORWARD_LOCK; int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA; - boolean fail = true; - int result = PackageManager.MOVE_FAILED_FORWARD_LOCKED; + boolean fail = false; + int result = PackageManager.MOVE_SUCCEEDED; sampleMoveFromRawResource(installFlags, moveFlags, fail, result); } @@ -1950,7 +1949,7 @@ public class PackageManagerTests extends AndroidTestCase { PackageManager.INSTALL_FORWARD_LOCK, true, false, -1, - PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL); + PackageInfo.INSTALL_LOCATION_AUTO); } /* The following test functions verify install location for existing apps. diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 3eec18c..c709e40 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -311,6 +311,14 @@ public class DefaultContainerService extends IntentService { return null; } + try { + Libcore.os.chmod(resFile.getAbsolutePath(), 0640); + } catch (ErrnoException e) { + Slog.e(TAG, "Could not chown APK: " + e.getMessage()); + PackageHelper.destroySdDir(newCid); + return null; + } + if (isForwardLocked) { File publicZipFile = new File(newCachePath, publicResFileName); try { @@ -326,10 +334,9 @@ public class DefaultContainerService extends IntentService { } try { - Libcore.os.chmod(resFile.getAbsolutePath(), 0640); Libcore.os.chmod(publicZipFile.getAbsolutePath(), 0644); } catch (ErrnoException e) { - Slog.e(TAG, "Could not chown APK or resource file: " + e.getMessage()); + Slog.e(TAG, "Could not chown public resource file: " + e.getMessage()); PackageHelper.destroySdDir(newCid); return null; } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 21ae624..b5d0b60 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -5863,9 +5863,28 @@ public class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Insufficient storage to install"); return; } - // Create the file args now. + + mRet = srcArgs.doPreCopy(); + if (mRet != PackageManager.INSTALL_SUCCEEDED) { + return; + } + mRet = targetArgs.copyApk(mContainerService, false); - targetArgs.doPreInstall(mRet); + if (mRet != PackageManager.INSTALL_SUCCEEDED) { + srcArgs.doPostCopy(uid); + return; + } + + mRet = srcArgs.doPostCopy(uid); + if (mRet != PackageManager.INSTALL_SUCCEEDED) { + return; + } + + mRet = targetArgs.doPreInstall(mRet); + if (mRet != PackageManager.INSTALL_SUCCEEDED) { + return; + } + if (DEBUG_SD_INSTALL) { StringBuilder builder = new StringBuilder(); if (srcArgs != null) { @@ -5936,7 +5955,7 @@ public class PackageManagerService extends IPackageManager.Stub { String nativeLibraryPath) { if (installOnSd(flags) || installForwardLocked(flags)) { return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, - (flags & PackageManager.INSTALL_EXTERNAL) != 0); + installOnSd(flags), installForwardLocked(flags)); } else { return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); } @@ -5945,9 +5964,10 @@ public class PackageManagerService extends IPackageManager.Stub { // Used by package mover private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) { if (installOnSd(flags) || installForwardLocked(flags)) { - String cid = getNextCodePath(null, pkgName, "/" + AsecInstallArgs.RES_FILE_NAME); - return new AsecInstallArgs(packageURI, cid, - (flags & PackageManager.INSTALL_EXTERNAL) != 0); + String cid = getNextCodePath(packageURI.getPath(), pkgName, "/" + + AsecInstallArgs.RES_FILE_NAME); + return new AsecInstallArgs(packageURI, cid, installOnSd(flags), + installForwardLocked(flags)); } else { return new FileInstallArgs(packageURI, pkgName, dataDir); } @@ -5984,6 +6004,26 @@ public class PackageManagerService extends IPackageManager.Stub { abstract boolean doPostDeleteLI(boolean delete); abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException; + /** + * Called before the source arguments are copied. This is used mostly + * for MoveParams when it needs to read the source file to put it in the + * destination. + */ + int doPreCopy() { + return PackageManager.INSTALL_SUCCEEDED; + } + + /** + * Called after the source arguments are copied. This is used mostly for + * MoveParams when it needs to read the source file to put it in the + * destination. + * + * @return + */ + int doPostCopy(int uid) { + return PackageManager.INSTALL_SUCCEEDED; + } + protected boolean isFwdLocked() { return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; } @@ -6280,8 +6320,9 @@ public class PackageManagerService extends IPackageManager.Stub { } AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, - boolean isExternal) { - super(null, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null); + boolean isExternal, boolean isForwardLocked) { + super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) + | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null); // Extract cid from fullCodePath int eidx = fullCodePath.lastIndexOf("/"); String subStr1 = fullCodePath.substring(0, eidx); @@ -6296,8 +6337,9 @@ public class PackageManagerService extends IPackageManager.Stub { setCachePath(PackageHelper.getSdDir(cid)); } - AsecInstallArgs(Uri packageURI, String cid, boolean isExternal) { - super(packageURI, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null); + AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) { + super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) + | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null); this.cid = cid; } @@ -6443,8 +6485,18 @@ public class PackageManagerService extends IPackageManager.Stub { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } else { + final int groupOwner; + final String protectedFile; + if (isFwdLocked()) { + groupOwner = uid; + protectedFile = RES_FILE_NAME; + } else { + groupOwner = -1; + protectedFile = null; + } + if (uid < Process.FIRST_APPLICATION_UID - || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) { + || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) { Slog.e(TAG, "Failed to finalize " + cid); PackageHelper.destroySdDir(cid); return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; @@ -6505,6 +6557,33 @@ public class PackageManagerService extends IPackageManager.Stub { } return ret; } + + @Override + int doPreCopy() { + if (isFwdLocked()) { + if (!PackageHelper.fixSdPermissions(cid, + getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) { + return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; + } + } + + return PackageManager.INSTALL_SUCCEEDED; + } + + @Override + int doPostCopy(int uid) { + if (isFwdLocked()) { + PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME); + if (uid < Process.FIRST_APPLICATION_UID + || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) { + Slog.e(TAG, "Failed to finalize " + cid); + PackageHelper.destroySdDir(cid); + return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; + } + } + + return PackageManager.INSTALL_SUCCEEDED; + } }; // Utility method used to create code paths based on package name and available index. @@ -8696,9 +8775,15 @@ public class PackageManagerService extends IPackageManager.Stub { : PackageManager.INSTALL_INTERNAL; currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL; + if (newFlags == currFlags) { Slog.w(TAG, "No move required. Trying to move to same location"); returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; + } else { + if (isForwardLocked(pkg)) { + currFlags |= PackageManager.INSTALL_FORWARD_LOCK; + newFlags |= PackageManager.INSTALL_FORWARD_LOCK; + } } } if (returnCode == PackageManager.MOVE_SUCCEEDED) { @@ -8784,21 +8869,31 @@ public class PackageManagerService extends IPackageManager.Stub { final String newNativePath = mp.targetArgs .getNativeLibraryPath(); - if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) { - if (mInstaller - .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { - returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; + try { + final File newNativeDir = new File(newNativePath); + + final String libParentDir = newNativeDir.getParentFile() + .getCanonicalPath(); + if (newNativeDir.getParentFile().getCanonicalPath() + .equals(pkg.applicationInfo.dataDir)) { + if (mInstaller + .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { + returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; + } else { + NativeLibraryHelper.copyNativeBinariesIfNeededLI( + new File(newCodePath), newNativeDir); + } } else { - NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File( - newCodePath), new File(newNativePath)); - } - } else { - if (mInstaller.linkNativeLibraryDirectory( - pkg.applicationInfo.dataDir, newNativePath) < 0) { - returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; + if (mInstaller.linkNativeLibraryDirectory( + pkg.applicationInfo.dataDir, newNativePath) < 0) { + returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; + } } + } catch (IOException e) { + returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; } + if (returnCode == PackageManager.MOVE_SUCCEEDED) { pkg.mPath = newCodePath; // Move dex files around |