summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ApplicationContext.java72
-rw-r--r--core/java/android/content/pm/PackageManager.java94
-rw-r--r--test-runner/android/test/mock/MockPackageManager.java8
3 files changed, 97 insertions, 77 deletions
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index fe05393..6c65bd8 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -71,6 +71,7 @@ import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.DropBoxManager;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -80,6 +81,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.StatFs;
import android.os.Vibrator;
import android.os.FileUtils.FileStatus;
import android.telephony.TelephonyManager;
@@ -2537,6 +2539,76 @@ class ApplicationContext extends Context {
return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
+ // Constants related to app heuristics
+ // No-installation limit for internal flash: 10% or less space available
+ private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
+
+ // SD-to-internal app size threshold: currently set to 1 MB
+ private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
+
+ @Override
+ public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ // Initial implementation:
+ // 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%
+
+ if ((packageURI == null) || (appInfo == null)) {
+ return INSTALL_PARSE_FAILED_NOT_APK;
+ }
+
+ StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
+ StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
+
+ long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
+ (long)internalFlashStats.getBlockSize();
+ long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
+ (long)internalFlashStats.getBlockSize();
+ long availSDSize = (long)sdcardStats.getAvailableBlocks() *
+ (long)sdcardStats.getBlockSize();
+
+ double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
+
+ final String archiveFilePath = packageURI.getPath();
+ File apkFile = new File(archiveFilePath);
+ long pkgLen = apkFile.length();
+
+ // Consider application flags preferences as well...
+ boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
+
+ // These are not very precise measures, but I guess it is hard to estimate sizes
+ // before installing the package.
+ // As a shortcut, I am assuming that the package fits on NAND flash if the available
+ // space is three times that of the APK size. For SD, we only worry about the APK size.
+ // Since packages are downloaded into SD, this might not even be necessary.
+ boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
+ boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
+
+ // Does not fit, recommend no installation.
+ if (!fitsOnSD && !fitsOnInternalFlash) {
+ return INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+
+ if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
+ // recommend internal NAND likely
+ if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
+ // Low space on NAND (<10%) - install on SD
+ return INSTALL_ON_SDCARD;
+ }
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ if (fitsOnSD) {
+ // Recommend SD card
+ return INSTALL_ON_SDCARD;
+ } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
+ !(installOnlyOnSD)) {
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ return INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ }
+ }
+
private final ApplicationContext mContext;
private final IPackageManager mPM;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d10c8f8..1e45f17 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -261,6 +261,13 @@ public abstract class PackageManager {
public static final int INSTALL_ON_SDCARD = 0x00000008;
/**
+ * Convenience flag parameter to indicate that this package has to be installed
+ * on internal flash.
+ * @hide
+ */
+ public static final int INSTALL_ON_INTERNAL_FLASH = 0x00000000;
+
+ /**
* 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
@@ -605,89 +612,22 @@ public abstract class PackageManager {
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
- // No-installation limit for internal flash: 10% or less space available
- private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
-
- // SD-to-internal app size threshold: currently set to 1 MB
- private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
-
- private static final int INSTALL_ON_INTERNAL_FLASH = 0;
-
/**
* Determines best place to install an application: either SD or internal FLASH.
* Tweak the algorithm for best results.
- * @param tmpPackageFile APK file containing the application to install.
- * @return <code>PKG_INSTALL_INTERNAL</code> if it is best to install package on internal
- * storage, <code>PKG_INSTALL_ON_SD</code> if it is best to install package on SD card,
- * and <code>PKG_CANNOT_FIT</code> if insufficient space to safely install the app.
- * This response does not take into account the package's own flags.
+ * @param appInfo ApplicationInfo object og the package to install.
+ * Call utility method to obtain.
+ * @param packageURI URI identifying the package's APK file.
+ * @return <code>INSTALL_ON_INTERNAL_FLASH</code> if it is best to install package on internal
+ * storage, <code>INSTALL_ON_SDCARD</code> if it is best to install package on SD card,
+ * and <code>INSTALL_FAILED_INSUFFICIENT_STORAGE</code> if insufficient space to safely install
+ * the application. <code>INSTALL_PARSE_FAILED_NOT_APK</code> Is returned if any input
+ * parameter is <code>null</code>.
+ * This recommendation does take into account the package's own flags.
* @hide
*/
- public static int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
- // Initial implementation:
- // 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 5%
- // 0 = install on internal FLASH
- // 1 = install on SD card
- // (-1) = insufficient space - package cannot be installed.
-
- if ((packageURI == null) || (appInfo == null)) {
- return (-1);
- }
-
- StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
- StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
-
- long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
- (long)internalFlashStats.getBlockSize();
- long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
- (long)internalFlashStats.getBlockSize();
- long availSDSize = (long)sdcardStats.getAvailableBlocks() *
- (long)sdcardStats.getBlockSize();
+ public abstract int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI);
- double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
-
- final String archiveFilePath = packageURI.getPath();
- File apkFile = new File(archiveFilePath);
- long pkgLen = apkFile.length();
-
- // Consider application flags preferences as well...
- boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
-
- // These are not very precise measures, but I guess it is hard to estimate sizes
- // before installing the package.
- // As a shortcut, I am assuming that the package fits on NAND flash if the available
- // space is three times that of the APK size. For SD, we only worry about the APK size.
- // Since packages are downloaded into SD, this might not even be necessary.
- boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
- boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
-
- // Does not fit, recommend no installation.
- if (!fitsOnSD && !fitsOnInternalFlash) {
- return (-1);
- }
-
- if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
- // recommend internal NAND likely
- if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
- // Low space on NAND (<10%) - install on SD
- return INSTALL_ON_SDCARD;
- }
- return INSTALL_ON_INTERNAL_FLASH;
- } else {
- if (fitsOnSD) {
- // Recommend SD card
- return INSTALL_ON_SDCARD;
- } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
- !(installOnlyOnSD)) {
- return INSTALL_ON_INTERNAL_FLASH;
- } else {
- return (-1);
- }
- }
- }
-
/**
* Retrieve overall information about an application package that is
* installed on the system.
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index 2f313af..cbe0253 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -438,4 +438,12 @@ public class MockPackageManager extends PackageManager {
public boolean isSafeMode() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ throw new UnsupportedOperationException();
+ }
}