summaryrefslogtreecommitdiffstats
path: root/core/java/android/content/pm
diff options
context:
space:
mode:
authorOscar Montemayor <oam@google.com>2010-01-28 12:01:44 -0800
committerOscar Montemayor <oam@google.com>2010-01-28 21:03:16 -0800
commit1228d0a1dddb8c03474ee3823499936a8b1d850c (patch)
treeeb6510dd8762d4a13845eb9ec56a8dec8ee0486c /core/java/android/content/pm
parent4d3cef348b4350abd9d50230376ff8b1d2ac4654 (diff)
downloadframeworks_base-1228d0a1dddb8c03474ee3823499936a8b1d850c.zip
frameworks_base-1228d0a1dddb8c03474ee3823499936a8b1d850c.tar.gz
frameworks_base-1228d0a1dddb8c03474ee3823499936a8b1d850c.tar.bz2
Apps on SD card project.
This class implements heuristics to determine best app install location, without looking at the package flags (pre-parsing stage).
Diffstat (limited to 'core/java/android/content/pm')
-rw-r--r--core/java/android/content/pm/PackageManager.java85
1 files changed, 85 insertions, 0 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bc59c94..d10c8f8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -27,6 +27,8 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Environment;
+import android.os.StatFs;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -602,6 +604,89 @@ 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.
+ * @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();
+
+ 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