diff options
Diffstat (limited to 'core')
32 files changed, 534 insertions, 255 deletions
diff --git a/core/java/android/animation/DoubleEvaluator.java b/core/java/android/animation/DoubleEvaluator.java deleted file mode 100644 index e46eb37..0000000 --- a/core/java/android/animation/DoubleEvaluator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.animation; - -/** - * This evaluator can be used to perform type interpolation between <code>double</code> values. - */ -public class DoubleEvaluator implements TypeEvaluator { - /** - * This function returns the result of linearly interpolating the start and end values, with - * <code>fraction</code> representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>, - * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>, - * and <code>t</code> is <code>fraction</code>. - * - * @param fraction The fraction from the starting to the ending values - * @param startValue The start value; should be of type <code>double</code> or - * <code>Double</code> - * @param endValue The end value; should be of type <code>double</code> or - * <code>Double</code> - * @return A linear interpolation between the start and end values, given the - * <code>fraction</code> parameter. - */ - public Object evaluate(float fraction, Object startValue, Object endValue) { - double startDouble = ((Number) startValue).doubleValue(); - return startDouble + fraction * (((Number) endValue).doubleValue() - startDouble); - } -}
\ No newline at end of file diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java index 6fad4a68..4009f13 100644 --- a/core/java/android/animation/FloatKeyframeSet.java +++ b/core/java/android/animation/FloatKeyframeSet.java @@ -25,8 +25,8 @@ import java.util.ArrayList; * values between those keyframes for a given animation. The class internal to the animation * package because it is an implementation detail of how Keyframes are stored and used. * - * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclasses for - * int, long, and double, exists to speed up the getValue() method when there is no custom + * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for + * int, exists to speed up the getValue() method when there is no custom * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the * Object equivalents of these primitive types.</p> */ diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java index 14a4e3a..5629c5e 100644 --- a/core/java/android/animation/IntKeyframeSet.java +++ b/core/java/android/animation/IntKeyframeSet.java @@ -25,8 +25,8 @@ import java.util.ArrayList; * values between those keyframes for a given animation. The class internal to the animation * package because it is an implementation detail of how Keyframes are stored and used. * - * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclasses for - * float, long, and double, exists to speed up the getValue() method when there is no custom + * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for + * float, exists to speed up the getValue() method when there is no custom * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the * Object equivalents of these primitive types.</p> */ diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 3212cba..d038cd6 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -18,7 +18,6 @@ package android.animation; import android.util.Log; -import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.ArrayList; @@ -29,8 +28,6 @@ import java.util.ArrayList; * are then determined internally and the animation will call these functions as necessary to * animate the property. * - * <p class="note"><b>Note:</b> Instances of this class hold only a {@link WeakReference} - * to the target object.</p> * @see #setPropertyName(String) * */ @@ -38,7 +35,7 @@ public final class ObjectAnimator extends ValueAnimator { private static final boolean DBG = false; // The target object on which the property exists, set in the constructor - private WeakReference<Object> mTargetRef; + private Object mTarget; private String mPropertyName; @@ -105,9 +102,6 @@ public final class ObjectAnimator extends ValueAnimator { * @return Method the method associated with mPropertyName. */ private Method getPropertyFunction(String prefix, Class valueType) { - final Object target = mTargetRef == null ? null : mTargetRef.get(); - if (target == null) return null; - // TODO: faster implementation... Method returnVal = null; String firstLetter = mPropertyName.substring(0, 1); @@ -120,7 +114,7 @@ public final class ObjectAnimator extends ValueAnimator { args[0] = valueType; } try { - returnVal = target.getClass().getMethod(setterName, args); + returnVal = mTarget.getClass().getMethod(setterName, args); } catch (NoSuchMethodException e) { Log.e("ObjectAnimator", "Couldn't find setter/getter for property " + mPropertyName + ": " + e); @@ -140,14 +134,13 @@ public final class ObjectAnimator extends ValueAnimator { * A constructor that takes a single property name and set of values. This constructor is * used in the simple case of animating a single property. * - * @param target The object whose property is to be animated. It will be weakly referenced - * from the newly-created ObjectAnimator. This object should have a public method on it called - * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code> - * parameter. + * @param target The object whose property is to be animated. This object should + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. */ private ObjectAnimator(Object target, String propertyName) { - mTargetRef = new WeakReference<Object>(target); + mTarget = target; setPropertyName(propertyName); } @@ -159,10 +152,9 @@ public final class ObjectAnimator extends ValueAnimator { * from the target object and property being animated). Therefore, there should typically * be two or more values. * - * @param target The object whose property is to be animated. It will be weakly referenced - * from the newly-created ObjectAnimator. This object should have a public method on it called - * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code> - * parameter. + * @param target The object whose property is to be animated. This object should + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. * @param values A set of values that the animation will animate between over time. * @return A ValueAnimator object that is set up to animate between the given values. @@ -181,10 +173,9 @@ public final class ObjectAnimator extends ValueAnimator { * from the target object and property being animated). Therefore, there should typically * be two or more values. * - * @param target The object whose property is to be animated. It will be weakly referenced - * from the newly-created ObjectAnimator. This object should have a public method on it called - * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code> - * parameter. + * @param target The object whose property is to be animated. This object should + * have a public method on it called <code>setName()</code>, where <code>name</code> is + * the value of the <code>propertyName</code> parameter. * @param propertyName The name of the property being animated. * @param values A set of values that the animation will animate between over time. * @return A ValueAnimator object that is set up to animate between the given values. @@ -201,10 +192,10 @@ public final class ObjectAnimator extends ValueAnimator { * PropertyValuesHolder allows you to associate a set of animation values with a property * name. * - * @param target The object whose property is to be animated. It will be weakly referenced - * from the newly-created ObjectAnimator. This object should have public methods on it called - * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the - * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects. + * @param target The object whose property is to be animated. This object should + * have public methods on it called <code>setName()</code>, where <code>name</code> is + * the name of the property passed in as the <code>propertyName</code> parameter for + * each of the PropertyValuesHolder objects. * @param propertyName The name of the property being animated. * @param evaluator A TypeEvaluator that will be called on each animation frame to * provide the ncessry interpolation between the Object values to derive the animated @@ -227,10 +218,10 @@ public final class ObjectAnimator extends ValueAnimator { * PropertyValuesHolder allows you to associate a set of animation values with a property * name. * - * @param target The object whose property is to be animated. It will be weakly referenced - * from the newly-created ObjectAnimator. This object should have public methods on it called - * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the - * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects. + * @param target The object whose property is to be animated. This object should + * have public methods on it called <code>setName()</code>, where <code>name</code> is + * the name of the property passed in as the <code>propertyName</code> parameter for + * each of the PropertyValuesHolder objects. * @param values A set of PropertyValuesHolder objects whose values will be animated * between over time. * @return A ValueAnimator object that is set up to animate between the given values. @@ -238,7 +229,7 @@ public final class ObjectAnimator extends ValueAnimator { public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) { ObjectAnimator anim = new ObjectAnimator(); - anim.mTargetRef = new WeakReference<Object>(target); + anim.mTarget = target; anim.setValues(values); return anim; } @@ -279,8 +270,7 @@ public final class ObjectAnimator extends ValueAnimator { @Override public void start() { if (DBG) { - final Object target = mTargetRef == null ? null : mTargetRef.get(); - Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration()); + Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration()); for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvh = mValues[i]; ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes; @@ -307,14 +297,11 @@ public final class ObjectAnimator extends ValueAnimator { @Override void initAnimation() { if (!mInitialized) { - final Object target = mTargetRef == null ? null : mTargetRef.get(); - if (target == null) return; - // mValueType may change due to setter/getter setup; do this before calling super.init(), // which uses mValueType to set up the default type evaluator. int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setupSetterAndGetter(target); + mValues[i].setupSetterAndGetter(mTarget); } super.initAnimation(); } @@ -339,26 +326,23 @@ public final class ObjectAnimator extends ValueAnimator { /** * The target object whose property will be animated by this animation * - * @return The object being animated, or null if the object has been garbage collected. + * @return The object being animated */ public Object getTarget() { - return mTargetRef == null ? null : mTargetRef.get(); + return mTarget; } /** - * Sets the target object whose property will be animated by this animation. The target - * will be weakly referenced from this object. + * Sets the target object whose property will be animated by this animation * * @param target The object being animated */ @Override public void setTarget(Object target) { - final Object currentTarget = mTargetRef == null ? null : mTargetRef.get(); - - if (currentTarget != target) { - mTargetRef = new WeakReference<Object>(target); - if (currentTarget != null && target != null - && currentTarget.getClass() == target.getClass()) { + if (mTarget != target) { + final Object oldTarget = mTarget; + mTarget = target; + if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) { return; } // New target type should cause re-initialization prior to starting @@ -368,25 +352,19 @@ public final class ObjectAnimator extends ValueAnimator { @Override public void setupStartValues() { - final Object target = mTargetRef == null ? null : mTargetRef.get(); - if (target == null) return; - initAnimation(); int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setupStartValue(target); + mValues[i].setupStartValue(mTarget); } } @Override public void setupEndValues() { - final Object target = mTargetRef == null ? null : mTargetRef.get(); - if (target == null) return; - initAnimation(); int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setupEndValue(target); + mValues[i].setupEndValue(mTarget); } } @@ -405,13 +383,9 @@ public final class ObjectAnimator extends ValueAnimator { @Override void animateValue(float fraction) { super.animateValue(fraction); - - final Object target = mTargetRef == null ? null : mTargetRef.get(); - if (target == null) return; - int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setAnimatedValue(target); + mValues[i].setAnimatedValue(mTarget); } } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 0254924..0c30aad 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -67,10 +67,9 @@ public class PropertyValuesHolder implements Cloneable { KeyframeSet mKeyframeSet = null; - // type evaluators for the three primitive types handled by this implementation + // type evaluators for the primitive types handled by this implementation private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); - private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator(); // We try several different types when searching for appropriate setter/getter functions. // The caller may have supplied values in a type that does not match the setter/getter @@ -104,7 +103,7 @@ public class PropertyValuesHolder implements Cloneable { /** * The type evaluator used to calculate the animated values. This evaluator is determined * automatically based on the type of the start/end objects passed into the constructor, - * but the system only knows about the primitive types int, double, and float. Any other + * but the system only knows about the primitive types int and float. Any other * type will need to set the evaluator to a custom evaluator for that type. */ private TypeEvaluator mEvaluator; @@ -501,7 +500,7 @@ public class PropertyValuesHolder implements Cloneable { */ void init() { if (mEvaluator == null) { - // We already handle int, float, long, double automatically, but not their Object + // We already handle int and float automatically, but not their Object // equivalents mEvaluator = (mValueType == Integer.class) ? sIntEvaluator : (mValueType == Float.class) ? sFloatEvaluator : @@ -509,7 +508,7 @@ public class PropertyValuesHolder implements Cloneable { } if (mEvaluator != null) { // KeyframeSet knows how to evaluate the common types - only give it a custom - // evaulator if one has been set on this class + // evaluator if one has been set on this class mKeyframeSet.setEvaluator(mEvaluator); } } @@ -520,7 +519,7 @@ public class PropertyValuesHolder implements Cloneable { * desired. This may be important in cases where either the type of the values supplied * do not match the way that they should be interpolated between, or if the values * are of a custom type or one not currently understood by the animation system. Currently, - * only values of type float, double, and int (and their Object equivalents, Float, Double, + * only values of type float and int (and their Object equivalents: Float * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. * @param evaluator */ diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index f884473..5705057 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -143,10 +143,9 @@ public class ValueAnimator extends Animator { private static final TimeInterpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); - // type evaluators for the three primitive types handled by this implementation + // type evaluators for the primitive types handled by this implementation private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); - private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator(); /** * Used to indicate whether the animation is currently playing in reverse. This causes the @@ -858,7 +857,7 @@ public class ValueAnimator extends Animator { /** * The type evaluator to be used when calculating the animated values of this animation. - * The system will automatically assign a float, int, or double evaluator based on the type + * The system will automatically assign a float or int evaluator based on the type * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values * are not one of these primitive types, or if different evaluation is desired (such as is * necessary with int values that represent colors), a custom evaluator needs to be assigned. @@ -1193,4 +1192,16 @@ public class ValueAnimator extends Animator { public static int getCurrentAnimationsCount() { return sAnimations.get().size(); } + + /** + * Clear all animations on this thread, without canceling or ending them. + * This should be used with caution. + * + * @hide + */ + public static void clearAllAnimations() { + sAnimations.get().clear(); + sPendingAnimations.get().clear(); + sDelayedAnims.get().clear(); + } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 44db50f..4eae14b 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -77,6 +77,9 @@ public class ActivityManager { * This may be the same size as {@link #getMemoryClass()} on memory * constrained devices, or it may be significantly larger on devices with * a large amount of available RAM. + * + * <p>The is the size of the application's Dalvik heap if it has + * specified <code>android:largeHeap="true"</code> in its manifest. */ public int getLargeMemoryClass() { return staticGetLargeMemoryClass(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index cc94aa0..db046ef 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -45,7 +45,6 @@ import android.graphics.Canvas; import android.net.IConnectivityManager; import android.net.Proxy; import android.net.ProxyProperties; -import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; @@ -3463,6 +3462,10 @@ public final class ActivityThread { mInstrumentation = new Instrumentation(); } + if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { + // XXX bump up Dalvik's heap. + } + // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. Application app = data.info.makeApplication(data.restrictedBackupMode, null); @@ -3471,7 +3474,7 @@ public final class ActivityThread { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); - // For process that contain content providers, we want to + // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index bb0ed6a..2d95781 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -270,19 +270,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19; /** - * Value for {@link #flags}: this is true if the application has set - * its android:neverEncrypt to true, false otherwise. It is used to specify - * that this package specifically "opts-out" of a secured file system solution, - * and will always store its data in-the-clear. - * - * {@hide} + * Value for {@link #flags}: true when the application has requested a + * large heap for its processes. Corresponds to + * {@link android.R.styleable#AndroidManifestApplication_largeHeap + * android:largeHeap}. */ - public static final int FLAG_NEVER_ENCRYPT = 1<<30; + public static final int FLAG_LARGE_HEAP = 1<<20; /** * Value for {@link #flags}: Set to true if the application has been * installed using the forward lock option. * + * NOTE: DO NOT CHANGE THIS VALUE! It is saved in packages.xml. + * * {@hide} */ public static final int FLAG_FORWARD_LOCK = 1<<29; @@ -298,7 +298,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * * {@hide} */ - public static final int FLAG_CANT_SAVE_STATE = 1<<27; + public static final int FLAG_CANT_SAVE_STATE = 1<<28; /** * Flags associated with the application. Any combination of diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index b2937ba..7676258 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -389,11 +389,15 @@ public class PackageParser { XmlResourceParser parser = null; AssetManager assmgr = null; + Resources res = null; boolean assetError = true; try { assmgr = new AssetManager(); int cookie = assmgr.addAssetPath(mArchiveSourcePath); - if(cookie != 0) { + if (cookie != 0) { + res = new Resources(assmgr, metrics, null); + assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Build.VERSION.RESOURCES_SDK_INT); parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); assetError = false; } else { @@ -403,7 +407,7 @@ public class PackageParser { Log.w(TAG, "Unable to read AndroidManifest.xml of " + mArchiveSourcePath, e); } - if(assetError) { + if (assetError) { if (assmgr != null) assmgr.close(); mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; return null; @@ -413,7 +417,6 @@ public class PackageParser { Exception errorException = null; try { // XXXX todo: need to figure out correct configuration. - Resources res = new Resources(assmgr, metrics, null); pkg = parsePackage(res, parser, flags, errorText); } catch (Exception e) { errorException = e; @@ -593,6 +596,8 @@ public class PackageParser { AssetManager assmgr = null; try { assmgr = new AssetManager(); + assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Build.VERSION.RESOURCES_SDK_INT); int cookie = assmgr.addAssetPath(packageFilePath); parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); } catch (Exception e) { @@ -1574,9 +1579,9 @@ public class PackageParser { } if (sa.getBoolean( - com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt, + com.android.internal.R.styleable.AndroidManifestApplication_largeHeap, false)) { - ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT; + ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP; } String str; diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java index 9464321..28a2886 100755 --- a/core/java/android/content/pm/PackageStats.java +++ b/core/java/android/content/pm/PackageStats.java @@ -19,20 +19,44 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; -import java.util.Arrays; - /** * implementation of PackageStats associated with a * application package. */ public class PackageStats implements Parcelable { + /** Name of the package to which this stats applies. */ public String packageName; + + /** Size of the code (e.g., APK) */ public long codeSize; + + /** + * Size of the internal data size for the application. (e.g., + * /data/data/<app>) + */ public long dataSize; + + /** Size of cache used by the application. (e.g., /data/data/<app>/cache) */ public long cacheSize; - + + /** + * Size of the external data used by the application (e.g., + * <sdcard>/Android/data/<app>) + */ + public long externalDataSize; + + /** + * Size of the external cache used by the application (i.e., on the SD + * card). If this is a subdirectory of the data directory, this size will be + * subtracted out of the external data size. + */ + public long externalCacheSize; + + /** Size of the external media size used by the application. */ + public long externalMediaSize; + public static final Parcelable.Creator<PackageStats> CREATOR - = new Parcelable.Creator<PackageStats>() { + = new Parcelable.Creator<PackageStats>() { public PackageStats createFromParcel(Parcel in) { return new PackageStats(in); } @@ -41,29 +65,49 @@ public class PackageStats implements Parcelable { return new PackageStats[size]; } }; - + public String toString() { - return "PackageStats{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + packageName + "}"; + final StringBuilder sb = new StringBuilder("PackageStats{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" packageName="); + sb.append(packageName); + sb.append(",codeSize="); + sb.append(codeSize); + sb.append(",dataSize="); + sb.append(dataSize); + sb.append(",cacheSize="); + sb.append(cacheSize); + sb.append(",externalDataSize="); + sb.append(externalDataSize); + sb.append(",externalCacheSize="); + sb.append(externalCacheSize); + sb.append(",externalMediaSize="); + sb.append(externalMediaSize); + return sb.toString(); } - + public PackageStats(String pkgName) { packageName = pkgName; } - + public PackageStats(Parcel source) { packageName = source.readString(); codeSize = source.readLong(); dataSize = source.readLong(); cacheSize = source.readLong(); + externalDataSize = source.readLong(); + externalCacheSize = source.readLong(); + externalMediaSize = source.readLong(); } - + public PackageStats(PackageStats pStats) { packageName = pStats.packageName; codeSize = pStats.codeSize; dataSize = pStats.dataSize; cacheSize = pStats.cacheSize; + externalDataSize = pStats.externalDataSize; + externalCacheSize = pStats.externalCacheSize; + externalMediaSize = pStats.externalMediaSize; } public int describeContents() { @@ -75,5 +119,8 @@ public class PackageStats implements Parcelable { dest.writeLong(codeSize); dest.writeLong(dataSize); dest.writeLong(cacheSize); + dest.writeLong(externalDataSize); + dest.writeLong(externalCacheSize); + dest.writeLong(externalMediaSize); } } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index b40a226..29bb004 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -56,10 +56,6 @@ public class Resources { private static final int ID_OTHER = 0x01000004; - // Use the current SDK version code. If we are a development build, - // also allow the previous SDK version + 1. - private static final int sSdkVersion = Build.VERSION.SDK_INT - + ("REL".equals(Build.VERSION.CODENAME) ? 0 : 1); private static final Object mSync = new Object(); private static Resources mSystem = null; @@ -1427,14 +1423,14 @@ public class Resources { mConfiguration.touchscreen, (int)(mMetrics.density*160), mConfiguration.keyboard, keyboardHidden, mConfiguration.navigation, width, height, - mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion); + mConfiguration.screenLayout, mConfiguration.uiMode, + Build.VERSION.RESOURCES_SDK_INT); clearDrawableCache(mDrawableCache, configChanges); clearDrawableCache(mColorDrawableCache, configChanges); mColorStateListCache.clear(); - flushLayoutCache(); } synchronized (mSync) { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 9f7e31c..5a35eb0 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -16,9 +16,11 @@ package android.os; +import java.util.ArrayDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.LinkedBlockingQueue; @@ -151,8 +153,6 @@ public abstract class AsyncTask<Params, Progress, Result> { private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 1; - private static final BlockingQueue<Runnable> sWorkQueue = - new LinkedBlockingQueue<Runnable>(10); private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); @@ -162,8 +162,17 @@ public abstract class AsyncTask<Params, Progress, Result> { } }; - private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, - MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory); + private static final BlockingQueue<Runnable> sPoolWorkQueue = + new LinkedBlockingQueue<Runnable>(10); + + /** + * A {@link ThreadPoolExecutor} that can be used to execute tasks in parallel. + */ + public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR + = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, + TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); + + private static final SerialExecutor sSerialExecutor = new SerialExecutor(); private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; @@ -177,6 +186,32 @@ public abstract class AsyncTask<Params, Progress, Result> { private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); + private static class SerialExecutor implements Executor { + final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); + Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + THREAD_POOL_EXECUTOR.execute(mActive); + } + } + } + /** * Indicates the current status of the task. Each status will be set only once * during the lifetime of a task. @@ -433,7 +468,11 @@ public abstract class AsyncTask<Params, Progress, Result> { /** * Executes the task with the specified parameters. The task returns - * itself (this) so that the caller can keep a reference to it. + * itself (this) so that the caller can keep a reference to it. The tasks + * started by all invocations of this method in a given process are run + * sequentially. Call the executeOnExecutor(Executor,Params...) + * with a custom {@link Executor} to have finer grained control over how the + * tasks are run. * * This method must be invoked on the UI thread. * @@ -445,6 +484,26 @@ public abstract class AsyncTask<Params, Progress, Result> { * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. */ public final AsyncTask<Params, Progress, Result> execute(Params... params) { + return executeOnExecutor(sSerialExecutor, params); + } + + /** + * Executes the task with the specified parameters. The task returns + * itself (this) so that the caller can keep a reference to it. + * + * This method must be invoked on the UI thread. + * + * @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a + * convenient process-wide thread pool for tasks that are loosely coupled. + * @param params The parameters of the task. + * + * @return This instance of AsyncTask. + * + * @throws IllegalStateException If {@link #getStatus()} returns either + * {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}. + */ + public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, + Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: @@ -462,12 +521,20 @@ public abstract class AsyncTask<Params, Progress, Result> { onPreExecute(); mWorker.mParams = params; - sExecutor.execute(mFuture); + exec.execute(mFuture); return this; } /** + * Schedules the {@link Runnable} in serial with the other AsyncTasks that were started + * with {@link #execute}. + */ + public static void execute(Runnable runnable) { + sSerialExecutor.execute(runnable); + } + + /** * This method can be invoked from {@link #doInBackground} to * publish updates on the UI thread while the background computation is * still running. Each call to this method will trigger the execution of diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 6e50e97..af7b28b 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -100,6 +100,15 @@ public class Build { * a release build. */ public static final String CODENAME = getString("ro.build.version.codename"); + + /** + * The SDK version to use when accessing resources. + * Use the current SDK version code. If we are a development build, + * also allow the previous SDK version + 1. + * @hide + */ + public static final int RESOURCES_SDK_INT = SDK_INT + + ("REL".equals(CODENAME) ? 0 : 1); } /** diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index ad9e6863..e228537 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1780,7 +1780,7 @@ public final class ViewRoot extends Handler implements ViewParent, } void dispatchDetachedFromWindow() { - if (mView != null) { + if (mView != null && mView.mAttachInfo != null) { mView.dispatchDetachedFromWindow(); } diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java index 3d21048..472a335 100644 --- a/core/java/android/widget/ExpandableListView.java +++ b/core/java/android/widget/ExpandableListView.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -212,6 +211,9 @@ public class ExpandableListView extends ListView { .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0); mIndicatorRight = a .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0); + if (mIndicatorRight == 0) { + mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); + } mChildIndicatorLeft = a.getDimensionPixelSize( com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT); mChildIndicatorRight = a.getDimensionPixelSize( diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index d4ef044..dfa94c7 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -56,7 +56,7 @@ class FastScroller { private static final int[] DEFAULT_STATES = new int[0]; private static final int[] ATTRS = new int[] { - android.R.attr.textColorPrimary, + android.R.attr.fastScrollTextColor, android.R.attr.fastScrollThumbDrawable, android.R.attr.fastScrollTrackDrawable, android.R.attr.fastScrollPreviewBackgroundLeft, @@ -64,7 +64,7 @@ class FastScroller { android.R.attr.fastScrollOverlayPosition }; - private static final int PRIMARY_TEXT_COLOR = 0; + private static final int TEXT_COLOR = 0; private static final int THUMB_DRAWABLE = 1; private static final int TRACK_DRAWABLE = 2; private static final int PREVIEW_BACKGROUND_LEFT = 3; @@ -247,7 +247,7 @@ class FastScroller { mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(mOverlaySize / 2); - ColorStateList textColor = ta.getColorStateList(PRIMARY_TEXT_COLOR); + ColorStateList textColor = ta.getColorStateList(TEXT_COLOR); int textColorNormal = textColor.getDefaultColor(); mPaint.setColor(textColorNormal); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 2c96056..585dcf2 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -83,6 +83,7 @@ public class SearchView extends LinearLayout { private CursorAdapter mSuggestionsAdapter; private View mSearchButton; private View mSubmitButton; + private View mSubmitArea; private ImageView mCloseButton; private View mSearchEditFrame; private View mVoiceButton; @@ -92,6 +93,7 @@ public class SearchView extends LinearLayout { private boolean mQueryRefinement; private boolean mClearingFocus; private int mMaxWidth; + private boolean mVoiceButtonEnabled; private SearchableInfo mSearchable; @@ -187,6 +189,7 @@ public class SearchView extends LinearLayout { mQueryTextView.setSearchView(this); mSearchEditFrame = findViewById(R.id.search_edit_frame); + mSubmitArea = findViewById(R.id.submit_area); mSubmitButton = findViewById(R.id.search_go_btn); mCloseButton = (ImageView) findViewById(R.id.search_close_btn); mVoiceButton = findViewById(R.id.search_voice_btn); @@ -248,6 +251,8 @@ public class SearchView extends LinearLayout { if (mSearchable != null) { updateSearchAutoComplete(); } + // Cache the voice search capability + mVoiceButtonEnabled = hasVoiceSearch(); updateViewsVisibility(mIconifiedByDefault); } @@ -513,18 +518,55 @@ public class SearchView extends LinearLayout { mIconified = collapsed; // Visibility of views that are visible when collapsed final int visCollapsed = collapsed ? VISIBLE : GONE; - // Visibility of views that are visible when expanded - final int visExpanded = collapsed ? GONE : VISIBLE; // Is there text in the query final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); mSearchButton.setVisibility(visCollapsed); - mSubmitButton.setVisibility(mSubmitButtonEnabled && hasText ? visExpanded : GONE); - mSearchEditFrame.setVisibility(visExpanded); + updateSubmitButton(hasText); + mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); updateCloseButton(); updateVoiceButton(!hasText); + updateSubmitArea(); requestLayout(); - invalidate(); + } + + private boolean hasVoiceSearch() { + if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) { + Intent testIntent = null; + if (mSearchable.getVoiceSearchLaunchWebSearch()) { + testIntent = mVoiceWebSearchIntent; + } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { + testIntent = mVoiceAppSearchIntent; + } + if (testIntent != null) { + ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent, + PackageManager.MATCH_DEFAULT_ONLY); + return ri != null; + } + } + return false; + } + + private boolean isSubmitAreaEnabled() { + return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified(); + } + + private void updateSubmitButton(boolean hasText) { + mSubmitButton.setVisibility( + isSubmitAreaEnabled() ? (hasText ? VISIBLE : INVISIBLE) : GONE); + } + + private void updateSubmitArea() { + int visibility = GONE; + if (isSubmitAreaEnabled()) { + if (mSubmitButton.getVisibility() == VISIBLE + || mVoiceButton.getVisibility() == VISIBLE) { + visibility = VISIBLE; + } else { + visibility = INVISIBLE; + } + } + mSubmitArea.setVisibility(visibility); } private void updateCloseButton() { @@ -790,22 +832,14 @@ public class SearchView extends LinearLayout { * be visible - i.e., if the user has typed a query, remove the voice button. */ private void updateVoiceButton(boolean empty) { - int visibility = View.GONE; - if (mSearchable != null && mSearchable.getVoiceSearchEnabled() && empty - && !isIconified()) { - Intent testIntent = null; - if (mSearchable.getVoiceSearchLaunchWebSearch()) { - testIntent = mVoiceWebSearchIntent; - } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { - testIntent = mVoiceAppSearchIntent; - } - if (testIntent != null) { - ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent, - PackageManager.MATCH_DEFAULT_ONLY); - if (ri != null) { - visibility = View.VISIBLE; - } - } + // If the voice button is to be visible, show it + // Else, make it gone if the submit button is enabled, otherwise invisible to + // avoid losing the real-estate + int visibility = mSubmitButtonEnabled ? GONE : INVISIBLE; + + if (mVoiceButtonEnabled && !isIconified() && empty) { + visibility = VISIBLE; + mSubmitButton.setVisibility(GONE); } mVoiceButton.setVisibility(visibility); } @@ -825,12 +859,11 @@ public class SearchView extends LinearLayout { CharSequence text = mQueryTextView.getText(); boolean hasText = !TextUtils.isEmpty(text); if (isSubmitButtonEnabled()) { - mSubmitButton.setVisibility(hasText ? VISIBLE : GONE); - requestLayout(); - invalidate(); + updateSubmitButton(hasText); } updateVoiceButton(!hasText); updateCloseButton(); + updateSubmitArea(); if (mOnQueryChangeListener != null) { mOnQueryChangeListener.onQueryTextChanged(newText.toString()); } diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 264af71..2c10077 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -1,5 +1,4 @@ -/* - * Copyright (C) 2010 The Android Open Source Project +/* 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. @@ -209,22 +208,19 @@ public class StackView extends AdapterViewAnimator { } } - if (fromIndex == -1 && toIndex == NUM_ACTIVE_VIEWS -1) { + if (fromIndex == -1 && toIndex == getNumActiveViews() -1) { // Fade item in if (view.getAlpha() == 1) { view.setAlpha(0); } - view.setScaleX(1 - PERSPECTIVE_SCALE_FACTOR); - view.setScaleY(1 - PERSPECTIVE_SCALE_FACTOR); - view.setTranslationX(mPerspectiveShiftX); - view.setTranslationY(0); + transformViewAtIndex(toIndex, view, false); view.setVisibility(VISIBLE); alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f); alphaOa.setDuration(FADE_IN_ANIMATION_DURATION); if (oldAlphaOa != null) oldAlphaOa.cancel(); alphaOa.start(); - view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, + view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, new WeakReference<ObjectAnimator>(alphaOa)); } else if (fromIndex == 0 && toIndex == 1) { // Slide item in @@ -270,7 +266,7 @@ public class StackView extends AdapterViewAnimator { alphaOa.setDuration(STACK_RELAYOUT_DURATION); if (oldAlphaOa != null) oldAlphaOa.cancel(); alphaOa.start(); - view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, + view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, new WeakReference<ObjectAnimator>(alphaOa)); } @@ -284,16 +280,20 @@ public class StackView extends AdapterViewAnimator { final float maxPerspectiveShiftY = mPerspectiveShiftY; final float maxPerspectiveShiftX = mPerspectiveShiftX; - index = mMaxNumActiveViews - index - 1; - if (index == mMaxNumActiveViews - 1) index--; + if (mStackMode == ITEMS_SLIDE_DOWN) { + index = mMaxNumActiveViews - index - 1; + if (index == mMaxNumActiveViews - 1) index--; + } else { + index--; + if (index < 0) index++; + } float r = (index * 1.0f) / (mMaxNumActiveViews - 2); final float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r); - int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1; - float perspectiveTranslationY = -stackDirection * r * maxPerspectiveShiftY; - float scaleShiftCorrectionY = stackDirection * (1 - scale) * + float perspectiveTranslationY = r * maxPerspectiveShiftY; + float scaleShiftCorrectionY = (scale - 1) * (getMeasuredHeight() * (1 - PERSPECTIVE_SHIFT_FACTOR_Y) / 2.0f); final float transY = perspectiveTranslationY + scaleShiftCorrectionY; @@ -302,7 +302,7 @@ public class StackView extends AdapterViewAnimator { (getMeasuredWidth() * (1 - PERSPECTIVE_SHIFT_FACTOR_X) / 2.0f); final float transX = perspectiveTranslationX + scaleShiftCorrectionX; - // If this view is currently being animated for a certain position, we need to cancel + // If this view is currently being animated for a certain position, we need to cancel // this animation so as not to interfere with the new transformation. Object tag = view.getTag(com.android.internal.R.id.viewAnimation); if (tag instanceof WeakReference<?>) { @@ -515,11 +515,12 @@ public class StackView extends AdapterViewAnimator { private void beginGestureIfNeeded(float deltaY) { if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) { - int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; + final int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; cancelLongPress(); requestDisallowInterceptTouchEvent(true); if (mAdapter == null) return; + final int adapterCount = mAdapter.getCount(); int activeIndex; if (mStackMode == ITEMS_SLIDE_UP) { @@ -528,13 +529,20 @@ public class StackView extends AdapterViewAnimator { activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0; } + boolean endOfStack = mLoopViews && adapterCount == 1 && + ((mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_UP) || + (mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_DOWN)); + boolean beginningOfStack = mLoopViews && adapterCount == 1 && + ((mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_UP) || + (mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_DOWN)); + int stackMode; - if (mLoopViews) { + if (mLoopViews && !beginningOfStack && !endOfStack) { stackMode = StackSlider.NORMAL_MODE; - } else if (mCurrentWindowStartUnbounded + activeIndex == -1) { + } else if (mCurrentWindowStartUnbounded + activeIndex == -1 || beginningOfStack) { activeIndex++; stackMode = StackSlider.BEGINNING_OF_STACK_MODE; - } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) { + } else if (mCurrentWindowStartUnbounded + activeIndex == adapterCount - 1 || endOfStack) { stackMode = StackSlider.END_OF_STACK_MODE; } else { stackMode = StackSlider.NORMAL_MODE; @@ -989,6 +997,11 @@ public class StackView extends AdapterViewAnimator { @Override public void advance() { long timeSinceLastInteraction = System.currentTimeMillis() - mLastInteractionTime; + + if (mAdapter == null) return; + final int adapterCount = mAdapter.getCount(); + if (adapterCount == 1 && mLoopViews) return; + if (mSwipeGestureType == GESTURE_NONE && timeSinceLastInteraction > MIN_TIME_BETWEEN_INTERACTION_AND_AUTOADVANCE) { showNext(); @@ -1266,4 +1279,4 @@ public class StackView extends AdapterViewAnimator { mask.recycle(); } } -} +}
\ No newline at end of file diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index 8e491e9..8825c02 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -20,7 +20,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -44,6 +43,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo private MenuBuilder mMenu; private int mMaxItems; + private int mWidthLimit; private boolean mReserveOverflow; private OverflowMenuButton mOverflowButton; private MenuPopupHelper mOverflowPopup; @@ -91,6 +91,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo final int screen = res.getConfiguration().screenLayout; mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; + mWidthLimit = res.getDisplayMetrics().widthPixels / 2; TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme); mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical); @@ -108,6 +109,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; mMaxItems = getMaxActionButtons(); + mWidthLimit = getResources().getDisplayMetrics().widthPixels / 2; if (mMenu != null) { mMenu.setMaxActionItems(mMaxItems); updateChildren(false); @@ -172,6 +174,19 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } public void initialize(MenuBuilder menu, int menuType) { + int width = mWidthLimit; + if (mReserveOverflow) { + if (mOverflowButton == null) { + OverflowMenuButton button = new OverflowMenuButton(mContext); + mOverflowButton = button; + } + final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + mOverflowButton.measure(spec, spec); + width -= mOverflowButton.getMeasuredWidth(); + } + + menu.setActionWidthLimit(width); + menu.setMaxActionItems(mMaxItems); mMenu = menu; updateChildren(true); @@ -219,9 +234,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo if (itemCount > 0) { addView(makeDividerView(), makeDividerLayoutParams()); } - OverflowMenuButton button = new OverflowMenuButton(mContext); - addView(button); - mOverflowButton = button; + if (mOverflowButton == null) { + OverflowMenuButton button = new OverflowMenuButton(mContext); + mOverflowButton = button; + } + addView(mOverflowButton); } else { mOverflowButton = null; } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 830c2c1..588b10c 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -27,9 +27,10 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; -import android.util.Log; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.TypedValue; +import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextThemeWrapper; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -38,8 +39,8 @@ import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; +import android.view.View.MeasureSpec; import android.view.ViewGroup; -import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView; import android.widget.BaseAdapter; @@ -164,6 +165,10 @@ public class MenuBuilder implements Menu { */ private int mMaxActionItems; /** + * The total width limit in pixels for all action items within a menu + */ + private int mActionWidthLimit; + /** * Whether or not the items (or any one item's action state) has changed since it was * last fetched. */ @@ -208,6 +213,11 @@ public class MenuBuilder implements Menu { private boolean mOptionalIconsVisible = false; + private ViewGroup mMeasureActionButtonParent; + + // Group IDs that have been added as actions - used temporarily, allocated here for reuse. + private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray(); + private static int getAlertDialogTheme(Context context) { TypedValue outValue = new TypedValue(); context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme, @@ -1035,6 +1045,44 @@ public class MenuBuilder implements Menu { return mVisibleItems; } + /** + * @return A fake action button parent view for obtaining child views. + */ + private ViewGroup getMeasureActionButtonParent() { + if (mMeasureActionButtonParent == null) { + mMeasureActionButtonParent = (ViewGroup) mMenuTypes[TYPE_ACTION_BUTTON].getInflater() + .inflate(LAYOUT_RES_FOR_TYPE[TYPE_ACTION_BUTTON], null, false); + } + return mMeasureActionButtonParent; + } + + /** + * This method determines which menu items get to be 'action items' that will appear + * in an action bar and which items should be 'overflow items' in a secondary menu. + * The rules are as follows: + * + * <p>Items are considered for inclusion in the order specified within the menu. + * There is a limit of mMaxActionItems as a total count, optionally including the overflow + * menu button itself. This is a soft limit; if an item shares a group ID with an item + * previously included as an action item, the new item will stay with its group and become + * an action item itself even if it breaks the max item count limit. This is done to + * limit the conceptual complexity of the items presented within an action bar. Only a few + * unrelated concepts should be presented to the user in this space, and groups are treated + * as a single concept. + * + * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This + * limit may be broken by a single item that exceeds the remaining space, but no further + * items may be added. If an item that is part of a group cannot fit within the remaining + * measured width, the entire group will be demoted to overflow. This is done to ensure room + * for navigation and other affordances in the action bar as well as reduce general UI clutter. + * + * <p>The space freed by demoting a full group cannot be consumed by future menu items. + * Once items begin to overflow, all future items become overflow items as well. This is + * to avoid inadvertent reordering that may break the app's intended design. + * + * @param reserveActionOverflow true if an overflow button should consume one space + * in the available item count + */ private void flagActionItems(boolean reserveActionOverflow) { if (reserveActionOverflow != mReserveActionOverflow) { mReserveActionOverflow = reserveActionOverflow; @@ -1048,9 +1096,13 @@ public class MenuBuilder implements Menu { final ArrayList<MenuItemImpl> visibleItems = getVisibleItems(); final int itemsSize = visibleItems.size(); int maxActions = mMaxActionItems; + int widthLimit = mActionWidthLimit; + final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final ViewGroup parent = getMeasureActionButtonParent(); int requiredItems = 0; int requestedItems = 0; + int firstActionWidth = 0; boolean hasOverflow = false; for (int i = 0; i < itemsSize; i++) { MenuItemImpl item = visibleItems.get(i); @@ -1070,12 +1122,68 @@ public class MenuBuilder implements Menu { } maxActions -= requiredItems; + final SparseBooleanArray seenGroups = mActionButtonGroups; + seenGroups.clear(); + // Flag as many more requested items as will fit. for (int i = 0; i < itemsSize; i++) { MenuItemImpl item = visibleItems.get(i); - if (item.requestsActionButton()) { - item.setIsActionButton(maxActions > 0); + + if (item.requiresActionButton()) { + View v = item.getActionView(); + if (v == null) { + v = item.getItemView(TYPE_ACTION_BUTTON, parent); + } + v.measure(querySpec, querySpec); + final int measuredWidth = v.getMeasuredWidth(); + widthLimit -= measuredWidth; + if (firstActionWidth == 0) { + firstActionWidth = measuredWidth; + } + final int groupId = item.getGroupId(); + if (groupId != 0) { + seenGroups.put(groupId, true); + } + } else if (item.requestsActionButton()) { + // Items in a group with other items that already have an action slot + // can break the max actions rule, but not the width limit. + final int groupId = item.getGroupId(); + final boolean inGroup = seenGroups.get(groupId); + boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0; maxActions--; + + if (isAction) { + View v = item.getActionView(); + if (v == null) { + v = item.getItemView(TYPE_ACTION_BUTTON, parent); + } + v.measure(querySpec, querySpec); + final int measuredWidth = v.getMeasuredWidth(); + widthLimit -= measuredWidth; + if (firstActionWidth == 0) { + firstActionWidth = measuredWidth; + } + + // Did this push the entire first item past halfway? + if (widthLimit + firstActionWidth <= 0) { + isAction = false; + } + } + + if (isAction && groupId != 0) { + seenGroups.put(groupId, true); + } else if (inGroup) { + // We broke the width limit. Demote the whole group, they all overflow now. + seenGroups.put(groupId, false); + for (int j = 0; j < i; j++) { + MenuItemImpl areYouMyGroupie = visibleItems.get(j); + if (areYouMyGroupie.getGroupId() == groupId) { + areYouMyGroupie.setIsActionButton(false); + } + } + } + + item.setIsActionButton(isAction); } } @@ -1108,6 +1216,11 @@ public class MenuBuilder implements Menu { mIsActionItemsStale = true; } + void setActionWidthLimit(int widthLimit) { + mActionWidthLimit = widthLimit; + mIsActionItemsStale = true; + } + public void clearHeader() { mHeaderIcon = null; mHeaderTitle = null; diff --git a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml index 8a46546..4f5beff 100644 --- a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml +++ b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml @@ -27,12 +27,11 @@ android:layout_height="0px" android:layout_weight="1" android:layout_above="@+id/emergencyCall"> - <RelativeLayout + <RelativeLayout android:layout_width="match_parent" - android:layout_height="match_parent" - > - - <TextView + android:layout_height="match_parent"> + + <TextView android:id="@+id/topHeader" android:layout_width="match_parent" android:layout_height="64dip" @@ -43,7 +42,7 @@ android:drawableLeft="@drawable/ic_lock_idle_lock" android:drawablePadding="5dip" /> - + <!-- spacer below header --> <View android:id="@+id/spacerTop" @@ -51,7 +50,7 @@ android:layout_height="1dip" android:layout_below="@id/topHeader" android:background="@drawable/divider_horizontal_dark"/> - + <TextView android:id="@+id/instructions" android:layout_width="match_parent" @@ -62,7 +61,7 @@ android:textAppearance="?android:attr/textAppearanceSmall" android:text="@android:string/lockscreen_glogin_instructions" /> - + <EditText android:id="@+id/login" android:layout_width="match_parent" @@ -74,7 +73,7 @@ android:hint="@android:string/lockscreen_glogin_username_hint" android:inputType="textEmailAddress" /> - + <EditText android:id="@+id/password" android:layout_width="match_parent" @@ -88,11 +87,11 @@ android:nextFocusRight="@+id/ok" android:nextFocusDown="@+id/ok" /> - + <!-- ok below password, aligned to right of screen --> <Button android:id="@+id/ok" - android:layout_width="85dip" + android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/password" android:layout_marginTop="7dip" @@ -100,10 +99,10 @@ android:layout_alignParentRight="true" android:text="@android:string/lockscreen_glogin_submit_button" /> - + </RelativeLayout> </ScrollView> - + <!-- spacer above emergency call --> <View android:layout_width="match_parent" @@ -121,6 +120,7 @@ android:drawableLeft="@drawable/ic_emergency" android:drawablePadding="8dip" android:text="@android:string/lockscreen_emergency_call" + android:visibility="gone" /> </LinearLayout> diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml index 1002c4b..57eb9c7 100644 --- a/core/res/res/layout/alert_dialog_holo.xml +++ b/core/res/res/layout/alert_dialog_holo.xml @@ -27,7 +27,6 @@ <LinearLayout android:id="@+id/topPanel" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="64dip" android:orientation="vertical"> <ImageView android:id="@+id/titleDividerTop" android:layout_width="match_parent" @@ -42,9 +41,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:gravity="center_vertical" - android:layout_marginTop="8dip" - android:layout_marginBottom="8dip" + android:gravity="center_vertical|left" + android:minHeight="60dip" android:layout_marginLeft="32dip" android:layout_marginRight="32dip"> <ImageView android:id="@+id/icon" diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml index 46d0341..0a7cd3c 100644 --- a/core/res/res/layout/search_view.xml +++ b/core/res/res/layout/search_view.xml @@ -100,8 +100,8 @@ android:id="@+id/search_close_btn" android:layout_width="wrap_content" android:layout_height="match_parent" - android:paddingLeft="4dip" - android:paddingRight="4dip" + android:paddingLeft="8dip" + android:paddingRight="8dip" android:layout_gravity="center_vertical" android:background="?android:attr/selectableItemBackground" android:src="?android:attr/searchViewCloseIcon" @@ -111,26 +111,34 @@ </LinearLayout> - <ImageView - android:id="@+id/search_go_btn" + <LinearLayout + android:id="@+id/submit_area" + android:orientation="horizontal" android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:paddingLeft="4dip" - android:paddingRight="4dip" - android:background="?android:attr/selectableItemBackground" - android:src="?android:attr/searchViewGoIcon" - /> + android:layout_height="match_parent"> - <ImageView - android:id="@+id/search_voice_btn" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:paddingLeft="4dip" - android:paddingRight="4dip" - android:src="?android:attr/searchViewVoiceIcon" - android:background="?android:attr/selectableItemBackground" - android:visibility="gone" - /> + <ImageView + android:id="@+id/search_go_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:background="?android:attr/selectableItemBackground" + android:src="?android:attr/searchViewGoIcon" + android:visibility="gone" + /> + + <ImageView + android:id="@+id/search_voice_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:src="?android:attr/searchViewVoiceIcon" + android:background="?android:attr/selectableItemBackground" + android:visibility="gone" + /> + </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/simple_dropdown_item_1line.xml b/core/res/res/layout/simple_dropdown_item_1line.xml index 18e7b88..3ec930c 100644 --- a/core/res/res/layout/simple_dropdown_item_1line.xml +++ b/core/res/res/layout/simple_dropdown_item_1line.xml @@ -20,7 +20,7 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceLargeInverse" + android:textAppearance="?android:attr/textAppearanceLargePopupMenu" android:singleLine="true" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" diff --git a/core/res/res/layout/simple_dropdown_item_2line.xml b/core/res/res/layout/simple_dropdown_item_2line.xml index 903adb0..d6f911a 100644 --- a/core/res/res/layout/simple_dropdown_item_2line.xml +++ b/core/res/res/layout/simple_dropdown_item_2line.xml @@ -37,7 +37,7 @@ <TextView android:id="@android:id/text1" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceLargeInverse" + android:textAppearance="?android:attr/textAppearanceLargePopupMenu" android:singleLine="true" android:layout_width="match_parent" android:layout_height="wrap_content" /> @@ -45,7 +45,7 @@ <TextView android:id="@android:id/text2" style="?android:attr/dropDownItemStyle" - android:textAppearance="?android:attr/textAppearanceSmallInverse" + android:textAppearance="?android:attr/textAppearanceSmallPopupMenu" android:textColor="#323232" android:singleLine="true" android:layout_width="match_parent" diff --git a/core/res/res/layout/textview_hint.xml b/core/res/res/layout/textview_hint.xml index 4978be5..20b08bf 100644 --- a/core/res/res/layout/textview_hint.xml +++ b/core/res/res/layout/textview_hint.xml @@ -18,5 +18,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/popup_inline_error" - android:textAppearance="?android:attr/textAppearanceSmallInverse" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="@color/primary_text_light" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 02855b5..19e2b8d 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -544,6 +544,9 @@ <enum name="floating" value="0" /> <enum name="atThumb" value="1" /> </attr> + <!-- Text color for the fast scroll index overlay. Make sure it + plays nicely with fastScrollPreviewBackground[Left|Right]. --> + <attr name="fastScrollTextColor" format="color" /> <!-- =================== --> <!-- Action bar styles --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 5ff6212..a9a7e4a 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -778,6 +778,13 @@ <attr name="restoreNeedsApplication" /> <attr name="restoreAnyVersion" /> <attr name="neverEncrypt" /> + <!-- Request that your application's processes be created with + a large Dalvik heap. This applies to <em>all</em> processes + created for the application. It only applies to the first + application loaded into a process; if using a sharedUserId + to allow multiple applications to use a process, they all must + use this option consistently or will get unpredictable results. --> + <attr name="largeHeap" format="boolean" /> <!-- Declare that this applicationn can't participate in the normal state save/restore mechanism. Since it is not able to save and restore its state on demand, diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index e5b6563..a51a26d 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -68,4 +68,10 @@ is along the minor axis (that is the screen is portrait). This may be either a fraction or a dimension. --> <item type="dimen" name="dialog_min_width_minor">95%</item> + + <!-- The width of the big icons in notifications. --> + <dimen name="notification_large_icon_width">60dp</dimen> + <!-- The width of the big icons in notifications. --> + <dimen name="notification_large_icon_height">60dp</dimen> + </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 9b88b01..3ad29c4 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1425,6 +1425,8 @@ <public type="attr" name="windowMinWidthMajor" /> <public type="attr" name="windowMinWidthMinor" /> <public type="attr" name="queryHint" /> + <public type="attr" name="fastScrollTextColor" /> + <public type="attr" name="largeHeap" /> <!-- A simple fade-in animation. --> <public type="animator" name="fade_in" id="0x010b0000" /> @@ -1469,6 +1471,8 @@ <public type="dimen" name="dialog_min_width_major" /> <public type="dimen" name="dialog_min_width_minor" /> + <public type="dimen" name="notification_large_icon_width" /> + <public type="dimen" name="notification_large_icon_height" /> <!-- Standard content view for a {@link android.app.ListFragment}. If you are implementing a subclass of ListFragment with your diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 971719e..744d0d8 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -114,7 +114,7 @@ ?android:attr/expandableListPreferredItemPaddingLeft</item> <item name="expandableListPreferredItemIndicatorLeft">3dip</item> - <item name="expandableListPreferredItemIndicatorRight">33dip</item> + <item name="expandableListPreferredItemIndicatorRight">0dip</item> <item name="expandableListPreferredChildIndicatorLeft"> ?android:attr/expandableListPreferredItemIndicatorLeft</item> <item name="expandableListPreferredChildIndicatorRight"> @@ -294,6 +294,7 @@ <item name="fastScrollPreviewBackgroundRight">@android:drawable/menu_submenu_background</item> <item name="fastScrollPreviewBackgroundLeft">@android:drawable/menu_submenu_background</item> <item name="fastScrollOverlayPosition">floating</item> + <item name="fastScrollTextColor">@android:color/primary_text_dark</item> </style> @@ -815,7 +816,7 @@ ?android:attr/expandableListPreferredItemPaddingLeft</item> <item name="expandableListPreferredItemIndicatorLeft">3dip</item> - <item name="expandableListPreferredItemIndicatorRight">33dip</item> + <item name="expandableListPreferredItemIndicatorRight">0dip</item> <item name="expandableListPreferredChildIndicatorLeft"> ?android:attr/expandableListPreferredItemIndicatorLeft</item> <item name="expandableListPreferredChildIndicatorRight"> @@ -1074,7 +1075,7 @@ ?android:attr/expandableListPreferredItemPaddingLeft</item> <item name="expandableListPreferredItemIndicatorLeft">3dip</item> - <item name="expandableListPreferredItemIndicatorRight">33dip</item> + <item name="expandableListPreferredItemIndicatorRight">0dip</item> <item name="expandableListPreferredChildIndicatorLeft"> ?android:attr/expandableListPreferredItemIndicatorLeft</item> <item name="expandableListPreferredChildIndicatorRight"> @@ -1106,6 +1107,7 @@ <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item> <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item> <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item> + <item name="alertDialogCenterButtons">false</item> <item name="alertDialogTheme">@android:style/Theme.Holo.Light.Dialog.Alert</item> <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_light</item> |