Some framework fixes for apps on sd
change hard coded path in installd
fix tests
Work around for renaming containers.
Do forced unmount when destroying containers.
Force a gc in default container service to release handle to parsed package
and thus avoid getting killed by vold
Some cosmetic changes to PackageManager api.
Unit tests for renaming container for MountService
Remove internal size limit on app to be installed.
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 92ae310..66f3676 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -68,7 +68,7 @@
 /* other handy constants */
 
 #define PROTECTED_DIR_PREFIX  "/data/app-private/"
-#define SDCARD_DIR_PREFIX  "/asec/"
+#define SDCARD_DIR_PREFIX  "/mnt/asec/"
 
 #define DALVIK_CACHE_PREFIX   "/data/dalvik-cache/"
 #define DALVIK_CACHE_POSTFIX  "/classes.dex"
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index f793a00..399a87d 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -309,7 +309,7 @@
      * MountService uses this to call into the package manager to update
      * status of sdcard.
      */
-    void updateExternalMediaStatus(boolean mounted);
+    boolean updateExternalMediaStatus(boolean mounted);
 
     String nextPackageToClean(String lastPackage);
 
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index bc7dbf4..c5db83f 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -36,7 +36,7 @@
     public static final int RECOMMEND_INSTALL_EXTERNAL = 2;
     public static final int RECOMMEND_FAILED_INSUFFICIENT_STORAGE = -1;
     public static final int RECOMMEND_FAILED_INVALID_APK = -2;
-    private static final boolean DEBUG_SD_INSTALL = true;
+    private static final boolean localLOGV = true;
     private static final String TAG = "PackageHelper";
 
     public static IMountService getMountService() {
@@ -58,7 +58,7 @@
         if ((len - (mbLen * 1024 * 1024)) > 0) {
             mbLen++;
         }
-        if (DEBUG_SD_INSTALL) Log.i(TAG, "Size of resource " + mbLen);
+        if (localLOGV) Log.i(TAG, "Size of resource " + mbLen);
 
         try {
             int rc = mountService.createSecureContainer(
@@ -68,7 +68,7 @@
                 return null;
             }
             String cachePath = mountService.getSecureContainerPath(cid);
-            if (DEBUG_SD_INSTALL) Log.i(TAG, "Created secure container " + cid +
+            if (localLOGV) Log.i(TAG, "Created secure container " + cid +
                     " at " + cachePath);
                 return cachePath;
         } catch (RemoteException e) {
@@ -93,7 +93,7 @@
 
    public static boolean unMountSdDir(String cid) {
     try {
-        int rc = getMountService().unmountSecureContainer(cid, false);
+        int rc = getMountService().unmountSecureContainer(cid, true);
         if (rc != StorageResultCode.OperationSucceeded) {
             Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc);
             return false;
@@ -148,7 +148,8 @@
 
     public static boolean destroySdDir(String cid) {
         try {
-            int rc = getMountService().destroySecureContainer(cid, false);
+            if (localLOGV) Log.i(TAG, "Forcibly destroying container " + cid);
+            int rc = getMountService().destroySecureContainer(cid, true);
             if (rc != StorageResultCode.OperationSucceeded) {
                 Log.i(TAG, "Failed to destroy container " + cid);
                 return false;
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 95ab684..a79f0cd 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -39,7 +39,7 @@
  */
 public class DefaultContainerService extends IntentService {
     private static final String TAG = "DefContainer";
-    private static final boolean localLOGV = false;
+    private static final boolean localLOGV = true;
 
     private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
         /*
@@ -211,6 +211,8 @@
                 if (PackageHelper.isContainerMounted(newCid)) {
                     if (localLOGV) Log.i(TAG, "Unmounting " + newCid +
                             " at path " + newCachePath + " after " + errMsg);
+                    // Force a gc to avoid being killed.
+                    Runtime.getRuntime().gc();
                     PackageHelper.unMountSdDir(newCid);
                 } else {
                     if (localLOGV) Log.i(TAG, "Container " + newCid + " not mounted");
@@ -328,8 +330,8 @@
         boolean auto = true;
         // To make final copy
         long reqInstallSize = pkgLen;
-        // For dex files
-        long reqInternalSize = 1 * 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) < availInternalFlashSize);
         boolean fitsOnSd = (reqInstallSize < availSDSize) && intThresholdOk &&
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4a7fc9c..9e0d623 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4858,42 +4858,67 @@
                 String oldCodePath) {
             String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
             String newCachePath = null;
-            final int RENAME_FAILED = 1;
-            final int MOUNT_FAILED = 2;
-            final int PASS = 4;
-            int errCode = RENAME_FAILED;
-            String errMsg = "RENAME_FAILED";
-            boolean mounted = PackageHelper.isContainerMounted(cid);
-            if (mounted) {
-                // Unmount the container
-                if (!PackageHelper.unMountSdDir(cid)) {
-                    Log.i(TAG, "Failed to unmount " + cid + " before renaming");
+            boolean enableRename = false;
+            if (enableRename) {
+                if (PackageHelper.isContainerMounted(cid)) {
+                    // Unmount the container
+                    if (!PackageHelper.unMountSdDir(cid)) {
+                        Log.i(TAG, "Failed to unmount " + cid + " before renaming");
+                        return false;
+                    }
+                }
+                if (!PackageHelper.renameSdDir(cid, newCacheId)) {
+                    Log.e(TAG, "Failed to rename " + cid + " to " + newCacheId);
                     return false;
                 }
-                mounted = false;
-            }
-            if (PackageHelper.renameSdDir(cid, newCacheId)) {
-                errCode = MOUNT_FAILED;
-                errMsg = "MOUNT_FAILED";
-                if ((newCachePath = PackageHelper.mountSdDir(newCacheId,
-                        getEncryptKey(), Process.SYSTEM_UID)) != null) {
-                    errCode = PASS;
-                    errMsg = "PASS";
+                if (!PackageHelper.isContainerMounted(newCacheId)) {
+                    Log.w(TAG, "Mounting container " + newCacheId);
+                    newCachePath = PackageHelper.mountSdDir(newCacheId,
+                            getEncryptKey(), Process.SYSTEM_UID);
+                } else {
+                    newCachePath = PackageHelper.getSdDir(newCacheId);
                 }
-            }
-            if (errCode != PASS) {
-                Log.i(TAG, "Failed to rename " + cid + " to " + newCacheId +
-                        " at path: " + cachePath + " to new path: " + newCachePath +
-                        "err = " + errMsg);
+                if (newCachePath == null) {
+                    Log.w(TAG, "Failed to get cache path for  " + newCacheId);
+                    return false;
+                }
                 // Mount old container?
-                return false;
+                Log.i(TAG, "Succesfully renamed " + cid +
+                        " at path: " + cachePath + " to " + newCacheId +
+                        " at new path: " + newCachePath);
+                cid = newCacheId;
+                cachePath = newCachePath;
+                return true;
             } else {
-                Log.i(TAG, "Succesfully renamed " + cid + " to " + newCacheId +
-                        " at path: " + cachePath + " to new path: " + newCachePath);
+                // STOPSHIP work around for rename
+                Log.i(TAG, "Copying instead of renaming");
+                File srcFile = new File(getCodePath());
+                // Create new container
+                newCachePath = PackageHelper.createSdDir(srcFile, newCacheId,
+                        getEncryptKey(), Process.SYSTEM_UID);
+                Log.i(TAG, "Created rename container " + newCacheId);
+                File destFile = new File(newCachePath + "/" + RES_FILE_NAME);
+                if (!FileUtils.copyFile(srcFile, destFile)) {
+                    Log.e(TAG, "Failed to copy " + srcFile + " to " + destFile);
+                    return false;
+                }
+                Log.i(TAG, "Successfully copied resource to " + newCachePath);
+                if (!PackageHelper.finalizeSdDir(newCacheId)) {
+                    Log.e(TAG, "Failed to finalize " + newCacheId);
+                    PackageHelper.destroySdDir(newCacheId);
+                    return false;
+                }
+                Log.i(TAG, "Finalized " + newCacheId);
+                Runtime.getRuntime().gc();
+                // Unmount first
+                PackageHelper.unMountSdDir(cid);
+                // Delete old container
+                PackageHelper.destroySdDir(cid);
+                // Dont have to mount. Already mounted.
+                cid = newCacheId;
+                cachePath = newCachePath;
+                return true;
             }
-            cid = newCacheId;
-            cachePath = newCachePath;
-            return true;
         }
 
         int doPostInstall(int status) {
@@ -5403,6 +5428,7 @@
             res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
             return;
         }
+
         if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
             res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
             return;
@@ -8809,7 +8835,7 @@
     }
 
    static String getTempContainerId() {
-       String prefix = "smdl1tmp";
+       String prefix = "smdl2tmp";
        int tmpIdx = 1;
        String list[] = PackageHelper.getSecureContainerList();
        if (list != null) {
@@ -8851,30 +8877,45 @@
        return prefix + tmpIdx;
    }
 
-   public void updateExternalMediaStatus(final boolean mediaStatus) {
+   public boolean updateExternalMediaStatus(final boolean mediaStatus) {
        synchronized (mPackages) {
            if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
                    mediaStatus+", mMediaMounted=" + mMediaMounted);
            if (mediaStatus == mMediaMounted) {
-               return;
+               return false;
            }
            mMediaMounted = mediaStatus;
+           final HashMap<SdInstallArgs, String> processCids =
+                   new HashMap<SdInstallArgs, String>();
+           final int[] uidArr = getExternalMediaPackages(mediaStatus, processCids);
+           if (processCids.size() == 0) {
+               return false;
+           }
             // Queue up an async operation since the package installation may take a little while.
            mHandler.post(new Runnable() {
                public void run() {
                    mHandler.removeCallbacks(this);
-                   updateExternalMediaStatusInner(mediaStatus);
+                   if (mediaStatus) {
+                       if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
+                       loadMediaPackages(processCids, uidArr);
+                       startCleaningPackages();
+                   } else {
+                       if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
+                       unloadMediaPackages(processCids, uidArr);
+                   }
                }
            });
+           return true;
        }
    }
 
-   void updateExternalMediaStatusInner(boolean mediaStatus) {
+    private int[] getExternalMediaPackages(boolean mediaStatus,
+            Map<SdInstallArgs, String> processCids) {
        final String list[] = PackageHelper.getSecureContainerList();
        if (list == null || list.length == 0) {
-           return;
+           return null;
        }
-       HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
+
        int uidList[] = new int[list.length];
        int num = 0;
        synchronized (mPackages) {
@@ -8916,14 +8957,7 @@
                }
            }
        }
-       if (mediaStatus) {
-           if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
-           loadMediaPackages(processCids, uidArr);
-           startCleaningPackages();
-       } else {
-           if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
-           unloadMediaPackages(processCids, uidArr);
-       }
+       return uidArr;
    }
 
    private void sendResourcesChangedBroadcast(boolean mediaStatus,
@@ -8943,7 +8977,7 @@
        }
    }
 
-   void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+   private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
        ArrayList<String> pkgList = new ArrayList<String>();
        Set<SdInstallArgs> keys = processCids.keySet();
        for (SdInstallArgs args : keys) {
@@ -8993,7 +9027,7 @@
        }
    }
 
-   void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+   private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
        if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
        ArrayList<String> pkgList = new ArrayList<String>();
        ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
index d5d23266..e85254d 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java
@@ -132,6 +132,14 @@
         return ms.destroySecureContainer(fullId, force);
     }
 
+    private boolean isContainerMounted(String localId) throws RemoteException {
+        Assert.assertTrue(isMediaMounted());
+        String fullId = "com.android.unittests.AsecTests." + localId;
+
+        IMountService ms = getMs();
+        return ms.isSecureContainerMounted(fullId);
+    }
+
     private IMountService getMs() {
         IBinder service = ServiceManager.getService("mount");
         if (service != null) {
@@ -329,4 +337,25 @@
             failStr(e);
         }
     }
+
+    public void testIsContainerMountedAfterRename() {
+        try {
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    createContainer("testRenameContainer.1", 4, "none"));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    unmountContainer("testRenameContainer.1", false));
+
+            Assert.assertEquals(StorageResultCode.OperationSucceeded,
+                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+
+            Assert.assertEquals(false, containerExists("testRenameContainer.1"));
+            Assert.assertEquals(true, containerExists("testRenameContainer.2"));
+            // Check if isContainerMounted returns valid value
+            Assert.assertEquals(true, isContainerMounted("testRenameContainer.2"));
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 9c5c44d..d161a88 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -57,17 +57,25 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.storage.IMountService;
+import android.os.storage.IMountServiceListener;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
 import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
     public static final String TAG="PackageManagerTests";
     public final long MAX_WAIT_TIME=120*1000;
     public final long WAIT_TIME_INCR=20*1000;
+    private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";
+    private static final int APP_INSTALL_AUTO = 0;
+    private static final int APP_INSTALL_DEVICE = 1;
+    private static final int APP_INSTALL_SDCARD = 2;
 
     void failStr(String errMsg) {
         Log.w(TAG, "errMsg="+errMsg);
@@ -244,9 +252,46 @@
         packageParser = null;
         return pkg;
     }
-
-    private void assertInstall(String pkgName, int flags) {
+    private boolean getInstallLoc(int flags, int expInstallLocation) {
+        // Flags explicitly over ride everything else.
+        if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ) {
+            return false;
+        } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) {
+            return true;
+        }
+        // Manifest option takes precedence next
+        if (expInstallLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
+            return true;
+        }
+        // TODO Out of memory checks here.
+        boolean checkSd = false;
+        int setLoc = 0;
         try {
+            setLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION);
+        } catch (SettingNotFoundException e) {
+            failStr(e);
+        }
+        if (setLoc == 1) {
+            int userPref = APP_INSTALL_AUTO;
+            try {
+                userPref = Settings.System.getInt(mContext.getContentResolver(), Settings.System.DEFAULT_INSTALL_LOCATION);
+            } catch (SettingNotFoundException e) {
+                failStr(e);
+            }
+            if (userPref == APP_INSTALL_DEVICE) {
+                checkSd = false;
+            } else if (userPref == APP_INSTALL_SDCARD) {
+                checkSd = true;
+            } else if (userPref == APP_INSTALL_AUTO) {
+                // Might be determined dynamically. TODO fix this
+                checkSd = false;
+            }
+        }
+        return checkSd;
+    }
+    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);
@@ -264,15 +309,14 @@
             assertEquals(publicSrcPath, appInstallPath);
         } else {
             assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-            if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-                assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
-                // Hardcoded for now
-                assertTrue(srcPath.startsWith("/asec"));
-                assertTrue(publicSrcPath.startsWith("/asec"));
-            } else {
+            if (!getInstallLoc(flags, expInstallLocation)) {
                 assertEquals(srcPath, appInstallPath);
                 assertEquals(publicSrcPath, appInstallPath);
                 assertFalse((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+            } else {
+                assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+                assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
             }
         }
         } catch (NameNotFoundException e) {
@@ -300,7 +344,7 @@
 
     private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) {
         return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
-                false, -1);
+                false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
     public void clearSecureContainersForPkg(String pkgName) {
@@ -327,7 +371,8 @@
      * PackageManager api to install it.
      */
     private InstallParams installFromRawResource(String outFileName,
-            int rawResId, int flags, boolean cleanUp, boolean fail, int result) {
+            int rawResId, int flags, boolean cleanUp, boolean fail, int result,
+            int expInstallLocation) {
         File filesDir = mContext.getFilesDir();
         File outFile = new File(filesDir, outFileName);
         Uri packageURI = getInstallablePackage(rawResId, outFile);
@@ -337,9 +382,7 @@
         // Make sure the package doesn't exist
         getPm().deletePackage(pkg.packageName, null, 0);
         // Clean up the containers as well
-        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-            clearSecureContainersForPkg(pkg.packageName);
-        }
+        clearSecureContainersForPkg(pkg.packageName);
         try {
             try {
                 if (fail) {
@@ -351,7 +394,7 @@
                     assertTrue(invokeInstallPackage(packageURI, flags,
                             pkg.packageName, receiver));
                     // Verify installed information
-                    assertInstall(pkg.packageName, flags);
+                    assertInstall(pkg, flags, expInstallLocation);
                     ip = new InstallParams(pkg, outFileName, packageURI);
                 }
             } catch (Exception e) {
@@ -443,6 +486,7 @@
     public void replaceFromRawResource(int flags) {
         InstallParams ip = sampleInstallFromRawResource(flags, false);
         boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0);
+        Log.i(TAG, "replace=" + replace);
         GenericReceiver receiver;
         if (replace) {
             receiver = new ReplaceReceiver(ip.pkg.packageName);
@@ -455,7 +499,7 @@
                 assertEquals(invokeInstallPackage(ip.packageURI, flags,
                         ip.pkg.packageName, receiver), replace);
                 if (replace) {
-                    assertInstall(ip.pkg.packageName, flags);
+                    assertInstall(ip.pkg, flags, ip.pkg.installLocation);
                 }
             } catch (Exception e) {
                 failStr("Failed with exception : " + e);
@@ -738,51 +782,73 @@
         }
     }
 
+    class StorageListener extends StorageEventListener {
+        String oldState;
+        String newState;
+        String path;
+        private boolean doneFlag = false;
+        @Override
+        public void onStorageStateChanged(String path, String oldState, String newState) {
+            if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState);
+            synchronized (this) {
+                this.oldState = oldState;
+                this.newState = newState;
+                this.path = path;
+                doneFlag = true;
+                notifyAll();
+            }
+        }
+
+        public boolean isDone() {
+            return doneFlag;
+        }
+    }
+
     private boolean unmountMedia() {
         if (!getMediaState()) {
             return true;
         }
+        String path = Environment.getExternalStorageDirectory().toString();
+        StorageListener observer = new StorageListener();
+        StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+        sm.registerListener(observer);
         try {
-        String mPath = Environment.getExternalStorageDirectory().toString();
-        int ret = getMs().unmountVolume(mPath, false);
-        return ret == StorageResultCode.OperationSucceeded;
-        } catch (RemoteException e) {
-            return true;
+            // Wait on observer
+            synchronized(observer) {
+                getMs().unmountVolume(path, false);
+                long waitTime = 0;
+                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    observer.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if(!observer.isDone()) {
+                    throw new Exception("Timed out waiting for packageInstalled callback");
+                }
+                return true;
+            }
+        } catch (Exception e) {
+            return false;
+        } finally {
+            sm.unregisterListener(observer);
         }
     }
 
-    /*
-     * Install package on sdcard. Unmount and then mount the media.
-     * (Use PackageManagerService private api for now)
-     * Make sure the installed package is available.
-     * STOPSHIP will uncomment when MountService api's to mount/unmount
-     * are made asynchronous.
-     */
-    public void xxxtestMountSdNormalInternal() {
-        assertTrue(mountFromRawResource());
-    }
-
     private boolean mountFromRawResource() {
         // Install pkg on sdcard
-        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL |
-                PackageManager.INSTALL_REPLACE_EXISTING, false);
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, false);
         if (localLOGV) Log.i(TAG, "Installed pkg on sdcard");
         boolean origState = getMediaState();
+        boolean registeredReceiver = false;
         SdMountReceiver receiver = new SdMountReceiver(new String[]{ip.pkg.packageName});
         try {
             if (localLOGV) Log.i(TAG, "Unmounting media");
             // Unmount media
             assertTrue(unmountMedia());
             if (localLOGV) Log.i(TAG, "Unmounted media");
-            try {
-                if (localLOGV) Log.i(TAG, "Sleeping for 10 second");
-                Thread.sleep(10*1000);
-            } catch (InterruptedException e) {
-                failStr(e);
-            }
             // Register receiver here
             PackageManager pm = getPm();
             mContext.registerReceiver(receiver, receiver.filter);
+            registeredReceiver = true;
 
             // Wait on receiver
             synchronized (receiver) {
@@ -807,7 +873,7 @@
             failStr(e);
             return false;
         } finally {
-            mContext.unregisterReceiver(receiver);
+            if (registeredReceiver) mContext.unregisterReceiver(receiver);
             // Restore original media state
             if (origState) {
                 mountMedia();
@@ -819,6 +885,17 @@
         }
     }
 
+    /*
+     * Install package on sdcard. Unmount and then mount the media.
+     * (Use PackageManagerService private api for now)
+     * Make sure the installed package is available.
+     * STOPSHIP will uncomment when MountService api's to mount/unmount
+     * are made asynchronous.
+     */
+    public void xxxtestMountSdNormalInternal() {
+        assertTrue(mountFromRawResource());
+    }
+
     void cleanUpInstall(InstallParams ip) {
         if (ip == null) {
             return;
@@ -834,28 +911,29 @@
 
     public void testManifestInstallLocationInternal() {
         installFromRawResource("install.apk", R.raw.install_loc_internal,
-                0, true, false, -1);
+                0, true, false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
     }
 
     public void testManifestInstallLocationSdcard() {
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-                0, true, false, -1);
+                0, true, false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
     }
 
     public void testManifestInstallLocationAuto() {
         installFromRawResource("install.apk", R.raw.install_loc_auto,
-                0, true, false, -1);
+                0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
     public void testManifestInstallLocationUnspecified() {
         installFromRawResource("install.apk", R.raw.install_loc_unspecified,
-                0, true, false, -1);
+                0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
     public void testManifestInstallLocationFwdLockedSdcard() {
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
                 PackageManager.INSTALL_FORWARD_LOCK, true, true,
-                PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION);
+                PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                PackageInfo.INSTALL_LOCATION_AUTO);
     }
 
     public void xxxtestClearAllSecureContainers() {