diff options
4 files changed, 102 insertions, 66 deletions
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 @@ public class PackageInfo implements Parcelable { * 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 @@ public class PackageParser { 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 @@ public class PackageParser { + 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 @@ public class PackageParser { 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 @@ class PackageManagerService extends IPackageManager.Stub { } 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { * 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 class PackageManagerTests extends AndroidTestCase { 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 @@ public class PackageManagerTests extends AndroidTestCase { 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[] { |