Merge "StorageNotification: Move notification / usb storage activity into StatusBarPolicy"
diff --git a/api/current.xml b/api/current.xml
index 31ab3ce..7169d0d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4585,6 +4585,17 @@
visibility="public"
>
</field>
+<field name="installLocation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843448"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="interpolator"
type="int"
transient="false"
@@ -66274,6 +66285,10 @@
</parameter>
<parameter name="format" type="int">
</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
<parameter name="strides" type="int[]">
</parameter>
</constructor>
@@ -66287,17 +66302,24 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="width" type="int">
-</parameter>
-<parameter name="height" type="int">
-</parameter>
-<parameter name="offsets" type="int[]">
+<parameter name="rectangle" type="android.graphics.Rect">
</parameter>
<parameter name="quality" type="int">
</parameter>
<parameter name="stream" type="java.io.OutputStream">
</parameter>
</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getStrides"
return="int[]"
abstract="false"
@@ -66309,6 +66331,17 @@
visibility="public"
>
</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getYuvData"
return="byte[]"
abstract="false"
@@ -66331,25 +66364,6 @@
visibility="public"
>
</method>
-<method name="validate"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="format" type="int">
-</parameter>
-<parameter name="width" type="int">
-</parameter>
-<parameter name="height" type="int">
-</parameter>
-<parameter name="offsets" type="int[]">
-</parameter>
-</method>
</class>
</package>
<package name="android.graphics.drawable"
@@ -72580,7 +72594,7 @@
type="float"
transient="false"
volatile="false"
- value="0.0010f"
+ value="0.001f"
static="true"
final="true"
deprecated="not deprecated"
diff --git a/common/java/com/android/common/Search.java b/common/java/com/android/common/Search.java
new file mode 100644
index 0000000..55fa6f5
--- /dev/null
+++ b/common/java/com/android/common/Search.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.common;
+
+/**
+ * Utilities for search implementations.
+ *
+ * @see android.app.SearchManager
+ */
+public class Search {
+
+ /**
+ * Key for the source identifier set by the application that launched a search intent.
+ * The identifier is search-source specific string. It can be used
+ * by the search provider to keep statistics of where searches are started from.
+ *
+ * The source identifier is stored in the {@link android.app.SearchManager#APP_DATA}
+ * Bundle in {@link android.content.Intent#ACTION_SEARCH} and
+ * {@link android.content.Intent#ACTION_WEB_SEARCH} intents.
+ */
+ public final static String SOURCE = "source";
+
+ private Search() { } // don't instantiate
+}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9b9cbd5..0a18fe5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -52,6 +52,7 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.PackageParser.Package;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -85,6 +86,7 @@
import android.os.Vibrator;
import android.os.FileUtils.FileStatus;
import android.os.storage.StorageManager;
+import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.ClipboardManager;
import android.util.AndroidRuntimeException;
@@ -2646,14 +2648,13 @@
// 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) {
+ public int recommendAppInstallLocation(Package pkg) {
// 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)) {
+ if (pkg == null) {
return INSTALL_PARSE_FAILED_NOT_APK;
}
@@ -2669,44 +2670,71 @@
double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
- final String archiveFilePath = packageURI.getPath();
+ final String archiveFilePath = pkg.mScanPath;
File apkFile = new File(archiveFilePath);
long pkgLen = apkFile.length();
+ boolean auto = true;
+ // To make final copy
+ long reqInstallSize = pkgLen;
+ // For dex files
+ long reqInternalSize = 1 * pkgLen;
+ boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
+ boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalFlashSize);
+ boolean fitsOnSd = (reqInstallSize < availSDSize) && intThresholdOk &&
+ (reqInternalSize < availInternalFlashSize);
+ boolean fitsOnInt = intThresholdOk && intAvailOk;
+
// 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;
+ boolean installOnlyOnSd = (pkg.installLocation ==
+ PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+ boolean installOnlyInternal = (pkg.installLocation ==
+ PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+ if (installOnlyInternal) {
+ // If set explicitly in manifest,
+ // let that override everything else
+ auto = false;
+ } else if (installOnlyOnSd){
+ // Check if this can be accommodated on the sdcard
+ if (fitsOnSd) {
+ auto = false;
}
- 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;
+ // Check if user option is enabled
+ boolean setInstallLoc = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 0) != 0;
+ if (setInstallLoc) {
+ // Pick user preference
+ int installPreference = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.DEFAULT_INSTALL_LOCATION,
+ PackageInfo.INSTALL_LOCATION_AUTO);
+ if (installPreference == 1) {
+ installOnlyInternal = true;
+ auto = false;
+ } else if (installPreference == 2) {
+ installOnlyOnSd = true;
+ auto = false;
+ }
}
}
+ if (!auto) {
+ if (installOnlyOnSd) {
+ return fitsOnSd ? INSTALL_ON_SDCARD : INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ } else if (installOnlyInternal){
+ // Check on internal flash
+ return fitsOnInt ? INSTALL_ON_INTERNAL_FLASH : INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ }
+ // Try to install internally
+ if (fitsOnInt) {
+ return INSTALL_ON_INTERNAL_FLASH;
+ }
+ // Try the sdcard now.
+ if (fitsOnSd) {
+ return INSTALL_ON_SDCARD;
+ }
+ // Return error code
+ return INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
private final ContextImpl mContext;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 3046a2c..5a295b4 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1279,16 +1279,6 @@
public final static String APP_DATA = "app_data";
/**
- * Intent app_data bundle key: Use this key with the bundle from
- * {@link android.content.Intent#getBundleExtra
- * content.Intent.getBundleExtra(APP_DATA)} to obtain the source identifier
- * set by the activity that launched the search.
- *
- * @hide
- */
- public final static String SOURCE = "source";
-
- /**
* Intent extra data key: Use {@link android.content.Intent#getBundleExtra
* content.Intent.getBundleExtra(SEARCH_MODE)} to get the search mode used
* to launch the intent.
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index a8ce889..c003355 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -131,6 +131,34 @@
* The features that this application has said it requires.
*/
public FeatureInfo[] reqFeatures;
+
+ /**
+ * 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
+ * the {@link android.R.attr#installLocation} attribute.
+ * @hide
+ */
+ public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1;
+ /**
+ * Constant corresponding to <code>preferExternal</code> in
+ * the {@link android.R.attr#installLocation} attribute.
+ * @hide
+ */
+ public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2;
+ /**
+ * The launch mode style requested by the activity. From the
+ * {@link android.R.attr#installLocation} attribute, one of
+ * {@link #INSTALL_LOCATION_AUTO},
+ * {@link #INSTALL_LOCATION_INTERNAL_ONLY},
+ * {@link #INSTALL_LOCATION_PREFER_EXTERNAL}
+ * @hide
+ */
+ public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
public PackageInfo() {
}
@@ -168,6 +196,7 @@
dest.writeTypedArray(signatures, parcelableFlags);
dest.writeTypedArray(configPreferences, parcelableFlags);
dest.writeTypedArray(reqFeatures, parcelableFlags);
+ dest.writeInt(installLocation);
}
public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -202,5 +231,6 @@
signatures = source.createTypedArray(Signature.CREATOR);
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
+ installLocation = source.readInt();
}
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fca8588..a61eab9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -630,10 +630,11 @@
/**
* Determines best place to install an application: either SD or internal FLASH.
- * Tweak the algorithm for best results.
- * @param appInfo ApplicationInfo object of the package to install.
+ * If applications explicitly set installLocation in their manifest, that
+ * preference takes precedence. If not a recommended location is returned
+ * based on current available storage on internal flash or sdcard.
+ * @param pkgInfo PackageParser.Package of the package that is to be installed.
* Call utility method to obtain.
- * @param packageURI URI identifying the package's APK file.
* @return {@link INSTALL_ON_INTERNAL_FLASH} if it is best to install package on internal
* storage, {@link INSTALL_ON_SDCARD} if it is best to install package on SD card,
* and {@link INSTALL_FAILED_INSUFFICIENT_STORAGE} if insufficient space to safely install
@@ -642,7 +643,7 @@
* This recommendation does take into account the package's own flags.
* @hide
*/
- public abstract int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI);
+ public abstract int recommendAppInstallLocation(PackageParser.Package pkg);
/**
* Retrieve overall information about an application package that is
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b31df32..0a6195f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -177,6 +177,7 @@
pi.sharedUserId = p.mSharedUserId;
pi.sharedUserLabel = p.mSharedUserLabel;
pi.applicationInfo = p.applicationInfo;
+ pi.installLocation = p.installLocation;
if ((flags&PackageManager.GET_GIDS) != 0) {
pi.gids = gids;
}
@@ -709,6 +710,9 @@
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
sa.recycle();
+ pkg.installLocation = sa.getInteger(
+ com.android.internal.R.styleable.AndroidManifest_installLocation,
+ PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
// Resource boolean are -1, so 1 means we don't know the value.
int supportsSmallScreens = 1;
@@ -2610,6 +2614,8 @@
*/
public ArrayList<FeatureInfo> reqFeatures = null;
+ public int installLocation;
+
public Package(String _name) {
packageName = _name;
applicationInfo.packageName = _name;
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 47c2cac..c0bff66 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -723,6 +723,7 @@
private static final String KEY_FOCAL_LENGTH = "focal-length";
private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
+ private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -1051,7 +1052,8 @@
}
/**
- * Sets the rate at which preview frames are received.
+ * Sets the rate at which preview frames are received. This is the
+ * target frame rate. The actual frame rate depends on the driver.
*
* @param fps the frame rate (frames per second)
*/
@@ -1060,8 +1062,9 @@
}
/**
- * Returns the setting for the rate at which preview frames
- * are received.
+ * Returns the setting for the rate at which preview frames are
+ * received. This is the target frame rate. The actual frame rate
+ * depends on the driver.
*
* @return the frame rate setting (frames per second)
*/
@@ -1540,6 +1543,41 @@
}
/**
+ * Gets the current exposure compensation setting.
+ *
+ * @return the current exposure compensation value multiplied by 100.
+ * null if exposure compensation is not supported. Ex: -100
+ * means -1 EV. 130 means +1.3 EV.
+ * @hide
+ */
+ public int getExposureCompensation() {
+ return getInt(KEY_EXPOSURE_COMPENSATION);
+ }
+
+ /**
+ * Sets the exposure compensation.
+ *
+ * @param value exposure compensation multiplied by 100. Ex: -100 means
+ * -1 EV. 130 means +1.3 EV.
+ * @hide
+ */
+ public void setExposureCompensation(int value) {
+ set(KEY_EXPOSURE_COMPENSATION, value);
+ }
+
+ /**
+ * Gets the supported exposure compensation.
+ *
+ * @return a List of Integer constants. null if exposure compensation is
+ * not supported. The list is sorted from small to large. Ex:
+ * -100, -66, -33, 0, 33, 66, 100.
+ * @hide
+ */
+ public List<Integer> getSupportedExposureCompensation() {
+ return splitInt(get(KEY_EXPOSURE_COMPENSATION + SUPPORTED_VALUES_SUFFIX));
+ }
+
+ /**
* Gets current zoom value. This also works when smooth zoom is in
* progress.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bacaf43..c2cdcc0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1473,6 +1473,21 @@
public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
/**
+ * Let user pick default install location.
+ * @hide
+ */
+ public static final String SET_INSTALL_LOCATION = "set_install_location";
+
+ /**
+ * Default install location value.
+ * 0 = auto, let system decide
+ * 1 = internal
+ * 2 = sdcard
+ * @hide
+ */
+ public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
* @hide
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 54781e3..2da23eb 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -600,6 +600,20 @@
Application class to avoid interference with application logic. -->
<attr name="restoreNeedsApplication" format="boolean" />
+ <!-- The default install location defined by an application. -->
+ <attr name="installLocation">
+ <!-- Let the system decide ideal install location -->
+ <enum name="auto" value="0" />
+ <!-- Explicitly request to be installed on internal phone storate
+ only. -->
+ <enum name="internalOnly" value="1" />
+ <!-- Prefer to be installed on sdcard. There is no guarantee that
+ the system will honour this request. The application might end
+ up being installed on internal storage if external media
+ is unavailable or too full. -->
+ <enum name="preferExternal" value="2" />
+ </attr>
+
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
describing the contents of an Android package (.apk) file. One
@@ -624,6 +638,7 @@
<attr name="versionName" />
<attr name="sharedUserId" />
<attr name="sharedUserLabel" />
+ <attr name="installLocation" />
</declare-styleable>
<!-- The <code>application</code> tag describes application-level components
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bd4a3eb..596e0b2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1224,9 +1224,10 @@
<public type="attr" name="expandableListViewWhiteStyle" id="0x010102b6" />
<!-- ===============================================================
- Resources proposed for Flan.
+ Resources proposed for Froyo.
=============================================================== -->
<eat-comment />
<public type="attr" name="neverEncrypt" id="0x010102b7" />
+ <public type="attr" name="installLocation" id="0x010102b8" />
</resources>
diff --git a/docs/html/shareables/latest_samples.zip b/docs/html/shareables/latest_samples.zip
index 42fad99..34102c5 100644
--- a/docs/html/shareables/latest_samples.zip
+++ b/docs/html/shareables/latest_samples.zip
Binary files differ
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index 09b4bf4..5a4531b 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -21,13 +21,11 @@
/**
* YuvImage contains YUV data and provides a method that compresses a region of
* the YUV data to a Jpeg. The YUV data should be provided as a single byte
- * array irrespective of the number of image planes in it. The stride of each
- * image plane should be provided as well.
+ * array irrespective of the number of image planes in it.
+ * Currently only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I are supported.
*
- * To compress a rectangle region in the YUV data, users have to specify a
- * region by width, height and offsets, where each image plane has a
- * corresponding offset. All offsets are measured as a displacement in bytes
- * from yuv[0], where yuv[0] is the beginning of the yuv data.
+ * To compress a rectangle region in the YUV data, users have to specify the
+ * region by left, top, width and height.
*/
public class YuvImage {
@@ -55,21 +53,56 @@
private int[] mStrides;
/**
+ * The width of the image.
+ */
+ private int mWidth;
+
+ /**
+ * The height of the the image.
+ */
+ private int mHeight;
+
+ /**
* Construct an YuvImage.
*
- * @param yuv The YUV data. In the case of more than one image plane, all the planes must be
- * concatenated into a single byte array.
- * @param format The YUV data format as defined in {@link PixelFormat}.
- * @param strides Row bytes of each image plane.
+ * @param yuv The YUV data. In the case of more than one image plane, all the planes must be
+ * concatenated into a single byte array.
+ * @param format The YUV data format as defined in {@link PixelFormat}.
+ * @param width The width of the YuvImage.
+ * @param height The height of the YuvImage.
+ * @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the stride
+ * of each image must be provided. If strides is null, the method assumes no
+ * padding and derives the row bytes by format and width itself.
+ * @throws IllegalArgumentException if format is not support; width or height <= 0; or yuv is
+ * null.
*/
- public YuvImage(byte[] yuv, int format, int[] strides) {
- if ((yuv == null) || (strides == null)) {
+ public YuvImage(byte[] yuv, int format, int width, int height, int[] strides) {
+ if (format != PixelFormat.YCbCr_420_SP &&
+ format != PixelFormat.YCbCr_422_I) {
throw new IllegalArgumentException(
- "yuv or strides cannot be null");
+ "only support PixelFormat.YCbCr_420_SP " +
+ "and PixelFormat.YCbCr_422_I for now");
}
+
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException(
+ "width and height must large than 0");
+ }
+
+ if (yuv == null) {
+ throw new IllegalArgumentException("yuv cannot be null");
+ }
+
+ if (strides == null) {
+ mStrides = calculateStrides(width, format);
+ } else {
+ mStrides = strides;
+ }
+
mData = yuv;
mFormat = format;
- mStrides = strides;
+ mWidth = width;
+ mHeight = height;
}
/**
@@ -77,22 +110,21 @@
* Only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I
* are supported for now.
*
- * @param width The width of the rectangle region.
- * @param height The height of the rectangle region.
- * @param offsets The offsets of the rectangle region in each image plane.
- * The offsets are measured as a displacement in bytes from
- * yuv[0], where yuv[0] is the beginning of the yuv data.
- * @param quality Hint to the compressor, 0-100. 0 meaning compress for
- * small size, 100 meaning compress for max quality.
- * @param stream The outputstream to write the compressed data.
- *
- * @return true if successfully compressed to the specified stream.
- *
+ * @param rectangle The rectangle region to be compressed. The medthod checks if rectangle is
+ * inside the image. Also, the method modifies rectangle if the chroma pixels
+ * in it are not matched with the luma pixels in it.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality.
+ * @param stream OutputStream to write the compressed data.
+ * @return True if the compression is successful.
+ * @throws IllegalArgumentException if rectangle is invalid; quality is not within [0,
+ * 100]; or stream is null.
*/
- public boolean compressToJpeg(int width, int height, int[] offsets, int quality,
- OutputStream stream) {
- if (!validate(mFormat, width, height, offsets)) {
- return false;
+ public boolean compressToJpeg(Rect rectangle, int quality, OutputStream stream) {
+ Rect wholeImage = new Rect(0, 0, mWidth, mHeight);
+ if (!wholeImage.contains(rectangle)) {
+ throw new IllegalArgumentException(
+ "rectangle is not inside the image");
}
if (quality < 0 || quality > 100) {
@@ -100,14 +132,19 @@
}
if (stream == null) {
- throw new NullPointerException();
+ throw new IllegalArgumentException("stream cannot be null");
}
- return nativeCompressToJpeg(mData, mFormat, width, height, offsets,
- mStrides, quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
+ adjustRectangle(rectangle);
+ int[] offsets = calculateOffsets(rectangle.left, rectangle.top);
+
+ return nativeCompressToJpeg(mData, mFormat, rectangle.width(),
+ rectangle.height(), offsets, mStrides, quality, stream,
+ new byte[WORKING_COMPRESS_STORAGE]);
}
- /**
+
+ /**
* @return the YUV data.
*/
public byte[] getYuvData() {
@@ -128,37 +165,71 @@
return mStrides;
}
- protected boolean validate(int format, int width, int height, int[] offsets) {
- if (format != PixelFormat.YCbCr_420_SP &&
- format != PixelFormat.YCbCr_422_I) {
- throw new IllegalArgumentException(
- "only support PixelFormat.YCbCr_420_SP " +
- "and PixelFormat.YCbCr_422_I for now");
+ /**
+ * @return the width of the image.
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * @return the height of the image.
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ int[] calculateOffsets(int left, int top) {
+ int[] offsets = null;
+ if (mFormat == PixelFormat.YCbCr_420_SP) {
+ offsets = new int[] {top * mStrides[0] + left,
+ mHeight * mStrides[0] + top / 2 * mStrides[1]
+ + left / 2 * 2 };
+ return offsets;
}
- if (offsets.length != mStrides.length) {
- throw new IllegalArgumentException(
- "the number of image planes are mismatched");
+ if (mFormat == PixelFormat.YCbCr_422_I) {
+ offsets = new int[] {top * mStrides[0] + left / 2 * 4};
+ return offsets;
}
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException(
- "width and height must large than 0");
- }
+ return offsets;
+ }
- int requiredSize;
+ private int[] calculateStrides(int width, int format) {
+ int[] strides = null;
if (format == PixelFormat.YCbCr_420_SP) {
- requiredSize = height * mStrides[0] +(height >> 1) * mStrides[1];
- } else {
- requiredSize = height * mStrides[0];
+ strides = new int[] {width, width};
+ return strides;
}
- if (requiredSize > mData.length) {
- throw new IllegalArgumentException(
- "width or/and height is larger than the yuv data");
+ if (format == PixelFormat.YCbCr_422_I) {
+ strides = new int[] {width * 2};
+ return strides;
}
- return true;
+ return strides;
+ }
+
+ private void adjustRectangle(Rect rect) {
+ int width = rect.width();
+ int height = rect.height();
+ if (mFormat == PixelFormat.YCbCr_420_SP) {
+ // Make sure left, top, width and height are all even.
+ width &= ~1;
+ height &= ~1;
+ rect.left &= ~1;
+ rect.top &= ~1;
+ rect.right = rect.left + width;
+ rect.bottom = rect.top + height;
+ }
+
+ if (mFormat == PixelFormat.YCbCr_422_I) {
+ // Make sure left and width are both even.
+ width &= ~1;
+ rect.left &= ~1;
+ rect.right = rect.left + width;
+ }
}
//////////// native methods
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index a5a1bb8..be06e33 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -62,7 +62,8 @@
// AudioSink: abstraction layer for audio output
class AudioSink : public RefBase {
public:
- typedef void (*AudioCallback)(
+ // Callback returns the number of bytes actually written to the buffer.
+ typedef size_t (*AudioCallback)(
AudioSink *audioSink, void *buffer, size_t size, void *cookie);
virtual ~AudioSink() {}
@@ -77,8 +78,7 @@
virtual status_t getPosition(uint32_t *position) = 0;
// If no callback is specified, use the "write" API below to submit
- // audio data. Otherwise return a full buffer of audio data on each
- // callback.
+ // audio data.
virtual status_t open(
uint32_t sampleRate, int channelCount,
int format=AudioSystem::PCM_16_BIT,
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 843e051..8e5f05f 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -90,11 +90,11 @@
static void AudioCallback(int event, void *user, void *info);
void AudioCallback(int event, void *info);
- static void AudioSinkCallback(
+ static size_t AudioSinkCallback(
MediaPlayerBase::AudioSink *audioSink,
void *data, size_t size, void *me);
- void fillBuffer(void *data, size_t size);
+ size_t fillBuffer(void *data, size_t size);
int64_t getRealTimeUsLocked() const;
diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h
index 2c29bfb..e328f33 100644
--- a/include/ui/CameraParameters.h
+++ b/include/ui/CameraParameters.h
@@ -187,6 +187,13 @@
// Vertical angle of view in degrees.
// Example value: "42.5". Read only.
static const char KEY_VERTICAL_VIEW_ANGLE[];
+ // Exposure compensation. The value is multiplied by 100. -100 means -1 EV.
+ // 130 means +1.3 EV.
+ // Example value: "0" or "133". Read/write.
+ static const char KEY_EXPOSURE_COMPENSATION[];
+ // Supported exposure compensation.
+ // Example value: "-100,-66,-33,0,33,66,100". Read only.
+ static const char KEY_SUPPORTED_EXPOSURE_COMPENSATION[];
// Values for white balance settings.
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 09a36f1..f374fbc 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -281,7 +281,7 @@
// send command to camera driver
status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
{
- LOGD("sendCommand");
+ LOGV("sendCommand");
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
return c->sendCommand(cmd, arg1, arg2);
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
index c4958a0..493b9c1 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/ui/CameraParameters.cpp
@@ -59,6 +59,8 @@
const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
+const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensation";
+const char CameraParameters::KEY_SUPPORTED_EXPOSURE_COMPENSATION[] = "exposure-compensation-values";
// Values for white balance settings.
const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp
index e1b3ec7..4154b05a 100644
--- a/libs/ui/ICamera.cpp
+++ b/libs/ui/ICamera.cpp
@@ -344,7 +344,7 @@
return NO_ERROR;
} break;
case SEND_COMMAND: {
- LOGD("SEND_COMMAND");
+ LOGV("SEND_COMMAND");
CHECK_INTERFACE(ICamera, data, reply);
int command = data.readInt32();
int arg1 = data.readInt32();
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 628cb6b7..8c24ee1 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -22,7 +22,6 @@
import android.location.IGeocodeProvider;
import android.location.IGpsStatusListener;
import android.location.ILocationListener;
-import android.location.ILocationProvider;
import android.location.Location;
import android.os.Bundle;
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 9fe6ab4..5529b11 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -21,7 +21,7 @@
import android.os.Bundle;
/**
- * Binder interface for location providers.
+ * Binder interface for services that implement location providers.
*
* {@hide}
*/
diff --git a/location/java/android/location/LocationProviderInterface.java b/location/java/android/location/LocationProviderInterface.java
new file mode 100644
index 0000000..98beffe
--- /dev/null
+++ b/location/java/android/location/LocationProviderInterface.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.location.Location;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+
+/**
+ * Location Manager's interface for location providers.
+ *
+ * {@hide}
+ */
+public interface LocationProviderInterface {
+ String getName();
+ boolean requiresNetwork();
+ boolean requiresSatellite();
+ boolean requiresCell();
+ boolean hasMonetaryCost();
+ boolean supportsAltitude();
+ boolean supportsSpeed();
+ boolean supportsBearing();
+ int getPowerRequirement();
+ int getAccuracy();
+ boolean isEnabled();
+ void enable();
+ void disable();
+ int getStatus(Bundle extras);
+ long getStatusUpdateTime();
+ void enableLocationTracking(boolean enable);
+ void setMinTime(long minTime);
+ void updateNetworkState(int state, NetworkInfo info);
+ void updateLocation(Location location);
+ boolean sendExtraCommand(String command, Bundle extras);
+ void addListener(int uid);
+ void removeListener(int uid);
+}
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 8b5f702..dce3b27 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -26,11 +26,11 @@
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
import android.location.ILocationManager;
-import android.location.ILocationProvider;
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.SntpClient;
@@ -65,7 +65,7 @@
*
* {@hide}
*/
-public class GpsLocationProvider extends ILocationProvider.Stub {
+public class GpsLocationProvider implements LocationProviderInterface {
private static final String TAG = "GpsLocationProvider";
@@ -374,6 +374,13 @@
}
/**
+ * Returns the name of this provider.
+ */
+ public String getName() {
+ return LocationManager.GPS_PROVIDER;
+ }
+
+ /**
* Returns true if the provider requires access to a
* data network (e.g., the Internet), false otherwise.
*/
@@ -576,6 +583,10 @@
}
}
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
public int getStatus(Bundle extras) {
if (extras != null) {
extras.putInt("satellites", mSvCount);
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index 361104f..abb90b7 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -22,6 +22,7 @@
import android.content.ServiceConnection;
import android.location.ILocationProvider;
import android.location.Location;
+import android.location.LocationProviderInterface;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
@@ -31,18 +32,17 @@
import android.util.Log;
/**
- * A class for proxying ILocationProvider implementations.
+ * A class for proxying location providers implemented as services.
*
* {@hide}
*/
-public class LocationProviderProxy {
+public class LocationProviderProxy implements LocationProviderInterface {
private static final String TAG = "LocationProviderProxy";
private final Context mContext;
private final String mName;
private ILocationProvider mProvider;
- private Intent mIntent;
private Handler mHandler;
private final Connection mServiceConnection = new Connection();
@@ -56,21 +56,13 @@
// for caching requiresNetwork, requiresSatellite, etc.
private DummyLocationProvider mCachedAttributes;
- // constructor for proxying built-in location providers
- public LocationProviderProxy(Context context, String name, ILocationProvider provider) {
- mContext = context;
- mName = name;
- mProvider = provider;
- }
-
// constructor for proxying location providers implemented in a separate service
public LocationProviderProxy(Context context, String name, String serviceName,
Handler handler) {
mContext = context;
mName = name;
- mIntent = new Intent(serviceName);
mHandler = handler;
- mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ mContext.bindService(new Intent(serviceName), mServiceConnection, Context.BIND_AUTO_CREATE);
}
private class Connection implements ServiceConnection {
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 7d9e86c..2f6fdee 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -17,9 +17,9 @@
package com.android.internal.location;
import android.location.ILocationManager;
-import android.location.ILocationProvider;
import android.location.Location;
import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.RemoteException;
@@ -33,7 +33,7 @@
*
* {@hide}
*/
-public class MockProvider extends ILocationProvider.Stub {
+public class MockProvider implements LocationProviderInterface {
private final String mName;
private final ILocationManager mLocationManager;
private final boolean mRequiresNetwork;
@@ -73,6 +73,10 @@
mLocation = new Location(name);
}
+ public String getName() {
+ return mName;
+ }
+
public void disable() {
mEnabled = false;
}
@@ -81,6 +85,10 @@
mEnabled = true;
}
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
public int getStatus(Bundle extras) {
if (mHasStatus) {
extras.clear();
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 8c1b0ea..34252ab 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -16,10 +16,14 @@
package android.media;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.IContentProvider;
-import android.content.ContentUris;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.BitmapFactory;
@@ -42,11 +46,12 @@
import android.util.Log;
import android.util.Xml;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -586,6 +591,9 @@
}
if (genreCode >= 0 && genreCode < ID3_GENRES.length) {
value = ID3_GENRES[genreCode];
+ } else if (genreCode == 255) {
+ // 255 is defined to be unknown
+ value = null;
}
}
mGenre = value;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8e61011..55b06f4 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1597,9 +1597,12 @@
AudioOutput *me = (AudioOutput *)cookie;
AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
- (*me->mCallback)(
+ size_t actualSize = (*me->mCallback)(
me, buffer->raw, buffer->size, me->mCallbackCookie);
- me->snoopWrite(buffer->raw, buffer->size);
+
+ if (actualSize > 0) {
+ me->snoopWrite(buffer->raw, actualSize);
+ }
}
#undef LOG_TAG
@@ -1629,14 +1632,75 @@
return NO_ERROR;
}
+////////////////////////////////////////////////////////////////////////////////
+
+struct CallbackThread : public Thread {
+ CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
+ MediaPlayerBase::AudioSink::AudioCallback cb,
+ void *cookie);
+
+protected:
+ virtual ~CallbackThread();
+
+ virtual bool threadLoop();
+
+private:
+ wp<MediaPlayerBase::AudioSink> mSink;
+ MediaPlayerBase::AudioSink::AudioCallback mCallback;
+ void *mCookie;
+ void *mBuffer;
+ size_t mBufferSize;
+
+ CallbackThread(const CallbackThread &);
+ CallbackThread &operator=(const CallbackThread &);
+};
+
+CallbackThread::CallbackThread(
+ const wp<MediaPlayerBase::AudioSink> &sink,
+ MediaPlayerBase::AudioSink::AudioCallback cb,
+ void *cookie)
+ : mSink(sink),
+ mCallback(cb),
+ mCookie(cookie),
+ mBuffer(NULL),
+ mBufferSize(0) {
+}
+
+CallbackThread::~CallbackThread() {
+ if (mBuffer) {
+ free(mBuffer);
+ mBuffer = NULL;
+ }
+}
+
+bool CallbackThread::threadLoop() {
+ sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
+ if (sink == NULL) {
+ return false;
+ }
+
+ if (mBuffer == NULL) {
+ mBufferSize = sink->bufferSize();
+ mBuffer = malloc(mBufferSize);
+ }
+
+ size_t actualSize =
+ (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie);
+
+ if (actualSize > 0) {
+ sink->write(mBuffer, actualSize);
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
status_t MediaPlayerService::AudioCache::open(
uint32_t sampleRate, int channelCount, int format, int bufferCount,
AudioCallback cb, void *cookie)
{
LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
- if (cb != NULL) {
- return UNKNOWN_ERROR; // TODO: implement this.
- }
if (mHeap->getHeapID() < 0) {
return NO_INIT;
}
@@ -1645,9 +1709,25 @@
mChannelCount = (uint16_t)channelCount;
mFormat = (uint16_t)format;
mMsecsPerFrame = 1.e3 / (float) sampleRate;
+
+ if (cb != NULL) {
+ mCallbackThread = new CallbackThread(this, cb, cookie);
+ }
return NO_ERROR;
}
+void MediaPlayerService::AudioCache::start() {
+ if (mCallbackThread != NULL) {
+ mCallbackThread->run("AudioCache callback");
+ }
+}
+
+void MediaPlayerService::AudioCache::stop() {
+ if (mCallbackThread != NULL) {
+ mCallbackThread->requestExitAndWait();
+ }
+}
+
ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
{
LOGV("write(%p, %u)", buffer, size);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index ffe1ba0..5c03e47 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -139,9 +139,9 @@
int bufferCount = 1,
AudioCallback cb = NULL, void *cookie = NULL);
- virtual void start() {}
+ virtual void start();
virtual ssize_t write(const void* buffer, size_t size);
- virtual void stop() {}
+ virtual void stop();
virtual void flush() {}
virtual void pause() {}
virtual void close() {}
@@ -171,6 +171,8 @@
uint32_t mSize;
int mError;
bool mCommandComplete;
+
+ sp<Thread> mCallbackThread;
};
public:
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 4926920..12d7ee2 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -187,12 +187,12 @@
}
// static
-void AudioPlayer::AudioSinkCallback(
+size_t AudioPlayer::AudioSinkCallback(
MediaPlayerBase::AudioSink *audioSink,
void *buffer, size_t size, void *cookie) {
AudioPlayer *me = (AudioPlayer *)cookie;
- me->fillBuffer(buffer, size);
+ return me->fillBuffer(buffer, size);
}
void AudioPlayer::AudioCallback(int event, void *info) {
@@ -201,17 +201,18 @@
}
AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
- fillBuffer(buffer->raw, buffer->size);
+ size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
+
+ buffer->size = numBytesWritten;
}
-void AudioPlayer::fillBuffer(void *data, size_t size) {
+size_t AudioPlayer::fillBuffer(void *data, size_t size) {
if (mNumFramesPlayed == 0) {
LOGV("AudioCallback");
}
if (mReachedEOS) {
- memset(data, 0, size);
- return;
+ return 0;
}
size_t size_done = 0;
@@ -244,7 +245,6 @@
if (err != OK) {
mReachedEOS = true;
- memset((char *)data + size_done, 0, size_remaining);
break;
}
@@ -285,7 +285,9 @@
}
Mutex::Autolock autoLock(mLock);
- mNumFramesPlayed += size / mFrameSize;
+ mNumFramesPlayed += size_done / mFrameSize;
+
+ return size_done;
}
int64_t AudioPlayer::getRealTimeUs() {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 4458006..1ff38ee 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1540,7 +1540,7 @@
if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
|| !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
- || !memcmp(header, "ftypM4A ", 8)) {
+ || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)) {
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.1;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c6c6f21..75b7b6f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -112,7 +112,6 @@
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
- { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
diff --git a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
index 6b3093f..1434d3f 100644
--- a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
+++ b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
@@ -43,10 +43,9 @@
private TestThread mThread;
private static final int[] mTestFiles = new int[] {
- // FIXME: Restore when Stagefright bug is fixed
R.raw.organ441,
R.raw.sine441,
- //R.raw.test1,
+ R.raw.test1,
R.raw.test2,
R.raw.test3,
R.raw.test4,
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 7686aa0..ba6024f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -56,5 +56,6 @@
<bool name="def_mount_ums_autostart">false</bool>
<bool name="def_mount_ums_prompt">true</bool>
<bool name="def_mount_ums_notify_enabled">true</bool>
+ <bool name="set_install_location">true</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 015b487..ac20297 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -864,6 +864,8 @@
loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
R.bool.def_notification_pulse);
+ loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION, R.bool.set_install_location);
+ loadIntegerSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION, 0);
stmt.close();
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index fff6c54..e12f2e1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -45,11 +45,11 @@
import android.location.IGpsStatusProvider;
import android.location.ILocationListener;
import android.location.ILocationManager;
-import android.location.ILocationProvider;
import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@@ -114,8 +114,8 @@
private LocationWorkerHandler mLocationHandler;
// Cache the real providers for use in addTestProvider() and removeTestProvider()
- LocationProviderProxy mNetworkLocationProvider;
- LocationProviderProxy mGpsLocationProvider;
+ LocationProviderInterface mNetworkLocationProvider;
+ LocationProviderInterface mGpsLocationProvider;
// Handler messages
private static final int MESSAGE_LOCATION_CHANGED = 1;
@@ -134,10 +134,10 @@
/**
* List of location providers.
*/
- private final ArrayList<LocationProviderProxy> mProviders =
- new ArrayList<LocationProviderProxy>();
- private final HashMap<String, LocationProviderProxy> mProvidersByName
- = new HashMap<String, LocationProviderProxy>();
+ private final ArrayList<LocationProviderInterface> mProviders =
+ new ArrayList<LocationProviderInterface>();
+ private final HashMap<String, LocationProviderInterface> mProvidersByName
+ = new HashMap<String, LocationProviderInterface>();
/**
* Object used internally for synchronization
@@ -411,12 +411,12 @@
}
}
- private void addProvider(LocationProviderProxy provider) {
+ private void addProvider(LocationProviderInterface provider) {
mProviders.add(provider);
mProvidersByName.put(provider.getName(), provider);
}
- private void removeProvider(LocationProviderProxy provider) {
+ private void removeProvider(LocationProviderInterface provider) {
mProviders.remove(provider);
mProvidersByName.remove(provider.getName());
}
@@ -445,13 +445,11 @@
// Attempt to load "real" providers first
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
- GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
- mGpsStatusProvider = provider.getGpsStatusProvider();
- mNetInitiatedListener = provider.getNetInitiatedListener();
- LocationProviderProxy proxy =
- new LocationProviderProxy(mContext, LocationManager.GPS_PROVIDER, provider);
- addProvider(proxy);
- mGpsLocationProvider = proxy;
+ GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
+ mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
+ mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
+ addProvider(gpsProvider);
+ mGpsLocationProvider = gpsProvider;
}
// initialize external network location and geocoder services
@@ -591,7 +589,7 @@
}
ArrayList<String> out = new ArrayList<String>(mProviders.size());
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy p = mProviders.get(i);
+ LocationProviderInterface p = mProviders.get(i);
out.add(p.getName());
}
return out;
@@ -616,7 +614,7 @@
}
ArrayList<String> out = new ArrayList<String>(mProviders.size());
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy p = mProviders.get(i);
+ LocationProviderInterface p = mProviders.get(i);
String name = p.getName();
if (isAllowedProviderSafe(name)) {
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@@ -630,7 +628,7 @@
private void updateProvidersLocked() {
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy p = mProviders.get(i);
+ LocationProviderInterface p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
@@ -647,7 +645,7 @@
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
return;
}
@@ -837,8 +835,8 @@
Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
}
- LocationProviderProxy proxy = mProvidersByName.get(provider);
- if (proxy == null) {
+ LocationProviderInterface p = mProvidersByName.get(provider);
+ if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@@ -856,14 +854,14 @@
}
if (newUid) {
- proxy.addListener(callingUid);
+ p.addListener(callingUid);
}
boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
if (isProviderEnabled) {
long minTimeForProvider = getMinTimeLocked(provider);
- proxy.setMinTime(minTimeForProvider);
- proxy.enableLocationTracking(true);
+ p.setMinTime(minTimeForProvider);
+ p.enableLocationTracking(true);
} else {
// Notify the listener that updates are currently disabled
receiver.callProviderEnabledLocked(provider, false);
@@ -923,9 +921,9 @@
// Call dispose() on the obsolete update records.
for (UpdateRecord record : oldRecords.values()) {
if (!providerHasListener(record.mProvider, callingUid, receiver)) {
- LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
- if (proxy != null) {
- proxy.removeListener(callingUid);
+ LocationProviderInterface p = mProvidersByName.get(record.mProvider);
+ if (p != null) {
+ p.removeListener(callingUid);
}
}
record.disposeLocked();
@@ -949,7 +947,7 @@
hasOtherListener = true;
}
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p != null) {
if (hasOtherListener) {
p.setMinTime(getMinTimeLocked(provider));
@@ -1006,12 +1004,12 @@
}
synchronized (mLock) {
- LocationProviderProxy proxy = mProvidersByName.get(provider);
- if (proxy == null) {
+ LocationProviderInterface p = mProvidersByName.get(provider);
+ if (p == null) {
return false;
}
- return proxy.sendExtraCommand(command, extras);
+ return p.sendExtraCommand(command, extras);
}
}
@@ -1261,7 +1259,7 @@
mProximityReceiver = new Receiver(mProximityListener);
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy provider = mProviders.get(i);
+ LocationProviderInterface provider = mProviders.get(i);
requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
}
}
@@ -1311,7 +1309,7 @@
}
private Bundle _getProviderInfoLocked(String provider) {
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null || !p.isEnabled()) {
return null;
}
@@ -1359,7 +1357,7 @@
private boolean _isProviderEnabledLocked(String provider) {
checkPermissionsSafe(provider);
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@@ -1382,7 +1380,7 @@
private Location _getLastKnownLocationLocked(String provider) {
checkPermissionsSafe(provider);
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
@@ -1424,7 +1422,7 @@
return;
}
- LocationProviderProxy p = mProvidersByName.get(provider);
+ LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
return;
}
@@ -1507,9 +1505,9 @@
// notify other providers of the new location
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy proxy = mProviders.get(i);
- if (!provider.equals(proxy.getName())) {
- proxy.updateLocation(location);
+ LocationProviderInterface p = mProviders.get(i);
+ if (!provider.equals(p.getName())) {
+ p.updateLocation(location);
}
}
@@ -1597,7 +1595,7 @@
// Notify location providers of current network state
synchronized (mLock) {
for (int i = mProviders.size() - 1; i >= 0; i--) {
- LocationProviderProxy provider = mProviders.get(i);
+ LocationProviderInterface provider = mProviders.get(i);
if (provider.isEnabled() && provider.requiresNetwork()) {
provider.updateNetworkState(mNetworkState, info);
}
@@ -1698,16 +1696,16 @@
// remove the real provider if we are replacing GPS or network provider
if (LocationManager.GPS_PROVIDER.equals(name)
|| LocationManager.NETWORK_PROVIDER.equals(name)) {
- LocationProviderProxy proxy = mProvidersByName.get(name);
- if (proxy != null) {
- proxy.enableLocationTracking(false);
- removeProvider(proxy);
+ LocationProviderInterface p = mProvidersByName.get(name);
+ if (p != null) {
+ p.enableLocationTracking(false);
+ removeProvider(p);
}
}
if (mProvidersByName.get(name) != null) {
throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
}
- addProvider(new LocationProviderProxy(mContext, name, provider));
+ addProvider(provider);
mMockProviders.put(name, provider);
mLastKnownLocation.put(name, null);
updateProvidersLocked();
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
deleted file mode 100644
index dc07585..0000000
--- a/test-runner/android/test/TestLocationProvider.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-
-import android.location.Criteria;
-import android.location.ILocationManager;
-import android.location.ILocationProvider;
-import android.location.Location;
-import android.location.LocationProvider;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.Log;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public class TestLocationProvider extends ILocationProvider.Stub {
-
- public static final String PROVIDER_NAME = "test";
- public static final double LAT = 0;
- public static final double LON = 1;
- public static final double ALTITUDE = 10000;
- public static final float SPEED = 10;
- public static final float BEARING = 1;
- public static final int STATUS = LocationProvider.AVAILABLE;
- private static final long LOCATION_INTERVAL = 1000;
-
- private static final String TAG = "TestLocationProvider";
-
- private final ILocationManager mLocationManager;
- private Location mLocation;
- private boolean mEnabled;
- private TestLocationProviderThread mThread;
-
- private class TestLocationProviderThread extends Thread {
-
- private boolean mDone = false;
-
- public TestLocationProviderThread() {
- super("TestLocationProviderThread");
- }
-
- public void run() {
- // thread exits after disable() is called
- synchronized (this) {
- while (!mDone) {
- try {
- wait(LOCATION_INTERVAL);
- } catch (InterruptedException e) {
- }
-
- if (!mDone) {
- TestLocationProvider.this.updateLocation();
- }
- }
- }
- }
-
- synchronized void setDone() {
- mDone = true;
- notify();
- }
- }
-
- public TestLocationProvider(ILocationManager locationManager) {
- mLocationManager = locationManager;
- mLocation = new Location(PROVIDER_NAME);
- }
-
- public int getAccuracy() {
- return Criteria.ACCURACY_COARSE;
- }
-
- public int getPowerRequirement() {
- return Criteria.NO_REQUIREMENT;
- }
-
- public boolean hasMonetaryCost() {
- return false;
- }
-
- public boolean requiresCell() {
- return false;
- }
-
- public boolean requiresNetwork() {
- return false;
- }
-
- public boolean requiresSatellite() {
- return false;
- }
-
- public boolean supportsAltitude() {
- return true;
- }
-
- public boolean supportsBearing() {
- return true;
- }
-
- public boolean supportsSpeed() {
- return true;
- }
-
- public synchronized void disable() {
- mEnabled = false;
- if (mThread != null) {
- mThread.setDone();
- try {
- mThread.join();
- } catch (InterruptedException e) {
- }
- mThread = null;
- }
- }
-
- public synchronized void enable() {
- mEnabled = true;
- mThread = new TestLocationProviderThread();
- mThread.start();
- }
-
- public boolean isEnabled() {
- return mEnabled;
- }
-
- public int getStatus(Bundle extras) {
- return STATUS;
- }
-
- public long getStatusUpdateTime() {
- return 0;
- }
-
- public void enableLocationTracking(boolean enable) {
- }
-
- public void setMinTime(long minTime) {
- }
-
- public void updateNetworkState(int state, NetworkInfo info) {
- }
-
- public void updateLocation(Location location) {
- }
-
- public boolean sendExtraCommand(String command, Bundle extras) {
- return false;
- }
-
- public void addListener(int uid) {
- }
-
- public void removeListener(int uid) {
- }
-
- private void updateLocation() {
- long time = SystemClock.uptimeMillis();
- long multiplier = (time/5000)%500000;
- mLocation.setLatitude(LAT*multiplier);
- mLocation.setLongitude(LON*multiplier);
- mLocation.setAltitude(ALTITUDE);
- mLocation.setSpeed(SPEED);
- mLocation.setBearing(BEARING*multiplier);
-
- Bundle extras = new Bundle();
- extras.putInt("extraTest", 24);
- mLocation.setExtras(extras);
- mLocation.setTime(time);
- try {
- mLocationManager.reportLocation(mLocation);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException calling updateLocation");
- }
- }
-
-}
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index cbe0253..c8339ed 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -30,6 +30,7 @@
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
@@ -443,7 +444,7 @@
* @hide
*/
@Override
- public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ public int recommendAppInstallLocation(PackageParser.Package pkg) {
throw new UnsupportedOperationException();
}
}
diff --git a/tests/AndroidTests/res/raw/install_loc_auto b/tests/AndroidTests/res/raw/install_loc_auto
new file mode 100644
index 0000000..60dda18
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_auto
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_internal b/tests/AndroidTests/res/raw/install_loc_internal
new file mode 100644
index 0000000..1bc33ca
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_internal
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_sdcard b/tests/AndroidTests/res/raw/install_loc_sdcard
new file mode 100644
index 0000000..6604e35
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_sdcard
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_unspecified b/tests/AndroidTests/res/raw/install_loc_unspecified
new file mode 100644
index 0000000..88bbace
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_unspecified
Binary files differ
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 3a4d38c..07bd489 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -37,6 +37,7 @@
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageStats;
@@ -59,6 +60,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
+import android.provider.Settings;
public class PackageManagerTests extends AndroidTestCase {
private static final boolean localLOGV = true;
@@ -761,6 +763,170 @@
outFile.delete();
}
}
+
+ public void invokeRecommendAppInstallLocation(String outFileName,
+ int fileResId, int expected) {
+ int origSetting = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 0);
+ try {
+ // Make sure the set install location setting is diabled.
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 0);
+ File filesDir = mContext.getFilesDir();
+ File outFile = new File(filesDir, outFileName);
+ Uri packageURI = getInstallablePackage(fileResId, outFile);
+ PackageParser.Package pkg = parsePackage(packageURI);
+ assertNotNull(pkg);
+ int installLoc = getPm().recommendAppInstallLocation(pkg);
+ Log.i(TAG, "expected=" + expected +", installLoc="+installLoc);
+ // Atleast one of the specified expected flags should be set.
+ boolean onFlash = (installLoc &
+ PackageManager.INSTALL_ON_INTERNAL_FLASH) != 0;
+ boolean onSd = (installLoc &
+ PackageManager.INSTALL_ON_SDCARD) != 0;
+ boolean expOnFlash = (expected &
+ PackageManager.INSTALL_ON_INTERNAL_FLASH) != 0;
+ boolean expOnSd = (expected &
+ PackageManager.INSTALL_ON_SDCARD) != 0;
+ assertTrue(expOnFlash == onFlash || expOnSd == onSd);
+ } finally {
+ // Restore original setting
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, origSetting);
+ }
+ }
+
+ /*
+ * Tests if an apk can be installed on internal flash by
+ * explicitly specifying in its manifest.
+ */
+ public void testInstallLocationInternal() {
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_internal, PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests if an apk can be installed on internal flash by
+ * explicitly specifying in its manifest and filling up
+ * internal flash. Should fail to install.
+ * TODO
+ */
+ public void xxxtestInstallLocationInternalFail() {
+ }
+
+ /*
+ * Tests if an apk can be installed on sdcard by
+ * explicitly specifying in its manifest.
+ */
+ public void testInstallLocationSdcard() {
+ // TODO No guarantee this will be on sdcard.
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_sdcard, PackageManager.INSTALL_ON_SDCARD
+ | PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests if an apk can be installed on sdcard by
+ * explicitly specifying in its manifest and filling up
+ * the sdcard. Should result in install failure
+ * TODO
+ */
+ public void xxxtestInstallLocationSdcardFail() {
+ }
+
+ /*
+ * Tests if an apk can be installed by specifying
+ * auto for install location
+ */
+ public void xxxtestInstallLocationAutoInternal() {
+ // TODO clear and make room on internal flash
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_auto, PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests if an apk can be installed by specifying
+ * auto for install location
+ */
+ public void testInstallLocationAutoSdcard() {
+ // TODO clear and make room on sdcard.
+ // Fill up internal
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_auto, PackageManager.INSTALL_ON_SDCARD |
+ PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests if an apk can be installed by specifying
+ * auto for install location
+ * fill up both internal and sdcard
+ * TODO
+ */
+ public void xxxtestInstallLocationAutoFail() {
+ }
+ /*
+ * Tests where an apk gets installed based
+ * on a not specifying anything in manifest.
+ */
+ public void testInstallLocationUnspecifiedInt() {
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_unspecified, PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ public void xxxtestInstallLocationUnspecifiedStorage() {
+ // TODO Fill up internal storage
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_unspecified, PackageManager.INSTALL_ON_SDCARD
+ | PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests where an apk gets installed by expcitly setting
+ * the user specified install location
+ */
+ public void testInstallLocationUserSpecifiedInternal() {
+ // Enable user setting
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 1);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.DEFAULT_INSTALL_LOCATION, 1);
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_unspecified, PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ }
+
+ /*
+ * Tests where an apk gets installed by expcitly setting
+ * the user specified install location
+ */
+ public void testInstallLocationUserSpecifiedSdcard() {
+ // Enable user setting
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 1);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.DEFAULT_INSTALL_LOCATION, 2);
+ int i = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.DEFAULT_INSTALL_LOCATION, 0);
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_unspecified, PackageManager.INSTALL_ON_SDCARD);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 0);
+ }
+ /*
+ * Tests where an apk gets installed by expcitly setting
+ * the user specified install location
+ */
+ public void testInstallLocationUserSpecifiedAuto() {
+ // Enable user setting
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 1);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.DEFAULT_INSTALL_LOCATION, 0);
+ invokeRecommendAppInstallLocation("install.apk",
+ R.raw.install_loc_unspecified, PackageManager.INSTALL_ON_INTERNAL_FLASH);
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, 0);
+ }
+
/*
* TODO's
* check version numbers for upgrades