diff options
author | Kenny Root <kroot@google.com> | 2012-04-25 15:40:52 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-04-25 15:40:52 -0700 |
commit | 1fa1de527e541c88fb3809279b67b0dc29419bac (patch) | |
tree | 69105136a6397b0af3594d976df4db5404f37269 | |
parent | d7a2a428db781b3fae5df395dccac1bcab867bd5 (diff) | |
parent | 6dceb88f1c7c42c6ab43834af2c993d599895d82 (diff) | |
download | frameworks_base-1fa1de527e541c88fb3809279b67b0dc29419bac.zip frameworks_base-1fa1de527e541c88fb3809279b67b0dc29419bac.tar.gz frameworks_base-1fa1de527e541c88fb3809279b67b0dc29419bac.tar.bz2 |
Merge "Allow forward locked apps to be in ASECs" into jb-dev
9 files changed, 783 insertions, 461 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 0640d7e..f4abda6 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -252,7 +252,7 @@ public interface IMountService extends IInterface { * an int consistent with MountServiceResultCode */ public int createSecureContainer(String id, int sizeMb, String fstype, String key, - int ownerUid) throws RemoteException { + int ownerUid, boolean external) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); int _result; @@ -263,6 +263,7 @@ public interface IMountService extends IInterface { _data.writeString(fstype); _data.writeString(key); _data.writeInt(ownerUid); + _data.writeInt(external ? 1 : 0); mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); @@ -711,6 +712,31 @@ public interface IMountService extends IInterface { } return _result; } + + /** + * Fix permissions in a container which has just been created and + * populated. Returns an int consistent with MountServiceResultCode + */ + public int fixPermissionsSecureContainer(String id, int gid, String filename) + throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(id); + _data.writeInt(gid); + _data.writeString(filename); + mRemote.transact(Stub.TRANSACTION_fixPermissionsSecureContainer, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + + } } private static final String DESCRIPTOR = "IMountService"; @@ -781,6 +807,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32; + static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -909,7 +937,10 @@ public interface IMountService extends IInterface { key = data.readString(); int ownerUid; ownerUid = data.readInt(); - int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid); + boolean external; + external = 0 != data.readInt(); + int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid, + external); reply.writeNoException(); reply.writeInt(resultCode); return true; @@ -1109,6 +1140,19 @@ public interface IMountService extends IInterface { reply.writeInt(result); return true; } + case TRANSACTION_fixPermissionsSecureContainer: { + data.enforceInterface(DESCRIPTOR); + String id; + id = data.readString(); + int gid; + gid = data.readInt(); + String filename; + filename = data.readString(); + int resultCode = fixPermissionsSecureContainer(id, gid, filename); + reply.writeNoException(); + reply.writeInt(resultCode); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -1118,8 +1162,8 @@ public interface IMountService extends IInterface { * Creates a secure container with the specified parameters. Returns an int * consistent with MountServiceResultCode */ - public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid) - throws RemoteException; + public int createSecureContainer(String id, int sizeMb, String fstype, String key, + int ownerUid, boolean external) throws RemoteException; /* * Destroy a secure container, and free up all resources associated with it. @@ -1317,4 +1361,11 @@ public interface IMountService extends IInterface { public Parcelable[] getVolumeList() throws RemoteException; public String getSecureContainerFilesystemPath(String id) throws RemoteException; + + /* + * Fix permissions in a container which has just been created and populated. + * Returns an int consistent with MountServiceResultCode + */ + public int fixPermissionsSecureContainer(String id, int gid, String filename) + throws RemoteException; } diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl index 4322a20..727c094 100755 --- a/core/java/com/android/internal/app/IMediaContainerService.aidl +++ b/core/java/com/android/internal/app/IMediaContainerService.aidl @@ -22,14 +22,14 @@ import android.content.pm.PackageInfoLite; import android.content.res.ObbInfo; interface IMediaContainerService { - String copyResourceToContainer(in Uri packageURI, - String containerId, - String key, String resFileName); + String copyResourceToContainer(in Uri packageURI, String containerId, String key, + String resFileName, String publicResFileName, boolean isExternal, + boolean isForwardLocked); int copyResource(in Uri packageURI, in ParcelFileDescriptor outStream); PackageInfoLite getMinimalPackageInfo(in Uri fileUri, in int flags, in long threshold); - boolean checkInternalFreeStorage(in Uri fileUri, in long threshold); - boolean checkExternalFreeStorage(in Uri fileUri); + boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold); + boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked); ObbInfo getObbInfo(in String filename); long calculateDirectorySize(in String directory); /** Return file system stats: [0] is total bytes, [1] is available bytes */ diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index 61866e5..48ed561 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -67,8 +67,8 @@ public class PackageHelper { return null; } - public static String createSdDir(int sizeMb, String cid, - String sdEncKey, int uid) { + public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid, + boolean isExternal) { // Create mount point via MountService IMountService mountService = getMountService(); @@ -76,8 +76,8 @@ public class PackageHelper { Log.i(TAG, "Size of container " + sizeMb + " MB"); try { - int rc = mountService.createSecureContainer( - cid, sizeMb, "fat", sdEncKey, uid); + int rc = mountService.createSecureContainer(cid, sizeMb, "ext4", sdEncKey, uid, + isExternal); if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to create secure container " + cid); return null; @@ -206,10 +206,21 @@ public class PackageHelper { return false; } - public static void extractPublicFiles(String packagePath, File publicZipFile) + public static int extractPublicFiles(String packagePath, File publicZipFile) throws IOException { - final FileOutputStream fstr = new FileOutputStream(publicZipFile); - final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr); + final FileOutputStream fstr; + final ZipOutputStream publicZipOutStream; + + if (publicZipFile == null) { + fstr = null; + publicZipOutStream = null; + } else { + fstr = new FileOutputStream(publicZipFile); + publicZipOutStream = new ZipOutputStream(fstr); + } + + int size = 0; + try { final ZipFile privateZip = new ZipFile(packagePath); try { @@ -219,25 +230,29 @@ public class PackageHelper { if ("AndroidManifest.xml".equals(zipEntryName) || "resources.arsc".equals(zipEntryName) || zipEntryName.startsWith("res/")) { - copyZipEntry(zipEntry, privateZip, publicZipOutStream); + size += zipEntry.getSize(); + if (publicZipFile != null) { + copyZipEntry(zipEntry, privateZip, publicZipOutStream); + } } } } finally { - try { - privateZip.close(); - } catch (IOException e) { - } + try { privateZip.close(); } catch (IOException e) {} } - publicZipOutStream.finish(); - publicZipOutStream.flush(); - FileUtils.sync(fstr); - publicZipOutStream.close(); - FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR - | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1); + if (publicZipFile != null) { + publicZipOutStream.finish(); + publicZipOutStream.flush(); + FileUtils.sync(fstr); + publicZipOutStream.close(); + FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR + | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1); + } } finally { IoUtils.closeQuietly(publicZipOutStream); } + + return size; } private static void copyZipEntry(ZipEntry zipEntry, ZipFile inZipFile, @@ -265,4 +280,18 @@ public class PackageHelper { IoUtils.closeQuietly(data); } } + + public static boolean fixSdPermissions(String cid, int gid, String filename) { + try { + int rc = getMountService().fixPermissionsSecureContainer(cid, gid, filename); + if (rc != StorageResultCode.OperationSucceeded) { + Log.i(TAG, "Failed to fixperms container " + cid); + return false; + } + return true; + } catch (RemoteException e) { + Log.e(TAG, "Failed to fixperms container " + cid + " with exception " + e); + } + return false; + } } diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java index 27112a6..7ad35d0 100644 --- a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java @@ -81,7 +81,8 @@ public class PackageHelperTests extends AndroidTestCase { public void testMountAndPullSdCard() { try { fullId = PREFIX; - fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid()); + fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid(), + true); Log.d(TAG,PackageHelper.getSdDir(fullId)); PackageHelper.unMountSdDir(fullId); diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 580b4da..8a5f8bb 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -309,9 +309,7 @@ public class PackageManagerTests extends AndroidTestCase { private static final int INSTALL_LOC_ERR = -1; private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) { // Flags explicitly over ride everything else. - if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ) { - return INSTALL_LOC_INT; - } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) { + if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) { return INSTALL_LOC_SD; } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) { return INSTALL_LOC_INT; @@ -380,61 +378,76 @@ public class PackageManagerTests extends AndroidTestCase { String publicSrcPath = publicSrcDir.getParent(); long pkgLen = new File(info.sourceDir).length(); - if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) { - assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); - assertEquals(srcPath, drmInstallPath); - assertEquals(publicSrcPath, appInstallPath); - assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath())); - } else { - assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); - int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen); - if (rLoc == INSTALL_LOC_INT) { - assertEquals(srcPath, appInstallPath); - assertEquals(publicSrcPath, appInstallPath); - assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); - assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath())); - - // Make sure the native library dir is not a symlink - final File nativeLibDir = new File(info.nativeLibraryDir); - assertTrue("Native library dir should exist at " + info.nativeLibraryDir, - nativeLibDir.exists()); - try { - assertEquals("Native library dir should not be a symlink", - info.nativeLibraryDir, - nativeLibDir.getCanonicalPath()); - } catch (IOException e) { - fail("Can't read " + nativeLibDir.getPath()); - } - } else if (rLoc == INSTALL_LOC_SD){ - assertTrue("Application flags (" + info.flags - + ") should contain FLAG_EXTERNAL_STORAGE", - (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); + int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen); + if (rLoc == INSTALL_LOC_INT) { + if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) { + assertTrue("The application should be installed forward locked", + (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); assertTrue("The APK path (" + srcPath + ") should start with " - + SECURE_CONTAINERS_PREFIX, srcPath - .startsWith(SECURE_CONTAINERS_PREFIX)); + + SECURE_CONTAINERS_PREFIX, + srcPath.startsWith(SECURE_CONTAINERS_PREFIX)); assertTrue("The public APK path (" + publicSrcPath + ") should start with " - + SECURE_CONTAINERS_PREFIX, publicSrcPath - .startsWith(SECURE_CONTAINERS_PREFIX)); + + SECURE_CONTAINERS_PREFIX, + publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX)); assertTrue("The native library path (" + info.nativeLibraryDir + ") should start with " + SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); + } else { + assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); + assertEquals(srcPath, appInstallPath); + assertEquals(publicSrcPath, appInstallPath); + assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath())); + } + assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); - // Make sure the native library in /data/data/<app>/lib is a - // symlink to the ASEC - final File nativeLibSymLink = new File(info.dataDir, "lib"); - assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(), - nativeLibSymLink.exists()); - try { - assertEquals(nativeLibSymLink.getPath() + " should be a symlink to " - + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink - .getCanonicalPath()); - } catch (IOException e) { - fail("Can't read " + nativeLibSymLink.getPath()); - } + // Make sure the native library dir is not a symlink + final File nativeLibDir = new File(info.nativeLibraryDir); + assertTrue("Native library dir should exist at " + info.nativeLibraryDir, + nativeLibDir.exists()); + try { + assertEquals("Native library dir should not be a symlink", + info.nativeLibraryDir, + nativeLibDir.getCanonicalPath()); + } catch (IOException e) { + fail("Can't read " + nativeLibDir.getPath()); + } + } else if (rLoc == INSTALL_LOC_SD){ + if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) { + assertTrue("The application should be installed forward locked", + (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); } else { - // TODO handle error. Install should have failed. - fail("Install should have failed"); + assertFalse("The application should not be installed forward locked", + (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); + } + assertTrue("Application flags (" + info.flags + + ") should contain FLAG_EXTERNAL_STORAGE", + (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0); + // Might need to check: + // ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) + assertTrue("The APK path (" + srcPath + ") should start with " + + SECURE_CONTAINERS_PREFIX, srcPath.startsWith(SECURE_CONTAINERS_PREFIX)); + assertTrue("The public APK path (" + publicSrcPath + ") should start with " + + SECURE_CONTAINERS_PREFIX, + publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX)); + assertTrue("The native library path (" + info.nativeLibraryDir + + ") should start with " + SECURE_CONTAINERS_PREFIX, + info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX)); + + // Make sure the native library in /data/data/<app>/lib is a + // symlink to the ASEC + final File nativeLibSymLink = new File(info.dataDir, "lib"); + assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(), + nativeLibSymLink.exists()); + try { + assertEquals(nativeLibSymLink.getPath() + " should be a symlink to " + + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink + .getCanonicalPath()); + } catch (IOException e) { + fail("Can't read " + nativeLibSymLink.getPath()); } + } else { + // TODO handle error. Install should have failed. + fail("Install should have failed"); } } catch (NameNotFoundException e) { failStr("failed with exception : " + e); @@ -1774,15 +1787,17 @@ public class PackageManagerTests extends AndroidTestCase { } /* - * Install an app with both external and forward-lock flags set. should fail + * Install an app with both external and forward-lock flags set. */ @LargeTest public void testFlagEF() { - installFromRawResource("install.apk", R.raw.install, - PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_EXTERNAL, - false, - true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION, - PackageInfo.INSTALL_LOCATION_AUTO); + // Do not run on devices with emulated external storage. + if (Environment.isExternalStorageEmulated()) { + return; + } + + sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK + | PackageManager.INSTALL_EXTERNAL, true); } /* @@ -1899,15 +1914,20 @@ public class PackageManagerTests extends AndroidTestCase { PackageManager.INSTALL_FORWARD_LOCK, true, false, -1, - PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL); + PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY); } /* * Install an app with fwd locked flag set and install location set to - * preferExternal. should install internally. + * preferExternal. Should install externally. */ @LargeTest public void testFlagFManifestE() { + // Do not run on devices with emulated external storage. + if (Environment.isExternalStorageEmulated()) { + return; + } + installFromRawResource("install.apk", R.raw.install_loc_sdcard, PackageManager.INSTALL_FORWARD_LOCK, true, @@ -1916,11 +1936,16 @@ public class PackageManagerTests extends AndroidTestCase { } /* - * Install an app with fwd locked flag set and install location set to - * auto. should install internally. + * Install an app with fwd locked flag set and install location set to auto. + * should install externally. */ @LargeTest public void testFlagFManifestA() { + // Do not run on devices with emulated external storage. + if (Environment.isExternalStorageEmulated()) { + return; + } + installFromRawResource("install.apk", R.raw.install_loc_auto, PackageManager.INSTALL_FORWARD_LOCK, true, diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java index 5efbd88..abb8eae 100755 --- a/core/tests/coretests/src/android/os/storage/AsecTests.java +++ b/core/tests/coretests/src/android/os/storage/AsecTests.java @@ -27,20 +27,13 @@ import android.util.Log; import java.io.File; import java.io.FileOutputStream; -import junit.framework.Assert; - public class AsecTests extends AndroidTestCase { + private static final String SECURE_CONTAINER_PREFIX = "com.android.unittests.AsecTests."; private static final boolean localLOGV = true; public static final String TAG="AsecTests"; - void failStr(String errMsg) { - Log.w(TAG, "errMsg="+errMsg); - } - - void failStr(Exception e) { - Log.w(TAG, "e.getMessage="+e.getMessage()); - Log.w(TAG, "e="+e); - } + private static final String FS_FAT = "fat"; + private static final String FS_EXT4 = "ext4"; @Override protected void setUp() throws Exception { @@ -61,7 +54,9 @@ public class AsecTests extends AndroidTestCase { String[] containers = ms.getSecureContainerList(); for (int i = 0; i < containers.length; i++) { - if (containers[i].startsWith("com.android.unittests.AsecTests.")) { + if (containers[i].startsWith(SECURE_CONTAINER_PREFIX)) { + if (localLOGV) + Log.i(TAG, "Cleaning: " + containers[i]); ms.destroySecureContainer(containers[i], true); } } @@ -70,7 +65,7 @@ public class AsecTests extends AndroidTestCase { private boolean containerExists(String localId) throws RemoteException { IMountService ms = getMs(); String[] containers = ms.getSecureContainerList(); - String fullId = "com.android.unittests.AsecTests." + localId; + String fullId = SECURE_CONTAINER_PREFIX + localId; for (int i = 0; i < containers.length; i++) { if (containers[i].equals(fullId)) { @@ -80,50 +75,52 @@ public class AsecTests extends AndroidTestCase { return false; } - private int createContainer(String localId, int size, String key) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId = "com.android.unittests.AsecTests." + localId; + private int createContainer(String localId, int size, String key, String filesystem, + boolean isExternal) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); - return ms.createSecureContainer(fullId, size, "fat", key, android.os.Process.myUid()); + return ms.createSecureContainer(fullId, size, filesystem, key, android.os.Process.myUid(), + isExternal); } - private int mountContainer(String localId, String key) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId = "com.android.unittests.AsecTests." + localId; + private int mountContainer(String localId, String key) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); return ms.mountSecureContainer(fullId, key, android.os.Process.myUid()); } - private int renameContainer(String localId1, String localId2) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId1 = "com.android.unittests.AsecTests." + localId1; - String fullId2 = "com.android.unittests.AsecTests." + localId2; + private int renameContainer(String localId1, String localId2) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId1 = SECURE_CONTAINER_PREFIX + localId1; + String fullId2 = SECURE_CONTAINER_PREFIX + localId2; IMountService ms = getMs(); return ms.renameSecureContainer(fullId1, fullId2); } - private int unmountContainer(String localId, boolean force) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId = "com.android.unittests.AsecTests." + localId; + private int unmountContainer(String localId, boolean force) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); return ms.unmountSecureContainer(fullId, force); } - private int destroyContainer(String localId, boolean force) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId = "com.android.unittests.AsecTests." + localId; + private int destroyContainer(String localId, boolean force) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); return ms.destroySecureContainer(fullId, force); } - private boolean isContainerMounted(String localId) throws RemoteException { - Assert.assertTrue(isMediaMounted()); - String fullId = "com.android.unittests.AsecTests." + localId; + private boolean isContainerMounted(String localId) throws Exception { + assertTrue("Media should be mounted", isMediaMounted()); + String fullId = SECURE_CONTAINER_PREFIX + localId; IMountService ms = getMs(); return ms.isSecureContainerMounted(fullId); @@ -139,248 +136,392 @@ public class AsecTests extends AndroidTestCase { return null; } - private boolean isMediaMounted() { - try { + private boolean isMediaMounted() throws Exception { String mPath = Environment.getExternalStorageDirectory().toString(); String state = getMs().getVolumeState(mPath); return Environment.MEDIA_MOUNTED.equals(state); - } catch (RemoteException e) { - failStr(e); - return false; - } } - public void testCreateContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testCreateContainer", 4, "none")); - Assert.assertEquals(true, containerExists("testCreateContainer")); - } catch (Exception e) { - failStr(e); + + /* + * CREATE + */ + + public void test_Fat_External_Create_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 4, "none", FS_FAT, true)); + assertTrue(containerExists("testCreateContainer")); } - public void testCreateMinSizeContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testCreateContainer", 1, "none")); - Assert.assertEquals(true, containerExists("testCreateContainer")); - } catch (Exception e) { - failStr(e); + public void test_Ext4_External_Create_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 4, "none", FS_EXT4, true)); + assertTrue(containerExists("testCreateContainer")); } - public void testCreateZeroSizeContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationFailedInternalError, - createContainer("testCreateZeroContainer", 0, "none")); - } catch (Exception e) { - failStr(e); - } + public void test_Fat_Internal_Create_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 4, "none", FS_FAT, false)); + assertTrue(containerExists("testCreateContainer")); } - public void testCreateDuplicateContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testCreateDupContainer", 4, "none")); + public void test_Ext4_Internal_Create_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 4, "none", FS_EXT4, false)); + assertTrue(containerExists("testCreateContainer")); + } - Assert.assertEquals(StorageResultCode.OperationFailedInternalError, - createContainer("testCreateDupContainer", 4, "none")); - } catch (Exception e) { - failStr(e); + + /* + * CREATE MIN SIZE + */ + + public void test_Fat_External_CreateMinSize_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 1, "none", FS_FAT, true)); + assertTrue(containerExists("testCreateContainer")); } - public void testDestroyContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testDestroyContainer", 4, "none")); - Assert.assertEquals(StorageResultCode.OperationSucceeded, - destroyContainer("testDestroyContainer", false)); - } catch (Exception e) { - failStr(e); + public void test_Ext4_External_CreateMinSize_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 1, "none", FS_EXT4, true)); + assertTrue(containerExists("testCreateContainer")); } - public void testMountContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testMountContainer", 4, "none")); + public void test_Fat_Internal_CreateMinSize_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 1, "none", FS_FAT, false)); + assertTrue(containerExists("testCreateContainer")); + } - Assert.assertEquals(StorageResultCode.OperationSucceeded, - unmountContainer("testMountContainer", false)); + public void test_Ext4_Internal_CreateMinSize_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateContainer", 1, "none", FS_EXT4, false)); + assertTrue(containerExists("testCreateContainer")); + } + + + /* + * CREATE ZERO SIZE - FAIL CASE + */ - Assert.assertEquals(StorageResultCode.OperationSucceeded, - mountContainer("testMountContainer", "none")); - } catch (Exception e) { - failStr(e); + public void test_Fat_External_CreateZeroSize_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateZeroContainer", 0, "none", FS_FAT, true)); } - public void testMountBadKey() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testMountBadKey", 4, "00000000000000000000000000000000")); + public void test_Ext4_External_CreateZeroSize_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, true)); + } - Assert.assertEquals(StorageResultCode.OperationSucceeded, - unmountContainer("testMountBadKey", false)); + public void test_Fat_Internal_CreateZeroSize_Failure() throws Exception { + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateZeroContainer", 0, "none", FS_FAT, false)); + } - Assert.assertEquals(StorageResultCode.OperationFailedInternalError, - mountContainer("testMountContainer", "000000000000000000000000000000001")); + public void test_Ext4_Internal_CreateZeroSize_Failure() throws Exception { + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, false)); + } - Assert.assertEquals(StorageResultCode.OperationFailedInternalError, - mountContainer("testMountContainer", "none")); - } catch (Exception e) { - failStr(e); + + /* + * CREATE DUPLICATE - FAIL CASE + */ + + public void test_Fat_External_CreateDuplicate_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateDupContainer", 4, "none", FS_FAT, true)); + + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateDupContainer", 4, "none", FS_FAT, true)); } - public void testNonExistPath() { - IMountService ms = getMs(); - try { - String path = ms.getSecureContainerPath("jparks.broke.it"); - failStr(path); - } catch (IllegalArgumentException e) { - } catch (Exception e) { - failStr(e); + public void test_Ext4_External_CreateDuplicate_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true)); + + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true)); } - public void testUnmountBusyContainer() { - IMountService ms = getMs(); - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testUnmountBusyContainer", 4, "none")); + public void test_Fat_Internal_CreateDuplicate_Failure() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateDupContainer", 4, "none", FS_FAT, false)); + + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateDupContainer", 4, "none", FS_FAT, false)); + } + + public void test_Ext4_Internal_CreateDuplicate_Failure() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false)); - String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); + assertEquals(StorageResultCode.OperationFailedInternalError, + createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false)); + } - File f = new File(path, "reference"); - FileOutputStream fos = new FileOutputStream(f); - Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, - unmountContainer("testUnmountBusyContainer", false)); + /* + * DESTROY + */ - fos.close(); - Assert.assertEquals(StorageResultCode.OperationSucceeded, - unmountContainer("testUnmountBusyContainer", false)); - } catch (Exception e) { - failStr(e); + public void test_Fat_External_Destroy_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testDestroyContainer", 4, "none", FS_FAT, true)); + assertEquals(StorageResultCode.OperationSucceeded, + destroyContainer("testDestroyContainer", false)); } - public void testDestroyBusyContainer() { - IMountService ms = getMs(); - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testDestroyBusyContainer", 4, "none")); + public void test_Ext4_External_Destroy_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testDestroyContainer", 4, "none", FS_EXT4, true)); + assertEquals(StorageResultCode.OperationSucceeded, + destroyContainer("testDestroyContainer", false)); + } - String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer"); + public void test_Fat_Internal_Destroy_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testDestroyContainer", 4, "none", FS_FAT, false)); + assertEquals(StorageResultCode.OperationSucceeded, + destroyContainer("testDestroyContainer", false)); + } + + public void test_Ext4_Internal_Destroy_Success() throws Exception { + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testDestroyContainer", 4, "none", FS_EXT4, false)); + assertEquals(StorageResultCode.OperationSucceeded, + destroyContainer("testDestroyContainer", false)); + } - File f = new File(path, "reference"); - FileOutputStream fos = new FileOutputStream(f); - Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, - destroyContainer("testDestroyBusyContainer", false)); + /* + * MOUNT + */ - fos.close(); - Assert.assertEquals(StorageResultCode.OperationSucceeded, - destroyContainer("testDestroyBusyContainer", false)); - } catch (Exception e) { - failStr(e); + public void test_Fat_External_Mount() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testMountContainer", 4, "none", FS_FAT, true)); + + assertEquals(StorageResultCode.OperationSucceeded, + unmountContainer("testMountContainer", false)); + + assertEquals(StorageResultCode.OperationSucceeded, + mountContainer("testMountContainer", "none")); } - public void testRenameContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testRenameContainer.1", 4, "none")); - Assert.assertEquals(StorageResultCode.OperationSucceeded, - unmountContainer("testRenameContainer.1", false)); + /* + * MOUNT BAD KEY - FAIL CASE + */ + + public void test_Fat_External_MountBadKey_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testMountBadKey", 4, "00000000000000000000000000000000", FS_FAT, + true)); + + assertEquals(StorageResultCode.OperationSucceeded, + unmountContainer("testMountBadKey", false)); + + assertEquals(StorageResultCode.OperationFailedInternalError, + mountContainer("testMountContainer", "000000000000000000000000000000001")); + + assertEquals(StorageResultCode.OperationFailedInternalError, + mountContainer("testMountContainer", "none")); + } - Assert.assertEquals(StorageResultCode.OperationSucceeded, - renameContainer("testRenameContainer.1", "testRenameContainer.2")); - Assert.assertEquals(false, containerExists("testRenameContainer.1")); - Assert.assertEquals(true, containerExists("testRenameContainer.2")); - } catch (Exception e) { - failStr(e); + public void test_Fat_External_UnmountBusy_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + IMountService ms = getMs(); + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testUnmountBusyContainer", 4, "none", FS_FAT, true)); + + String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + + "testUnmountBusyContainer"); + + File f = new File(path, "reference"); + FileOutputStream fos = new FileOutputStream(f); + + assertEquals(StorageResultCode.OperationFailedStorageBusy, + unmountContainer("testUnmountBusyContainer", false)); + + fos.close(); + assertEquals(StorageResultCode.OperationSucceeded, + unmountContainer("testUnmountBusyContainer", false)); } - public void testRenameSrcMountedContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testRenameContainer.1", 4, "none")); + public void test_Fat_External_DestroyBusy() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + + IMountService ms = getMs(); + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testDestroyBusyContainer", 4, "none", FS_FAT, true)); + + String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + + "testDestroyBusyContainer"); + + File f = new File(path, "reference"); + FileOutputStream fos = new FileOutputStream(f); + + assertEquals(StorageResultCode.OperationFailedStorageBusy, + destroyContainer("testDestroyBusyContainer", false)); - Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted, - renameContainer("testRenameContainer.1", "testRenameContainer.2")); - } catch (Exception e) { - failStr(e); + fos.close(); + assertEquals(StorageResultCode.OperationSucceeded, + destroyContainer("testDestroyBusyContainer", false)); + } + + public void test_Fat_External_Rename_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); + + assertEquals(StorageResultCode.OperationSucceeded, + unmountContainer("testRenameContainer.1", false)); + + assertEquals(StorageResultCode.OperationSucceeded, + renameContainer("testRenameContainer.1", "testRenameContainer.2")); + + assertFalse(containerExists("testRenameContainer.1")); + assertTrue(containerExists("testRenameContainer.2")); } - public void testRenameDstMountedContainer() { - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testRenameContainer.1", 4, "none")); + public void test_Fat_External_RenameSrcMounted_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } - Assert.assertEquals(StorageResultCode.OperationSucceeded, - unmountContainer("testRenameContainer.1", false)); + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testRenameContainer.2", 4, "none")); + assertEquals(StorageResultCode.OperationFailedStorageMounted, + renameContainer("testRenameContainer.1", "testRenameContainer.2")); + } - Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted, - renameContainer("testRenameContainer.1", "testRenameContainer.2")); - } catch (Exception e) { - failStr(e); + public void test_Fat_External_RenameDstMounted_Failure() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; } + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testRenameContainer.1", 4, "none", FS_FAT, true)); + + assertEquals(StorageResultCode.OperationSucceeded, + unmountContainer("testRenameContainer.1", false)); + + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testRenameContainer.2", 4, "none", FS_FAT, true)); + + assertEquals(StorageResultCode.OperationFailedStorageMounted, + renameContainer("testRenameContainer.1", "testRenameContainer.2")); } - public void testContainerSize() { + public void test_Fat_External_Size_Success() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + IMountService ms = getMs(); - try { - Assert.assertEquals(StorageResultCode.OperationSucceeded, - createContainer("testContainerSize", 1, "none")); - String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); - - byte[] buf = new byte[4096]; - File f = new File(path, "reference"); - FileOutputStream fos = new FileOutputStream(f); - for (int i = 0; i < (1024 * 1024); i+= buf.length) { - fos.write(buf); - } - fos.close(); - } catch (Exception e) { - failStr(e); + assertEquals(StorageResultCode.OperationSucceeded, + createContainer("testContainerSize", 1, "none", FS_FAT, true)); + String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + "testContainerSize"); + + byte[] buf = new byte[4096]; + File f = new File(path, "reference"); + FileOutputStream fos = new FileOutputStream(f); + for (int i = 0; i < (1024 * 1024); i += buf.length) { + fos.write(buf); } + fos.close(); + } + + public void testGetSecureContainerPath_NonExistPath_Failure() throws Exception { + IMountService ms = getMs(); + assertNull("Getting the path for an invalid container should return null", + ms.getSecureContainerPath("jparks.broke.it")); } /*------------ Tests for unmounting volume ---*/ public final long MAX_WAIT_TIME=120*1000; public final long WAIT_TIME_INCR=20*1000; - boolean getMediaState() { - try { + + boolean getMediaState() throws Exception { String mPath = Environment.getExternalStorageDirectory().toString(); String state = getMs().getVolumeState(mPath); return Environment.MEDIA_MOUNTED.equals(state); - } catch (RemoteException e) { - return false; - } } - boolean mountMedia() { + boolean mountMedia() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return true; + } + if (getMediaState()) { return true; } - try { + String mPath = Environment.getExternalStorageDirectory().toString(); int ret = getMs().mountVolume(mPath); return ret == StorageResultCode.OperationSucceeded; - } catch (RemoteException e) { - return false; - } } class StorageListener extends StorageEventListener { @@ -410,10 +551,15 @@ public class AsecTests extends AndroidTestCase { } } - private boolean unmountMedia() { + private void unmountMedia() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + if (!getMediaState()) { - return true; + return; } + String path = Environment.getExternalStorageDirectory().toString(); StorageListener observer = new StorageListener(); StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); @@ -428,17 +574,15 @@ public class AsecTests extends AndroidTestCase { waitTime += WAIT_TIME_INCR; } if(!observer.isDone()) { - throw new Exception("Timed out waiting for packageInstalled callback"); + fail("Timed out waiting for packageInstalled callback"); } - return true; } - } catch (Exception e) { - return false; } finally { sm.unregisterListener(observer); } } - public void testUnmount() { + + public void testUnmount() throws Exception { boolean oldStatus = getMediaState(); Log.i(TAG, "oldStatus="+oldStatus); try { @@ -446,7 +590,7 @@ public class AsecTests extends AndroidTestCase { if (!getMediaState()) { mountMedia(); } - assertTrue(unmountMedia()); + unmountMedia(); } finally { // Restore old status boolean currStatus = getMediaState(); @@ -472,7 +616,11 @@ public class AsecTests extends AndroidTestCase { * This test invokes unmount multiple time and expects the call back * to be invoked just once. */ - public void testUnmountMultiple() { + public void testUnmountMultiple() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + boolean oldStatus = getMediaState(); StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); MultipleStorageLis observer = new MultipleStorageLis(); @@ -494,12 +642,10 @@ public class AsecTests extends AndroidTestCase { waitTime += WAIT_TIME_INCR; } if(!observer.isDone()) { - failStr("Timed out waiting for packageInstalled callback"); + fail("Timed out waiting for packageInstalled callback"); } } assertEquals(observer.count, 1); - } catch (Exception e) { - failStr(e); } finally { sm.unregisterListener(observer); // Restore old status @@ -514,7 +660,7 @@ public class AsecTests extends AndroidTestCase { } } } - + class ShutdownObserver extends IMountShutdownObserver.Stub{ private boolean doneFlag = false; int statusCode; @@ -536,28 +682,26 @@ public class AsecTests extends AndroidTestCase { } - boolean invokeShutdown() { + void invokeShutdown() throws Exception { IMountService ms = getMs(); ShutdownObserver observer = new ShutdownObserver(); synchronized (observer) { - try { - ms.shutdown(observer); - return true; - } catch (RemoteException e) { - failStr(e); - } + ms.shutdown(observer); } - return false; } - public void testShutdown() { + public void testShutdown() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + boolean oldStatus = getMediaState(); try { // Mount media firsts if (!getMediaState()) { mountMedia(); } - assertTrue(invokeShutdown()); + invokeShutdown(); } finally { // Restore old status boolean currStatus = getMediaState(); @@ -576,7 +720,11 @@ public class AsecTests extends AndroidTestCase { * This test invokes unmount multiple time and expects the call back * to be invoked just once. */ - public void testShutdownMultiple() { + public void testShutdownMultiple() throws Exception { + if (Environment.isExternalStorageEmulated()) { + return; + } + boolean oldStatus = getMediaState(); try { // Mount media firsts @@ -586,13 +734,9 @@ public class AsecTests extends AndroidTestCase { IMountService ms = getMs(); ShutdownObserver observer = new ShutdownObserver(); synchronized (observer) { - try { - ms.shutdown(observer); - for (int i = 0; i < 4; i++) { - ms.shutdown(null); - } - } catch (RemoteException e) { - failStr(e); + ms.shutdown(observer); + for (int i = 0; i < 4; i++) { + ms.shutdown(null); } } } finally { diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 8e3a3c5..3eec18c 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -81,13 +81,15 @@ public class DefaultContainerService extends IntentService { * @return Returns the new cache path where the resource has been copied into * */ - public String copyResourceToContainer(final Uri packageURI, - final String cid, - final String key, final String resFileName) { + public String copyResourceToContainer(final Uri packageURI, final String cid, + final String key, final String resFileName, final String publicResFileName, + boolean isExternal, boolean isForwardLocked) { if (packageURI == null || cid == null) { return null; } - return copyResourceInner(packageURI, cid, key, resFileName); + + return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName, + isExternal, isForwardLocked); } /* @@ -169,22 +171,23 @@ public class DefaultContainerService extends IntentService { } @Override - public boolean checkInternalFreeStorage(Uri packageUri, long threshold) - throws RemoteException { + public boolean checkInternalFreeStorage(Uri packageUri, boolean isForwardLocked, + long threshold) throws RemoteException { final File apkFile = new File(packageUri.getPath()); try { - return isUnderInternalThreshold(apkFile, threshold); - } catch (FileNotFoundException e) { + return isUnderInternalThreshold(apkFile, isForwardLocked, threshold); + } catch (IOException e) { return true; } } @Override - public boolean checkExternalFreeStorage(Uri packageUri) throws RemoteException { + public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked) + throws RemoteException { final File apkFile = new File(packageUri.getPath()); try { - return isUnderExternalThreshold(apkFile); - } catch (FileNotFoundException e) { + return isUnderExternalThreshold(apkFile, isForwardLocked); + } catch (IOException e) { return true; } } @@ -259,12 +262,16 @@ public class DefaultContainerService extends IntentService { return mBinder; } - private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName) { - // Make sure the sdcard is mounted. - String status = Environment.getExternalStorageState(); - if (!status.equals(Environment.MEDIA_MOUNTED)) { - Slog.w(TAG, "Make sure sdcard is mounted."); - return null; + private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName, + String publicResFileName, boolean isExternal, boolean isForwardLocked) { + + if (isExternal) { + // Make sure the sdcard is mounted. + String status = Environment.getExternalStorageState(); + if (!status.equals(Environment.MEDIA_MOUNTED)) { + Slog.w(TAG, "Make sure sdcard is mounted."); + return null; + } } // The .apk file @@ -272,17 +279,18 @@ public class DefaultContainerService extends IntentService { File codeFile = new File(codePath); // Calculate size of container needed to hold base APK. - int sizeMb; + final int sizeMb; try { - sizeMb = calculateContainerSize(codeFile); - } catch (FileNotFoundException e) { - Slog.w(TAG, "File does not exist when trying to copy " + codeFile.getPath()); + sizeMb = calculateContainerSize(codeFile, isForwardLocked); + } catch (IOException e) { + Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath()); return null; } // Create new container - final String newCachePath; - if ((newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid())) == null) { + final String newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(), + isExternal); + if (newCachePath == null) { Slog.e(TAG, "Failed to create container " + newCid); return null; } @@ -303,6 +311,30 @@ public class DefaultContainerService extends IntentService { return null; } + if (isForwardLocked) { + File publicZipFile = new File(newCachePath, publicResFileName); + try { + PackageHelper.extractPublicFiles(resFile.getAbsolutePath(), publicZipFile); + if (localLOGV) { + Slog.i(TAG, "Copied resources to " + publicZipFile); + } + } catch (IOException e) { + Slog.e(TAG, "Could not chown public APK " + publicZipFile.getAbsolutePath() + ": " + + e.getMessage()); + PackageHelper.destroySdDir(newCid); + return null; + } + + 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()); + PackageHelper.destroySdDir(newCid); + return null; + } + } + final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME); if (sharedLibraryDir.mkdir()) { int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir); @@ -412,18 +444,13 @@ public class DefaultContainerService extends IntentService { int prefer; boolean checkBoth = false; + final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + check_inner : { /* * Explicit install flags should override the manifest settings. */ - if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) { - /* - * Forward-locked applications cannot be installed on SD card, - * so only allow checking internal storage. - */ - prefer = PREFER_INTERNAL; - break check_inner; - } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) { + if ((flags & PackageManager.INSTALL_INTERNAL) != 0) { prefer = PREFER_INTERNAL; break check_inner; } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) { @@ -473,8 +500,8 @@ public class DefaultContainerService extends IntentService { boolean fitsOnInternal = false; if (checkBoth || prefer == PREFER_INTERNAL) { try { - fitsOnInternal = isUnderInternalThreshold(apkFile, threshold); - } catch (FileNotFoundException e) { + fitsOnInternal = isUnderInternalThreshold(apkFile, isForwardLocked, threshold); + } catch (IOException e) { return PackageHelper.RECOMMEND_FAILED_INVALID_URI; } } @@ -482,8 +509,8 @@ public class DefaultContainerService extends IntentService { boolean fitsOnSd = false; if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)) { try { - fitsOnSd = isUnderExternalThreshold(apkFile); - } catch (FileNotFoundException e) { + fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked); + } catch (IOException e) { return PackageHelper.RECOMMEND_FAILED_INVALID_URI; } } @@ -527,13 +554,17 @@ public class DefaultContainerService extends IntentService { * @return true if file fits under threshold * @throws FileNotFoundException when APK does not exist */ - private boolean isUnderInternalThreshold(File apkFile, long threshold) - throws FileNotFoundException { - final long size = apkFile.length(); + private boolean isUnderInternalThreshold(File apkFile, boolean isForwardLocked, long threshold) + throws IOException { + long size = apkFile.length(); if (size == 0 && !apkFile.exists()) { throw new FileNotFoundException(); } + if (isForwardLocked) { + size += PackageHelper.extractPublicFiles(apkFile.getAbsolutePath(), null); + } + final StatFs internalStats = new StatFs(Environment.getDataDirectory().getPath()); final long availInternalSize = (long) internalStats.getAvailableBlocks() * (long) internalStats.getBlockSize(); @@ -549,12 +580,13 @@ public class DefaultContainerService extends IntentService { * @return true if file fits * @throws IOException when file does not exist */ - private boolean isUnderExternalThreshold(File apkFile) throws FileNotFoundException { + private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked) + throws IOException { if (Environment.isExternalStorageEmulated()) { return false; } - final int sizeMb = calculateContainerSize(apkFile); + final int sizeMb = calculateContainerSize(apkFile, isForwardLocked); final int availSdMb; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { @@ -573,9 +605,9 @@ public class DefaultContainerService extends IntentService { * * @param apkFile file from which to calculate size * @return size in megabytes (2^20 bytes) - * @throws FileNotFoundException when file does not exist + * @throws IOException when there is a problem reading the file */ - private int calculateContainerSize(File apkFile) throws FileNotFoundException { + private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException { // Calculate size of container needed to hold base APK. long sizeBytes = apkFile.length(); if (sizeBytes == 0 && !apkFile.exists()) { @@ -586,6 +618,10 @@ public class DefaultContainerService extends IntentService { // container size. sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile); + if (forwardLocked) { + sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null); + } + int sizeMb = (int) (sizeBytes >> 20); if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) { sizeMb++; diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 510bdb2..d6606f6 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -668,6 +668,9 @@ class MountService extends IMountService.Stub updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED); } + // Let package manager load internal ASECs. + mPms.updateExternalMediaStatus(true, false); + /* * Now that we've done our initialization, release * the hounds! @@ -1435,15 +1438,16 @@ class MountService extends IMountService.Stub } } - public int createSecureContainer(String id, int sizeMb, String fstype, - String key, int ownerUid) { + public int createSecureContainer(String id, int sizeMb, String fstype, String key, + int ownerUid, boolean external) { validatePermission(android.Manifest.permission.ASEC_CREATE); waitForReady(); warnOnNotMounted(); int rc = StorageResultCode.OperationSucceeded; try { - mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid); + mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid, + external ? "1" : "0"); } catch (NativeDaemonConnectorException e) { rc = StorageResultCode.OperationFailedInternalError; } @@ -1473,6 +1477,23 @@ class MountService extends IMountService.Stub return rc; } + public int fixPermissionsSecureContainer(String id, int gid, String filename) { + validatePermission(android.Manifest.permission.ASEC_CREATE); + warnOnNotMounted(); + + int rc = StorageResultCode.OperationSucceeded; + try { + mConnector.execute("asec", "fixperms", id, gid, filename); + /* + * Fix permissions does a remount, so no need to update + * mAsecMountSet + */ + } catch (NativeDaemonConnectorException e) { + rc = StorageResultCode.OperationFailedInternalError; + } + return rc; + } + public int destroySecureContainer(String id, boolean force) { validatePermission(android.Manifest.permission.ASEC_DESTROY); waitForReady(); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 00d86e3..21ae624 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -723,7 +723,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (msg.obj != null) { @SuppressWarnings("unchecked") - Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj; + Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj; if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers"); // Unload containers unloadAllContainers(args); @@ -830,17 +830,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - static boolean installOnSd(int flags) { - if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) || - ((flags & PackageManager.INSTALL_INTERNAL) != 0)) { - return false; - } - if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) { - return true; - } - return false; - } - public static final IPackageManager main(Context context, boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore); @@ -5396,7 +5385,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mInstallLock) { installPackageLI(args, true, res); } - args.doPostInstall(res.returnCode); + args.doPostInstall(res.returnCode, res.uid); } // A restore should be performed at this point if (a) the install @@ -5646,7 +5635,6 @@ public class PackageManagerService extends IPackageManager.Stub { */ public void handleStartCopy() throws RemoteException { int ret = PackageManager.INSTALL_SUCCEEDED; - final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; PackageInfoLite pkgLite = null; @@ -5655,10 +5643,6 @@ public class PackageManagerService extends IPackageManager.Stub { // Check if both bits are set. Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; - } else if (fwdLocked && onSd) { - // Check for forward locked apps - Slog.w(TAG, "Cannot install fwd locked apps on sdcard"); - ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; } else { final long lowThreshold; @@ -5835,6 +5819,10 @@ public class PackageManagerService extends IPackageManager.Stub { mArgs = createInstallArgs(this); mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; } + + public boolean isForwardLocked() { + return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + } } /* @@ -5850,14 +5838,16 @@ public class PackageManagerService extends IPackageManager.Stub { final String packageName; final InstallArgs srcArgs; final InstallArgs targetArgs; + int uid; int mRet; MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, - String packageName, String dataDir) { + String packageName, String dataDir, int uid) { this.srcArgs = srcArgs; this.observer = observer; this.flags = flags; this.packageName = packageName; + this.uid = uid; if (srcArgs != null) { Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath())); targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir); @@ -5892,7 +5882,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override void handleReturnCode() { - targetArgs.doPostInstall(mRet); + targetArgs.doPostInstall(mRet, uid); int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR; if (mRet == PackageManager.INSTALL_SUCCEEDED) { currentStatus = PackageManager.MOVE_SUCCEEDED; @@ -5908,9 +5898,35 @@ public class PackageManagerService extends IPackageManager.Stub { } } + /** + * Used during creation of InstallArgs + * + * @param flags package installation flags + * @return true if should be installed on external storage + */ + private static boolean installOnSd(int flags) { + if ((flags & PackageManager.INSTALL_INTERNAL) != 0) { + return false; + } + if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) { + return true; + } + return false; + } + + /** + * Used during creation of InstallArgs + * + * @param flags package installation flags + * @return true if should be installed as forward locked + */ + private static boolean installForwardLocked(int flags) { + return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + } + private InstallArgs createInstallArgs(InstallParams params) { - if (installOnSd(params.flags)) { - return new SdInstallArgs(params); + if (installOnSd(params.flags) || params.isForwardLocked()) { + return new AsecInstallArgs(params); } else { return new FileInstallArgs(params); } @@ -5918,8 +5934,9 @@ public class PackageManagerService extends IPackageManager.Stub { private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath, String nativeLibraryPath) { - if (installOnSd(flags)) { - return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); + if (installOnSd(flags) || installForwardLocked(flags)) { + return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, + (flags & PackageManager.INSTALL_EXTERNAL) != 0); } else { return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); } @@ -5927,9 +5944,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)) { - String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME); - return new SdInstallArgs(packageURI, cid); + if (installOnSd(flags) || installForwardLocked(flags)) { + String cid = getNextCodePath(null, pkgName, "/" + AsecInstallArgs.RES_FILE_NAME); + return new AsecInstallArgs(packageURI, cid, + (flags & PackageManager.INSTALL_EXTERNAL) != 0); } else { return new FileInstallArgs(packageURI, pkgName, dataDir); } @@ -5956,7 +5974,8 @@ public class PackageManagerService extends IPackageManager.Stub { abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException; abstract int doPreInstall(int status); abstract boolean doRename(int status, String pkgName, String oldCodePath); - abstract int doPostInstall(int status); + + abstract int doPostInstall(int status, int uid); abstract String getCodePath(); abstract String getResourcePath(); abstract String getNativeLibraryPath(); @@ -5964,6 +5983,10 @@ public class PackageManagerService extends IPackageManager.Stub { abstract void cleanUpResourcesLI(); abstract boolean doPostDeleteLI(boolean delete); abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException; + + protected boolean isFwdLocked() { + return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; + } } class FileInstallArgs extends InstallArgs { @@ -6016,7 +6039,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); - return imcs.checkInternalFreeStorage(packageURI, lowThreshold); + return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold); } finally { mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); } @@ -6126,7 +6149,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - int doPostInstall(int status) { + int doPostInstall(int status, int uid) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } @@ -6229,10 +6252,6 @@ public class PackageManagerService extends IPackageManager.Stub { cleanUpResourcesLI(); return true; } - - private boolean isFwdLocked() { - return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; - } } /** @@ -6246,20 +6265,23 @@ public class PackageManagerService extends IPackageManager.Stub { return subStr1.substring(sidx+1, eidx); } - class SdInstallArgs extends InstallArgs { + class AsecInstallArgs extends InstallArgs { static final String RES_FILE_NAME = "pkg.apk"; + static final String PUBLIC_RES_FILE_NAME = "res.zip"; String cid; String packagePath; + String resourcePath; String libraryPath; - SdInstallArgs(InstallParams params) { + AsecInstallArgs(InstallParams params) { super(params.packageURI, params.observer, params.flags, params.installerPackageName, params.manifestDigest); } - SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { - super(null, null, PackageManager.INSTALL_EXTERNAL, null, null); + AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, + boolean isExternal) { + super(null, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null); // Extract cid from fullCodePath int eidx = fullCodePath.lastIndexOf("/"); String subStr1 = fullCodePath.substring(0, eidx); @@ -6268,14 +6290,14 @@ public class PackageManagerService extends IPackageManager.Stub { setCachePath(subStr1); } - SdInstallArgs(String cid) { - super(null, null, PackageManager.INSTALL_EXTERNAL, null, null); + AsecInstallArgs(String cid) { + super(null, null, 0, null, null); this.cid = cid; setCachePath(PackageHelper.getSdDir(cid)); } - SdInstallArgs(Uri packageURI, String cid) { - super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null, null); + AsecInstallArgs(Uri packageURI, String cid, boolean isExternal) { + super(packageURI, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null); this.cid = cid; } @@ -6287,12 +6309,16 @@ public class PackageManagerService extends IPackageManager.Stub { try { mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); - return imcs.checkExternalFreeStorage(packageURI); + return imcs.checkExternalFreeStorage(packageURI, isFwdLocked()); } finally { mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); } } + private final boolean isExternal() { + return (flags & PackageManager.INSTALL_EXTERNAL) != 0; + } + int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { if (temp) { createCopyFile(); @@ -6308,8 +6334,8 @@ public class PackageManagerService extends IPackageManager.Stub { try { mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); - newCachePath = imcs.copyResourceToContainer(packageURI, cid, - getEncryptKey(), RES_FILE_NAME); + newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(), + RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked()); } finally { mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); } @@ -6329,7 +6355,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override String getResourcePath() { - return packagePath; + return resourcePath; } @Override @@ -6405,22 +6431,36 @@ public class PackageManagerService extends IPackageManager.Stub { File cachePath = new File(newCachePath); libraryPath = new File(cachePath, LIB_DIR_NAME).getPath(); packagePath = new File(cachePath, RES_FILE_NAME).getPath(); + + if (isFwdLocked()) { + resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath(); + } else { + resourcePath = packagePath; + } } - int doPostInstall(int status) { + int doPostInstall(int status, int uid) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); } else { + 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; + } + boolean mounted = PackageHelper.isContainerMounted(cid); if (!mounted) { - PackageHelper.mountSdDir(cid, - getEncryptKey(), Process.myUid()); + PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid()); } } return status; } private void cleanUp() { + if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp"); + // Destroy secure container PackageHelper.destroySdDir(cid); } @@ -6749,8 +6789,7 @@ public class PackageManagerService extends IPackageManager.Stub { // We didn't need to disable the .apk as a current system package, // which means we are replacing another update that is already // installed. We need to make sure to delete the older one's .apk. - res.removedInfo.args = createInstallArgs(isExternal(pkg) - ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL, + res.removedInfo.args = createInstallArgs(0, deletedPackage.applicationInfo.sourceDir, deletedPackage.applicationInfo.publicSourceDir, deletedPackage.applicationInfo.nativeLibraryDir); @@ -6836,13 +6875,9 @@ public class PackageManagerService extends IPackageManager.Stub { // Discontinue if moving dex files failed. return; } - if((res.returnCode = setPermissionsLI(newPackage)) - != PackageManager.INSTALL_SUCCEEDED) { - mInstaller.rmdex(newPackage.mScanPath); - return; - } else { - Log.d(TAG, "New package installed in " + newPackage.mPath); - } + + Log.d(TAG, "New package installed in " + newPackage.mPath); + synchronized (mPackages) { updatePermissionsLPw(newPackage.packageName, newPackage, UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0 @@ -6872,10 +6907,9 @@ public class PackageManagerService extends IPackageManager.Stub { res.returnCode = PackageManager.INSTALL_SUCCEEDED; // Retrieve PackageSettings and parse package - int parseFlags = PackageParser.PARSE_CHATTY | - (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | - (onSd ? PackageParser.PARSE_ON_SDCARD : 0); - parseFlags |= mDefParseFlags; + int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY + | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) + | (onSd ? PackageParser.PARSE_ON_SDCARD : 0); PackageParser pp = new PackageParser(tmpPackageFile.getPath()); pp.setSeparateProcesses(mSeparateProcesses); final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, @@ -6972,27 +7006,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private int setPermissionsLI(PackageParser.Package newPackage) { - int retCode = 0; - // TODO Gross hack but fix later. Ideally move this to be a post installation - // check after alloting uid. - if (isForwardLocked(newPackage)) { - retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath), - newPackage.applicationInfo.uid); - } else { - // The permissions on the resource file was set when it was copied for - // non forward locked apps and apps on sdcard - } - - if (retCode != 0) { - Slog.e(TAG, "Couldn't set new package file permissions for " + newPackage.mPath - + ". The return code was: " + retCode); - // TODO Define new internal error - return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; - } - return PackageManager.INSTALL_SUCCEEDED; - } - private static boolean isForwardLocked(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0; } @@ -7001,6 +7014,10 @@ public class PackageManagerService extends IPackageManager.Stub { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } + private static boolean isExternal(PackageSetting ps) { + return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; + } + private static boolean isSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @@ -8359,8 +8376,6 @@ public class PackageManagerService extends IPackageManager.Stub { // little while. mHandler.post(new Runnable() { public void run() { - // TODO fix this; this does nothing. - mHandler.removeCallbacks(this); updateExternalMediaStatusInner(mediaStatus, reportStatus); } }); @@ -8372,13 +8387,13 @@ public class PackageManagerService extends IPackageManager.Stub { * Please note that we always have to report status if reportStatus has been * set to true especially when unloading packages. */ - private void updateExternalMediaStatusInner(boolean mediaStatus, boolean reportStatus) { + private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus) { // Collection of uids int uidArr[] = null; // Collection of stale containers HashSet<String> removeCids = new HashSet<String>(); // Collection of packages on external media with valid containers. - HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>(); + HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>(); // Get list of secure containers. final String list[] = PackageHelper.getSecureContainerList(); if (list == null || list.length == 0) { @@ -8391,7 +8406,7 @@ public class PackageManagerService extends IPackageManager.Stub { // reader synchronized (mPackages) { for (String cid : list) { - SdInstallArgs args = new SdInstallArgs(cid); + AsecInstallArgs args = new AsecInstallArgs(cid); if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid); String pkgName = args.getPackageName(); @@ -8441,7 +8456,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } // Process packages with valid entries. - if (mediaStatus) { + if (isMounted) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); loadMediaPackages(processCids, uidArr, removeCids); @@ -8476,12 +8491,12 @@ public class PackageManagerService extends IPackageManager.Stub { * the cid is added to list of removeCids. We currently don't delete stale * containers. */ - private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[], + private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[], HashSet<String> removeCids) { ArrayList<String> pkgList = new ArrayList<String>(); - Set<SdInstallArgs> keys = processCids.keySet(); + Set<AsecInstallArgs> keys = processCids.keySet(); boolean doGc = false; - for (SdInstallArgs args : keys) { + for (AsecInstallArgs args : keys) { String codePath = processCids.get(args); if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : " + args.cid); @@ -8517,7 +8532,8 @@ public class PackageManagerService extends IPackageManager.Stub { retCode = PackageManager.INSTALL_SUCCEEDED; pkgList.add(pkg.packageName); // Post process args - args.doPostInstall(PackageManager.INSTALL_SUCCEEDED); + args.doPostInstall(PackageManager.INSTALL_SUCCEEDED, + pkg.applicationInfo.uid); } } else { Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard"); @@ -8580,9 +8596,9 @@ public class PackageManagerService extends IPackageManager.Stub { /* * Utility method to unload a list of specified containers */ - private void unloadAllContainers(Set<SdInstallArgs> cidArgs) { + private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) { // Just unmount all valid containers. - for (SdInstallArgs arg : cidArgs) { + for (AsecInstallArgs arg : cidArgs) { synchronized (mInstallLock) { arg.doPostDeleteLI(false); } @@ -8598,14 +8614,14 @@ public class PackageManagerService extends IPackageManager.Stub { * that we always have to post this message if status has been requested no * matter what. */ - private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[], + private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[], final boolean reportStatus) { if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages"); ArrayList<String> pkgList = new ArrayList<String>(); - ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>(); - final Set<SdInstallArgs> keys = processCids.keySet(); - for (SdInstallArgs args : keys) { + ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>(); + final Set<AsecInstallArgs> keys = processCids.keySet(); + for (AsecInstallArgs args : keys) { String pkgName = args.getPackageName(); if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName); @@ -8666,9 +8682,6 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.applicationInfo != null && isSystemApp(pkg)) { Slog.w(TAG, "Cannot move system application"); returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE; - } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) { - Slog.w(TAG, "Cannot move forward locked app."); - returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED; } else if (pkg.mOperationPending) { Slog.w(TAG, "Attempt to move package which has pending operations"); returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING; @@ -8700,13 +8713,14 @@ public class PackageManagerService extends IPackageManager.Stub { * anyway. */ if (returnCode != PackageManager.MOVE_SUCCEEDED) { - processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode); + processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1), + returnCode); } else { Message msg = mHandler.obtainMessage(INIT_COPY); InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, - pkg.applicationInfo.dataDir); + pkg.applicationInfo.dataDir, pkg.applicationInfo.uid); msg.obj = mp; mHandler.sendMessage(msg); } @@ -8831,7 +8845,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (returnCode != PackageManager.MOVE_SUCCEEDED) { // Clean up failed installation if (mp.targetArgs != null) { - mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR); + mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, + -1); } } else { // Force a gc to clear things up. |