Add new install flag to install on internal flash only
Change default install location policy for new flag.
New error code for media unavailable.

Change-Id: I5a5d0828b067692b2b94a15a2bcc7534f796c1a2
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index fc5707d..cfc2e75 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -602,6 +602,9 @@
             } else if (opt.equals("-s")) {
                 // Override if -s option is specified.
                 installFlags |= PackageManager.INSTALL_EXTERNAL;
+            } else if (opt.equals("-f")) {
+                // Override if -s option is specified.
+                installFlags |= PackageManager.INSTALL_INTERNAL;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -861,7 +864,7 @@
         System.err.println("       pm list instrumentation [-f] [TARGET-PACKAGE]");
         System.err.println("       pm list features");
         System.err.println("       pm path PACKAGE");
-        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] PATH");
+        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm mountsd [-m true/false]");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
@@ -895,6 +898,7 @@
         System.err.println("  -t: allow test .apks to be installed.");
         System.err.println("  -i: specify the installer package name.");
         System.err.println("  -s: install package on sdcard.");
+        System.err.println("  -f: install package on internal flash.");
         System.err.println("");
         System.err.println("The uninstall command removes a package from the system. Options:");
         System.err.println("  -k: keep the data and cache directories around.");
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e1fbe48..bbf4ca1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -261,6 +261,13 @@
     public static final int INSTALL_EXTERNAL = 0x00000008;
 
     /**
+    * Flag parameter for {@link #installPackage} to indicate that this
+    * package has to be installed on the sdcard.
+    * @hide
+    */
+   public static final int INSTALL_INTERNAL = 0x00000010;
+
+    /**
      * Flag parameter for
      * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
      * that you don't want to kill the app containing the component.  Be careful when you set this
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index badabb0..0f817b7 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -26,6 +26,6 @@
                 String key, String resFileName);
     boolean copyResource(in Uri packageURI,
                 in ParcelFileDescriptor outStream);
-    PackageInfoLite getMinimalPackageInfo(in Uri fileUri);
+    PackageInfoLite getMinimalPackageInfo(in Uri fileUri, int flags);
     boolean checkFreeStorage(boolean external, in Uri fileUri);
 }
\ No newline at end of file
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 77d11cc..14c8806 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -105,7 +105,7 @@
          * @return Returns PackageInfoLite object containing
          * the package info and recommended app location.
          */
-        public PackageInfoLite getMinimalPackageInfo(final Uri fileUri) {
+        public PackageInfoLite getMinimalPackageInfo(final Uri fileUri, int flags) {
             PackageInfoLite ret = new PackageInfoLite();
             if (fileUri == null) {
                 Log.i(TAG, "Invalid package uri " + fileUri);
@@ -136,7 +136,7 @@
                 return ret;
             }
             ret.packageName = pkg.packageName;
-            ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation, archiveFilePath);
+            ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation, archiveFilePath, flags);
             return ret;
         }
 
@@ -305,8 +305,65 @@
     private static final int ERR_LOC = -1;
 
     private int recommendAppInstallLocation(int installLocation,
-            String archiveFilePath) {
-        // Initial implementation:
+            String archiveFilePath, int flags) {
+        boolean checkInt = false;
+        boolean checkExt = false;
+        boolean checkBoth = false;
+        check_inner : {
+            // Check flags.
+            if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
+                // Check for forward locked app
+                checkInt = true;
+                break check_inner;
+            } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
+                // Explicit flag to install internally.
+                // Check internal storage and return
+                checkInt = true;
+                break check_inner;
+            } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                // Explicit flag to install externally.
+                // Check external storage and return
+                checkExt = true;
+                break check_inner;
+            }
+            // Check for manifest option
+            if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
+                checkInt = true;
+                break check_inner;
+            } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
+                checkExt = true;
+                checkBoth = true;
+                break check_inner;
+            } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
+                checkInt = true;
+                checkBoth = true;
+                break check_inner;
+            }
+            // Check if user option is enabled
+            boolean setInstallLoc = Settings.System.getInt(getApplicationContext()
+                    .getContentResolver(),
+                    Settings.System.SET_INSTALL_LOCATION, 0) != 0;
+            if (setInstallLoc) {
+                // Pick user preference
+                int installPreference = Settings.System.getInt(getApplicationContext()
+                        .getContentResolver(),
+                        Settings.System.DEFAULT_INSTALL_LOCATION,
+                        PackageHelper.APP_INSTALL_AUTO);
+                if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
+                    checkInt = true;
+                    checkBoth = true;
+                    break check_inner;
+                } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
+                    checkExt = true;
+                    checkBoth = true;
+                    break check_inner;
+                }
+            }
+            // Fall back to default policy if nothing else is specified.
+            checkInt = true;
+            checkBoth = true;
+        }
+
         // Package size = code size + cache size + data size
         // If code size > 1 MB, install on SD card.
         // Else install on internal NAND flash, unless space on NAND is less than 10%
@@ -330,77 +387,47 @@
 
         File apkFile = new File(archiveFilePath);
         long pkgLen = apkFile.length();
-
-        boolean auto = true;
+        
         // To make final copy
         long reqInstallSize = pkgLen;
         // For dex files. Just ignore and fail when extracting. Max limit of 2Gig for now.
         long reqInternalSize = 0;
         boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
         boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalSize);
-        boolean fitsOnSd = mediaAvailable && (reqInstallSize < availSDSize)
-                 && intThresholdOk &&
-                (reqInternalSize < availInternalSize);
+        boolean fitsOnSd = false;
+        if (mediaAvailable && (reqInstallSize < availSDSize)) {
+            // If we do not have an internal size requirement
+            // don't do a threshold check.
+            if (reqInternalSize == 0) {
+                fitsOnSd = true;
+            } else if ((reqInternalSize < availInternalSize) && intThresholdOk) {
+                fitsOnSd = true;
+            }
+        }
         boolean fitsOnInt = intThresholdOk && intAvailOk;
-
-        // Consider application flags preferences as well...
-        boolean installOnlyOnSd = (installLocation ==
-                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-        boolean installOnlyInternal = (installLocation ==
-                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-        if (installOnlyInternal) {
-            // If set explicitly in manifest,
-            // let that override everything else
-            auto = false;
-        } else if (installOnlyOnSd){
-            // Check if this can be accommodated on the sdcard
+        if (checkInt) {
+            // Check for internal memory availability
+            if (fitsOnInt) {
+                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+            }
+        } else if (checkExt) {
             if (fitsOnSd) {
-                auto = false;
-            }
-        } else {
-            // Check if user option is enabled
-            boolean setInstallLoc = Settings.System.getInt(getApplicationContext()
-                    .getContentResolver(),
-                    Settings.System.SET_INSTALL_LOCATION, 0) != 0;
-            if (setInstallLoc) {
-                // Pick user preference
-                int installPreference = Settings.System.getInt(getApplicationContext()
-                        .getContentResolver(),
-                        Settings.System.DEFAULT_INSTALL_LOCATION,
-                        PackageHelper.APP_INSTALL_AUTO);
-                if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
-                    installOnlyInternal = true;
-                    auto = false;
-                } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
-                    installOnlyOnSd = true;
-                    auto = false;
-                }
+                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
             }
         }
-        if (!auto) {
-            if (installOnlyOnSd) {
-                if (fitsOnSd) {
-                    return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
-                }
-                if (!mediaAvailable) {
-                    return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
-                }
-                return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
-            } else if (installOnlyInternal){
-                // Check on internal flash
-                return fitsOnInt ?  PackageHelper.RECOMMEND_INSTALL_INTERNAL :
-                    PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+        if (checkBoth) {
+            // Check for internal first
+            if (fitsOnInt) {
+                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+            }
+            // Check for external next
+            if (fitsOnSd) {
+                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
             }
         }
-        // Try to install internally
-        if (fitsOnInt) {
-            return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+        if (checkExt || checkBoth && !mediaAvailable) {
+            return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
         }
-        // Try the sdcard now.
-        if (fitsOnSd) {
-            return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
-        }
-        // Return error code
         return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
     }
 
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 818e99e..55725bd 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -595,10 +595,13 @@
 
     static boolean installOnSd(int flags) {
         if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
-                ((flags & PackageManager.INSTALL_EXTERNAL) == 0)) {
+                ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
             return false;
         }
-        return true;
+        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            return true;
+        }
+        return false;
     }
 
     static boolean isFwdLocked(int flags) {
@@ -4452,8 +4455,8 @@
                 res.uid = -1;
                 res.pkg = null;
                 res.removedInfo = new PackageRemovedInfo();
-                args.doPreInstall(res.returnCode);
                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+                    args.doPreInstall(res.returnCode);
                     synchronized (mInstallLock) {
                         installPackageLI(args, true, res);
                     }
@@ -4623,13 +4626,18 @@
             int ret = PackageManager.INSTALL_SUCCEEDED;
             boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
             boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
-            // Dont need to invoke getInstallLocation for forward locked apps.
-            if (fwdLocked && onSd) {
+            boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+            if (onInt && onSd) {
+                // 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 {
                 // Remote call to find out default install location
-                PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI);
+                PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
                 int loc = pkgLite.recommendedInstallLocation;
                 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
                     ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
@@ -4644,14 +4652,16 @@
                 } else {
                     // Override with defaults if needed.
                     loc = installLocationPolicy(pkgLite, flags);
-                    // Override install location with flags
-                    if ((flags & PackageManager.INSTALL_EXTERNAL) == 0){
+                    if (!onSd && !onInt) {
+                        // Override install location with flags
                         if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                             // Set the flag to install on external media.
                             flags |= PackageManager.INSTALL_EXTERNAL;
+                            flags &= ~PackageManager.INSTALL_INTERNAL;
                         } else {
                             // Make sure the flag for installing on external
                             // media is unset
+                            flags |= PackageManager.INSTALL_INTERNAL;
                             flags &= ~PackageManager.INSTALL_EXTERNAL;
                         }
                     }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index a06a13b..b988920 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -78,6 +78,7 @@
     private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
     private static final int APP_INSTALL_DEVICE = PackageHelper.APP_INSTALL_INTERNAL;
     private static final int APP_INSTALL_SDCARD = PackageHelper.APP_INSTALL_EXTERNAL;
+    private boolean mOrigState;
 
     void failStr(String errMsg) {
         Log.w(TAG, "errMsg="+errMsg);
@@ -91,6 +92,21 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mOrigState = getMediaState();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Restore media state.
+        boolean newState = getMediaState();
+        if (newState != mOrigState) {
+            if (mOrigState) {
+                getMs().mountVolume(Environment.getExternalStorageDirectory().getPath());
+            } else {
+                getMs().unmountVolume(Environment.getExternalStorageDirectory().getPath(), true);
+            }
+        }
+        super.tearDown();
     }
 
     private class PackageInstallObserver extends IPackageInstallObserver.Stub {
@@ -254,21 +270,70 @@
         packageParser = null;
         return pkg;
     }
-    private boolean getInstallLoc(int flags, int expInstallLocation) {
+    private boolean checkSd(long pkgLen) {
+        String status = Environment.getExternalStorageState();
+        if (!status.equals(Environment.MEDIA_MOUNTED)) {
+            return false;
+        }
+        long sdSize = -1;
+        StatFs sdStats = new StatFs(
+                Environment.getExternalStorageDirectory().getPath());
+        sdSize = (long)sdStats.getAvailableBlocks() *
+                (long)sdStats.getBlockSize();
+        // TODO check for thesholds here
+        return pkgLen <= sdSize;
+        
+    }
+    private boolean checkInt(long pkgLen) {
+        StatFs intStats = new StatFs(Environment.getDataDirectory().getPath());
+        long intSize = (long)intStats.getBlockCount() *
+                (long)intStats.getBlockSize();
+        long iSize = (long)intStats.getAvailableBlocks() *
+                (long)intStats.getBlockSize();
+        // TODO check for thresholds here?
+        return pkgLen <= iSize;
+    }
+    private static final int INSTALL_LOC_INT = 1;
+    private static final int INSTALL_LOC_SD = 2;
+    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 false;
+            return INSTALL_LOC_INT;
         } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) {
-            return true;
+            return INSTALL_LOC_SD;
+        } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
+            return INSTALL_LOC_INT;
         }
         // Manifest option takes precedence next
         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
-            return true;
+            // TODO fitsonSd check
+            if (checkSd(pkgLen)) {
+               return INSTALL_LOC_SD;
+            }
+            if (checkInt(pkgLen)) {
+                return INSTALL_LOC_INT;
+            }
+            return INSTALL_LOC_ERR;
         }
         if (expInstallLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
-            return false;
+            if (checkInt(pkgLen)) {
+                return INSTALL_LOC_INT;
+            }
+            return INSTALL_LOC_ERR;
         }
-        // TODO Out of memory checks here.
+        if (expInstallLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
+            // Check for free memory internally
+            if (checkInt(pkgLen)) {
+                return INSTALL_LOC_INT;
+            }
+            // Check for free memory externally
+            if (checkSd(pkgLen)) {
+                return INSTALL_LOC_SD;
+            }
+            return INSTALL_LOC_ERR;
+        }
+        // Check for settings preference.
         boolean checkSd = false;
         int setLoc = 0;
         try {
@@ -284,46 +349,63 @@
                 failStr(e);
             }
             if (userPref == APP_INSTALL_DEVICE) {
-                checkSd = false;
+                if (checkInt(pkgLen)) {
+                    return INSTALL_LOC_INT;
+                }
+                return INSTALL_LOC_ERR;
             } else if (userPref == APP_INSTALL_SDCARD) {
-                checkSd = true;
+                if (checkSd(pkgLen)) {
+                    return INSTALL_LOC_SD;
+                }
+                return INSTALL_LOC_ERR;
             } else if (userPref == APP_INSTALL_AUTO) {
-                // Might be determined dynamically. TODO fix this
-                checkSd = false;
+                if (checkInt(pkgLen)) {
+                    return INSTALL_LOC_INT;
+                }
+                // Check for free memory externally
+                if (checkSd(pkgLen)) {
+                    return INSTALL_LOC_SD;
+                }
+                return INSTALL_LOC_ERR;
+                
             }
-        }
-        return checkSd;
+        } 
+        return INSTALL_LOC_ERR;
     }
     private void assertInstall(PackageParser.Package pkg, int flags, int expInstallLocation) {
         try {
             String pkgName = pkg.packageName;
-        ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
-        assertNotNull(info);
-        assertEquals(pkgName, info.packageName);
-        File dataDir = Environment.getDataDirectory();
-        String appInstallPath = new File(dataDir, "app").getPath();
-        String drmInstallPath = new File(dataDir, "app-private").getPath();
-        File srcDir = new File(info.sourceDir);
-        String srcPath = srcDir.getParent();
-        File publicSrcDir = new File(info.publicSourceDir);
-        String publicSrcPath = publicSrcDir.getParent();
+            ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
+            assertNotNull(info);
+            assertEquals(pkgName, info.packageName);
+            File dataDir = Environment.getDataDirectory();
+            String appInstallPath = new File(dataDir, "app").getPath();
+            String drmInstallPath = new File(dataDir, "app-private").getPath();
+            File srcDir = new File(info.sourceDir);
+            String srcPath = srcDir.getParent();
+            File publicSrcDir = new File(info.publicSourceDir);
+            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);
-        } else {
-            assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-            if (!getInstallLoc(flags, expInstallLocation)) {
-                assertEquals(srcPath, appInstallPath);
+            if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
+                assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                assertEquals(srcPath, drmInstallPath);
                 assertEquals(publicSrcPath, appInstallPath);
-                assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
             } else {
-                assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
-                assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
-                assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                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);
+                } else if (rLoc == INSTALL_LOC_SD){
+                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+                    assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                    assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                } else {
+                    // TODO handle error. Install should have failed.
+                }
             }
-        }
         } catch (NameNotFoundException e) {
             failStr("failed with exception : " + e);
         }
@@ -396,8 +478,6 @@
             } catch (Exception e) {
                 failStr(e);
             }
-            // Clean up the containers as well
-            clearSecureContainersForPkg(pkg.packageName);
         }
         InstallParams ip = null;
         try {
@@ -1047,19 +1127,6 @@
         }
     }
 
-    public void xxxtestClearAllSecureContainers() {
-        IMountService ms = getMs();
-        try {
-            String list[] = ms.getSecureContainerList();
-            if (list != null) {
-                for (String cid : list) {
-                    Log.i(TAG, "Destroying container " + cid);
-                    ms.destroySecureContainer(cid, false);
-                }
-            }
-        } catch (RemoteException e) {}
-    }
-
     class MoveReceiver extends GenericReceiver {
         String pkgName;
         final static int INVALID = -1;
@@ -1185,7 +1252,7 @@
     public void moveFromRawResource(int installFlags, int moveFlags,
             int expRetCode) {
         int origDefaultLoc = getInstallLoc();
-        setInstallLoc(PackageInfo.INSTALL_LOCATION_AUTO);
+        setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
         // Install first
         InstallParams ip = sampleInstallFromRawResource(installFlags, false);
         ApplicationInfo oldAppInfo = null;
@@ -1255,7 +1322,7 @@
             // Try to install and make sure an error code is returned.
             assertNull(installFromRawResource("install.apk", R.raw.install,
                     PackageManager.INSTALL_EXTERNAL, false,
-                    true, PackageManager.INSTALL_FAILED_CONTAINER_ERROR,
+                    true, PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE,
                     PackageInfo.INSTALL_LOCATION_AUTO));
         } finally {
             // Restore original media state
@@ -1292,6 +1359,509 @@
    }
 
    /*---------- Recommended install location tests ----*/
+   /* Precedence: FlagManifestExistingUser
+    * PrecedenceSuffixes:
+    * Flag : FlagI, FlagE, FlagF
+    * I - internal, E - external, F - forward locked, Flag suffix absent if not using any option.
+    * Manifest: ManifestI, ManifestE, ManifestA, Manifest suffix absent if not using any option.
+    * Existing: Existing suffix absent if not existing.
+    * User: UserI, UserE, UserA, User suffix absent if not existing. 
+    * 
+    */
+   /*
+    * Install an app on internal flash
+    */
+   public void testFlagI() {
+       sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, true);
+   }
+   /*
+    * Install an app on sdcard.
+    */
+   public void testFlagE() {
+       sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
+   }
+
+   /*
+    * Install an app on sdcard.
+    */
+   public void testFlagF() {
+       sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
+   }
+   /*
+    * Install an app with both internal and external flags set. should fail
+    */
+   public void testFlagIE() {
+       installFromRawResource("install.apk", R.raw.install,
+               PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_INTERNAL,
+               false,
+               true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+               PackageInfo.INSTALL_LOCATION_AUTO);
+   }
+
+   /*
+    * Install an app with both internal and external flags set. should fail
+    */
+   public void testFlagIF() {
+       sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK |
+               PackageManager.INSTALL_INTERNAL, true);
+   }
+   /*
+    * Install an app with both internal and external flags set. should fail
+    */
+   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);
+   }
+   /*
+    * Install an app with both internal and external flags set. should fail
+    */
+   public void testFlagIEF() {
+       installFromRawResource("install.apk", R.raw.install,
+               PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_INTERNAL |
+               PackageManager.INSTALL_EXTERNAL,
+               false,
+               true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+               PackageInfo.INSTALL_LOCATION_AUTO);
+   }
+   /*
+    * Install an app with both internal and manifest option set.
+    * should install on internal.
+    */
+   public void testFlagIManifestI() {
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               PackageManager.INSTALL_INTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   /*
+    * Install an app with both internal and manifest preference for
+    * preferExternal. Should install on internal.
+    */
+   public void testFlagIManifestE() {
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               PackageManager.INSTALL_INTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   /*
+    * Install an app with both internal and manifest preference for
+    * auto. should install internal.
+    */
+   public void testFlagIManifestA() {
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               PackageManager.INSTALL_INTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   /*
+    * Install an app with both external and manifest option set.
+    * should install externally.
+    */
+   public void testFlagEManifestI() {
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /*
+    * Install an app with both external and manifest preference for
+    * preferExternal. Should install externally.
+    */
+   public void testFlagEManifestE() {
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /*
+    * Install an app with both external and manifest preference for
+    * auto. should install on external media.
+    */
+   public void testFlagEManifestA() {
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /*
+    * Install an app with fwd locked flag set and install location set to
+    * internal. should install internally.
+    */
+   public void testFlagFManifestI() {
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /*
+    * Install an app with fwd locked flag set and install location set to
+    * preferExternal. should install internally.
+    */
+   public void testFlagFManifestE() {
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /*
+    * Install an app with fwd locked flag set and install location set to
+    * auto. should install internally.
+    */
+   public void testFlagFManifestA() {
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               PackageManager.INSTALL_EXTERNAL,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   /* The following test functions verify install location for existing apps.
+    * ie existing app can be installed internally or externally. If install
+    * flag is explicitly set it should override current location. If manifest location
+    * is set, that should over ride current location too. if not the existing install
+    * location should be honoured.
+    * testFlagI/E/F/ExistingI/E - 
+    */
+   public void testFlagIExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   public void testFlagIExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   public void testFlagEExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   public void testFlagEExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   public void testFlagFExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   public void testFlagFExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install,
+               rFlags,
+               true,
+               false, -1,
+               -1);
+   }
+   /*
+    * The following set of tests verify the installation of apps with
+    * install location attribute set to internalOnly, preferExternal and auto.
+    * The manifest option should dictate the install location.
+    * public void testManifestI/E/A
+    * TODO out of memory fall back behaviour.
+    */
+   public void testManifestI() {
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               0,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   public void testManifestE() {
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               0,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   public void testManifestA() {
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               0,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   /*
+    * The following set of tests verify the installation of apps
+    * with install location attribute set to internalOnly, preferExternal and auto
+    * for already existing apps. The manifest option should take precedence.
+    * TODO add out of memory fall back behaviour.
+    * testManifestI/E/AExistingI/E 
+    */
+   public void testManifestIExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   public void testManifestIExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_internal,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+   }
+   public void testManifestEExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   public void testManifestEExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+   }
+   public void testManifestAExistingI() {
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_AUTO);
+   }
+   public void testManifestAExistingE() {
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Replace now
+       installFromRawResource("install.apk", R.raw.install_loc_auto,
+               rFlags,
+               true,
+               false, -1,
+               PackageInfo.INSTALL_LOCATION_AUTO);
+   }
+   /*
+    * The following set of tests check install location for existing
+    * application based on user setting.
+    */
+   private void setExistingXUserX(int userSetting, int iFlags) {
+       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+       // First install.
+       installFromRawResource("install.apk", R.raw.install,
+               iFlags,
+               false,
+               false, -1,
+               -1);
+       // Watch out for this.
+       int iloc = PackageInfo.INSTALL_LOCATION_AUTO;
+       if ((iFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+           iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+       } else if ((iFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+           iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
+       }
+       int origSetting = getInstallLoc();
+       try {
+           // Set user setting
+           setInstallLoc(userSetting);
+           // Replace now
+           installFromRawResource("install.apk", R.raw.install,
+                   rFlags,
+                   true,
+                   false, -1,
+                   iloc);
+       } finally {
+           setInstallLoc(origSetting);
+       }
+   }
+   public void testExistingIUserI() {
+       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   public void testExistingIUserE() {
+       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   public void testExistingIUserA() {
+       int userSetting = PackageHelper.APP_INSTALL_AUTO;
+       int iFlags = PackageManager.INSTALL_INTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   public void testExistingEUserI() {
+       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   public void testExistingEUserE() {
+       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   public void testExistingEUserA() {
+       int userSetting = PackageHelper.APP_INSTALL_AUTO;
+       int iFlags = PackageManager.INSTALL_EXTERNAL;
+       setExistingXUserX(userSetting, iFlags);
+   }
+   /*
+    * The following set of tests verify that the user setting defines
+    * the install location.
+    * 
+    */
+   private void setUserX(int userSetting) {
+       int origSetting = getInstallLoc();
+       int iloc = PackageInfo.INSTALL_LOCATION_AUTO;
+       if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
+           iloc = PackageInfo.INSTALL_LOCATION_AUTO;
+       } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
+           iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
+       } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
+           iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+       }
+       try {
+           // Set user setting
+           setInstallLoc(userSetting);
+           // Replace now
+           installFromRawResource("install.apk", R.raw.install,
+                   0,
+                   true,
+                   false, -1,
+                   iloc);
+       } finally {
+           setInstallLoc(origSetting);
+       }
+   }
+   public void testUserI() {
+       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+       setUserX(userSetting);
+   }
+   public void testUserE() {
+       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+       setUserX(userSetting);
+   }
+   public void testUserA() {
+       int userSetting = PackageHelper.APP_INSTALL_AUTO;
+       setUserX(userSetting);
+   }
     /*
      * TODO's
      * check version numbers for upgrades