Switch default install location to unspecified.
Add a new install location unspecified for backward compatibility.
There is not much difference between policies auto and unspecified.
But we dont have to make any code changes in PackageParser based
on our preference for install location.
Add tests

Change-Id: I563238133261d911d08fbc66344687b7dfc870b1
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index e9a9f31..af327c3 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -153,6 +153,12 @@
      * the {@link android.R.attr#installLocation} attribute.
      * @hide
      */
+    public static final int INSTALL_LOCATION_UNSPECIFIED = -1;
+    /**
+     * Constant corresponding to <code>auto</code> in
+     * the {@link android.R.attr#installLocation} attribute.
+     * @hide
+     */
     public static final int INSTALL_LOCATION_AUTO = 0;
     /**
      * Constant corresponding to <code>internalOnly</code> in
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c33f305..821d19c 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -96,7 +96,8 @@
     private static final Object mSync = new Object();
     private static WeakReference<byte[]> mReadBuffer;
 
-    private static boolean sCompatibilityModeEnabled = true; 
+    private static boolean sCompatibilityModeEnabled = true;
+    private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
 
     static class ParsePackageItemArgs {
         final Package owner;
@@ -707,12 +708,12 @@
                 + pkgName + "\": " + nameError;
             return null;
         }
-        int installLocation = PackageInfo.INSTALL_LOCATION_AUTO;
+        int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
         for (int i = 0; i < attrs.getAttributeCount(); i++) {
             String attr = attrs.getAttributeName(i);
             if (attr.equals("installLocation")) {
                 installLocation = attrs.getAttributeIntValue(i,
-                        PackageInfo.INSTALL_LOCATION_AUTO);
+                        PARSE_DEFAULT_INSTALL_LOCATION);
                 break;
             }
         }
@@ -778,7 +779,7 @@
 
         pkg.installLocation = sa.getInteger(
                 com.android.internal.R.styleable.AndroidManifest_installLocation,
-                PackageInfo.INSTALL_LOCATION_AUTO);
+                PARSE_DEFAULT_INSTALL_LOCATION);
 
         // Resource boolean are -1, so 1 means we don't know the value.
         int supportsSmallScreens = 1;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 87a744e..f854067 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4701,23 +4701,22 @@
                             }
                             return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                         } else {
-                            // When replacing apps make sure we honour
-                            // the existing app location if not overwritten by other options
-                            boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
                             if (onSd) {
                                 // Install flag overrides everything.
                                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
                             }
-                            // If current upgrade does not specify install location.
+                            // If current upgrade specifies particular preference
                             if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
                                 // Application explicitly specified internal.
                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                             } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
                                 // App explictly prefers external. Let policy decide
-                            } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
+                            } else {
                                 // Prefer previous location
-                                return prevOnSd ? PackageHelper.RECOMMEND_INSTALL_EXTERNAL:
-                                    PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+                                if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+                                    return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
+                                }
+                                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                             }
                         }
                     } else {
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 009c0f2..b581192 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -86,8 +86,7 @@
         fail(errMsg);
     }
     void failStr(Exception e) {
-        Log.w(TAG, "e.getMessage="+e.getMessage());
-        Log.w(TAG, "e="+e);
+        failStr(e.getMessage());
     }
 
     @Override
@@ -297,6 +296,17 @@
     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 checkDefaultPolicy(long pkgLen) {
+        // 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;
+    }
     private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) {
         // Flags explicitly over ride everything else.
         if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ) {
@@ -324,15 +334,7 @@
             return INSTALL_LOC_ERR;
         }
         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;
+            return checkDefaultPolicy(pkgLen);
         }
         // Check for settings preference.
         boolean checkSd = false;
@@ -359,19 +361,9 @@
                     return INSTALL_LOC_SD;
                 }
                 return INSTALL_LOC_ERR;
-            } else if (userPref == APP_INSTALL_AUTO) {
-                if (checkInt(pkgLen)) {
-                    return INSTALL_LOC_INT;
-                }
-                // Check for free memory externally
-                if (checkSd(pkgLen)) {
-                    return INSTALL_LOC_SD;
-                }
-                return INSTALL_LOC_ERR;
-                
             }
-        } 
-        return INSTALL_LOC_ERR;
+        }
+        return checkDefaultPolicy(pkgLen);
     }
     
     private void assertInstall(PackageParser.Package pkg, int flags, int expInstallLocation) {
@@ -434,7 +426,7 @@
 
     private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) {
         return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
-                false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+                false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     static final String PERM_PACKAGE = "package";
@@ -1114,7 +1106,7 @@
 
     public void testManifestInstallLocationUnspecified() {
         installFromRawResource("install.apk", R.raw.install_loc_unspecified,
-                0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+                0, true, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     public void testManifestInstallLocationFwdLockedFlagSdcard() {
@@ -1122,7 +1114,7 @@
                 PackageManager.INSTALL_FORWARD_LOCK |
                 PackageManager.INSTALL_EXTERNAL, true, true,
                 PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
-                PackageInfo.INSTALL_LOCATION_AUTO);
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     public void testManifestInstallLocationFwdLockedSdcard() {
@@ -1178,12 +1170,12 @@
 
     public void testManifestInstallLocationReplaceInternalSdcard() {
         int iFlags = 0;
-        int iApk = R.raw.install_loc_unspecified;
+        int iApk = R.raw.install_loc_internal;
         int rFlags = 0;
         int rApk = R.raw.install_loc_sdcard;
         InstallParams ip = installFromRawResource("install.apk", iApk,
                 iFlags, false,
-                false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+                false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
         GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
         int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
         try {
@@ -1855,21 +1847,28 @@
     * The following set of tests check install location for existing
     * application based on user setting.
     */
-   private void setExistingXUserX(int userSetting, int iFlags) {
+   private int getExpectedInstallLocation(int userSetting) {
+       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+       boolean enable = getUserSettingSetInstallLocation();
+       if (enable) {
+           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;
+           }
+       }
+       return iloc;
+   }
+   private void setExistingXUserX(int userSetting, int iFlags, int iloc) {
        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;
-       }
+               PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
        int origSetting = getInstallLoc();
        try {
            // Set user setting
@@ -1887,49 +1886,56 @@
    public void testExistingIUserI() {
        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
        int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
    }
    public void testExistingIUserE() {
        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
        int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
    }
    public void testExistingIUserA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
        int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
    }
    public void testExistingEUserI() {
        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
        int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
    }
    public void testExistingEUserE() {
        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
        int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
    }
    public void testExistingEUserA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
        int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags);
+       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
    }
    /*
     * 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;
-       }
+   private boolean getUserSettingSetInstallLocation() {
        try {
+           return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
+           
+       } catch (SettingNotFoundException e1) {
+       }
+       return false;
+   }
+
+   private void setUserSettingSetInstallLocation(boolean value) {
+       Settings.System.putInt(mContext.getContentResolver(),
+               Settings.System.SET_INSTALL_LOCATION, value ? 1 : 0);
+   }
+   private void setUserX(boolean enable, int userSetting, int iloc) {
+       boolean origUserSetting = getUserSettingSetInstallLocation();
+       int origSetting = getInstallLoc();
+       try {
+           setUserSettingSetInstallLocation(enable);
            // Set user setting
            setInstallLoc(userSetting);
            // Replace now
@@ -1939,20 +1945,44 @@
                    false, -1,
                    iloc);
        } finally {
+           // Restore original setting
+           setUserSettingSetInstallLocation(origUserSetting);
            setInstallLoc(origSetting);
        }
    }
    public void testUserI() {
        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
-       setUserX(userSetting);
+       int iloc = getExpectedInstallLocation(userSetting);
+       setUserX(true, userSetting, iloc);
    }
    public void testUserE() {
        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
-       setUserX(userSetting);
+       int iloc = getExpectedInstallLocation(userSetting);
+       setUserX(true, userSetting, iloc);
    }
    public void testUserA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
-       setUserX(userSetting);
+       int iloc = getExpectedInstallLocation(userSetting);
+       setUserX(true, userSetting, iloc);
+   }
+   /*
+    * The following set of tests turn on/off the basic
+    * user setting for turning on install location.
+    */
+   public void testUserPrefOffUserI() {
+       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+       setUserX(false, userSetting, iloc);
+   }
+   public void testUserPrefOffUserE() {
+       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+       setUserX(false, userSetting, iloc);
+   }
+   public void testUserPrefOffA() {
+       int userSetting = PackageHelper.APP_INSTALL_AUTO;
+       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+       setUserX(false, userSetting, iloc);
    }
    
     static final String BASE_PERMISSIONS_DEFINED[] = new String[] {