diff options
42 files changed, 798 insertions, 419 deletions
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,8 +66331,8 @@ visibility="public" > </method> -<method name="getYuvData" - return="byte[]" +<method name="getWidth" + return="int" abstract="false" native="false" synchronized="false" @@ -66320,8 +66342,8 @@ visibility="public" > </method> -<method name="getYuvFormat" - return="int" +<method name="getYuvData" + return="byte[]" abstract="false" native="false" synchronized="false" @@ -66331,24 +66353,16 @@ visibility="public" > </method> -<method name="validate" - return="boolean" +<method name="getYuvFormat" + return="int" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" - visibility="protected" + visibility="public" > -<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> @@ -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.PermissionInfo; 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.StatFs; 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 @@ class ContextImpl extends Context { // 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 @@ class ContextImpl extends Context { 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 class SearchManager 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 @@ public class PackageInfo implements Parcelable { * 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 @@ public class PackageInfo implements Parcelable { 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 @@ public class PackageInfo implements Parcelable { 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 @@ public abstract class PackageManager { /** * 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 @@ public abstract class PackageManager { * 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 @@ public class PackageParser { 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 @@ public class PackageParser { 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 class PackageParser { */ 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 @@ public class Camera { 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 @@ public class Camera { } /** - * 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 @@ public class Camera { } /** - * 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 @@ public class Camera { } /** + * 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 final class Settings { 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 Binary files differindex 42fad99..34102c5 100644 --- a/docs/html/shareables/latest_samples.zip +++ b/docs/html/shareables/latest_samples.zip 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 @@ import java.io.OutputStream; /** * 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 @@ public class YuvImage { 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 @@ public class YuvImage { * 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 @@ public class YuvImage { } 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 @@ public class YuvImage { 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; + } - if (offsets.length != mStrides.length) { - throw new IllegalArgumentException( - "the number of image planes are mismatched"); + /** + * @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 (width <= 0 || height <= 0) { - throw new IllegalArgumentException( - "width and height must large than 0"); + if (mFormat == PixelFormat.YCbCr_422_I) { + offsets = new int[] {top * mStrides[0] + left / 2 * 4}; + return offsets; } - int requiredSize; + return offsets; + } + + 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 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; } - return true; + 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 @@ public: // 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 @@ public: 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 @@ private: 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 @@ public: // 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 @@ String8 Camera::getParameters() const // 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_SUPPORTED_FOCUS_MODES[] = "focus-mode-values"; 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..4154b05 100644 --- a/libs/ui/ICamera.cpp +++ b/libs/ui/ICamera.cpp @@ -344,7 +344,7 @@ status_t BnCamera::onTransact( 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.GeocoderParams; 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.net.NetworkInfo; 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.Criteria; 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 @@ import java.util.Map.Entry; * * {@hide} */ -public class GpsLocationProvider extends ILocationProvider.Stub { +public class GpsLocationProvider implements LocationProviderInterface { private static final String TAG = "GpsLocationProvider"; @@ -374,6 +374,13 @@ public class GpsLocationProvider extends ILocationProvider.Stub { } /** + * 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 class GpsLocationProvider extends ILocationProvider.Stub { } } + 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.Intent; 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.os.SystemClock; 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 @@ public class LocationProviderProxy { // 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 @@ import java.io.PrintWriter; * * {@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 @@ public class MockProvider extends ILocationProvider.Stub { mLocation = new Location(name); } + public String getName() { + return mName; + } + public void disable() { mEnabled = false; } @@ -81,6 +85,10 @@ public class MockProvider extends ILocationProvider.Stub { 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.Config; 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 @@ public class MediaScanner } 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 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( 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 @@ status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) 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 @@ status_t MediaPlayerService::AudioCache::open( 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 @@ class MediaPlayerService : public BnMediaPlayerService 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 @@ class MediaPlayerService : public BnMediaPlayerService 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 @@ bool AudioPlayer::reachedEOS() { } // 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 @@ void AudioPlayer::AudioCallback(int event, void *info) { } 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 @@ void AudioPlayer::fillBuffer(void *data, size_t size) { if (err != OK) { mReachedEOS = true; - memset((char *)data + size_done, 0, size_remaining); break; } @@ -285,7 +285,9 @@ void AudioPlayer::fillBuffer(void *data, size_t size) { } 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 @@ bool SniffMPEG4( 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 @@ static const CodecInfo kDecoderInfo[] = { { 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 @@ public class SoundPoolTest extends Activity 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 @@ public class DatabaseHelper extends SQLiteOpenHelper { 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.IGpsStatusListener; 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run /** * 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return; } - LocationProviderProxy p = mProvidersByName.get(provider); + LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) { return; } @@ -1507,9 +1505,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // 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 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // 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.IPackageStatsObserver; 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 @@ public class MockPackageManager extends PackageManager { * @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 Binary files differnew file mode 100644 index 0000000..60dda18 --- /dev/null +++ b/tests/AndroidTests/res/raw/install_loc_auto diff --git a/tests/AndroidTests/res/raw/install_loc_internal b/tests/AndroidTests/res/raw/install_loc_internal Binary files differnew file mode 100644 index 0000000..1bc33ca --- /dev/null +++ b/tests/AndroidTests/res/raw/install_loc_internal diff --git a/tests/AndroidTests/res/raw/install_loc_sdcard b/tests/AndroidTests/res/raw/install_loc_sdcard Binary files differnew file mode 100644 index 0000000..6604e35 --- /dev/null +++ b/tests/AndroidTests/res/raw/install_loc_sdcard diff --git a/tests/AndroidTests/res/raw/install_loc_unspecified b/tests/AndroidTests/res/raw/install_loc_unspecified Binary files differnew file mode 100644 index 0000000..88bbace --- /dev/null +++ b/tests/AndroidTests/res/raw/install_loc_unspecified 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.ApplicationInfo; 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.storage.StorageResultCode; 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 @@ public class PackageManagerTests extends AndroidTestCase { 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 |