Merge "making slide unlock on tablet have a larger radius" into ics-mr1
diff --git a/api/current.txt b/api/current.txt
index fe0699c..b180f7d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14399,6 +14399,7 @@
field public static final int HONEYCOMB_MR1 = 12; // 0xc
field public static final int HONEYCOMB_MR2 = 13; // 0xd
field public static final int ICE_CREAM_SANDWICH = 14; // 0xe
+ field public static final int ICE_CREAM_SANDWICH_MR1 = 15; // 0xf
}
public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
@@ -22849,6 +22850,7 @@
method public void buildDrawingCache();
method public void buildDrawingCache(boolean);
method public void buildLayer();
+ method public boolean callOnClick();
method public boolean canScrollHorizontally(int);
method public boolean canScrollVertically(int);
method public void cancelLongPress();
@@ -23000,6 +23002,7 @@
method public float getY();
method public boolean hasFocus();
method public boolean hasFocusable();
+ method public boolean hasOnClickListeners();
method public boolean hasWindowFocus();
method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
method protected void initializeFadingEdge(android.content.res.TypedArray);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8afe9bf..00fe953 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2769,7 +2769,9 @@
if (info != null) {
try {
// First create a thumbnail for the activity...
- info.thumbnail = createThumbnailBitmap(r);
+ // For now, don't create the thumbnail here; we are
+ // doing that by doing a screen snapshot.
+ info.thumbnail = null; //createThumbnailBitmap(r);
info.description = r.activity.onCreateDescription();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 7a69419..f1ce2bb 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -28,6 +28,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextMenu;
@@ -77,6 +78,7 @@
*/
public class Dialog implements DialogInterface, Window.Callback,
KeyEvent.Callback, OnCreateContextMenuListener {
+ private static final String TAG = "Dialog";
private Activity mOwnerActivity;
final Context mContext;
@@ -110,6 +112,8 @@
private Handler mListenersHandler;
+ private ActionMode mActionMode;
+
private final Runnable mDismissAction = new Runnable() {
public void run() {
dismissDialog();
@@ -298,18 +302,27 @@
if (Thread.currentThread() != mUiThread) {
mHandler.post(mDismissAction);
} else {
+ mHandler.removeCallbacks(mDismissAction);
mDismissAction.run();
}
}
- private void dismissDialog() {
+ void dismissDialog() {
if (mDecor == null || !mShowing) {
return;
}
+ if (mWindow.isDestroyed()) {
+ Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
+ return;
+ }
+
try {
mWindowManager.removeView(mDecor);
} finally {
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
mDecor = null;
mWindow.closeAllPanels();
onStop();
@@ -952,10 +965,26 @@
return null;
}
+ /**
+ * {@inheritDoc}
+ *
+ * Note that if you override this method you should always call through
+ * to the superclass implementation by calling super.onActionModeStarted(mode).
+ */
public void onActionModeStarted(ActionMode mode) {
+ mActionMode = mode;
}
+ /**
+ * {@inheritDoc}
+ *
+ * Note that if you override this method you should always call through
+ * to the superclass implementation by calling super.onActionModeFinished(mode).
+ */
public void onActionModeFinished(ActionMode mode) {
+ if (mode == mActionMode) {
+ mActionMode = null;
+ }
}
/**
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 17a882d..7d034940 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -277,7 +277,7 @@
public static final int HONEYCOMB_MR2 = 13;
/**
- * Android 4.0.
+ * October 2011: Android 4.0.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -309,6 +309,11 @@
* </ul>
*/
public static final int ICE_CREAM_SANDWICH = 14;
+
+ /**
+ * Android 4.1.
+ */
+ public static final int ICE_CREAM_SANDWICH_MR1 = 15;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fea79d5..62e6ebd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1548,7 +1548,7 @@
int mID = NO_ID;
/**
- * The stable ID of this view for accessibility porposes.
+ * The stable ID of this view for accessibility purposes.
*/
int mAccessibilityViewId = NO_ID;
@@ -2317,55 +2317,59 @@
private int mBackgroundResource;
private boolean mBackgroundSizeChanged;
- /**
- * Listener used to dispatch focus change events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnFocusChangeListener mOnFocusChangeListener;
+ static class ListenerInfo {
+ /**
+ * Listener used to dispatch focus change events.
+ * This field should be made private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ protected OnFocusChangeListener mOnFocusChangeListener;
- /**
- * Listeners for layout change events.
- */
- private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
+ /**
+ * Listeners for layout change events.
+ */
+ private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
- /**
- * Listeners for attach events.
- */
- private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
+ /**
+ * Listeners for attach events.
+ */
+ private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
- /**
- * Listener used to dispatch click events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnClickListener mOnClickListener;
+ /**
+ * Listener used to dispatch click events.
+ * This field should be made private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ public OnClickListener mOnClickListener;
- /**
- * Listener used to dispatch long click events.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnLongClickListener mOnLongClickListener;
+ /**
+ * Listener used to dispatch long click events.
+ * This field should be made private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ protected OnLongClickListener mOnLongClickListener;
- /**
- * Listener used to build the context menu.
- * This field should be made private, so it is hidden from the SDK.
- * {@hide}
- */
- protected OnCreateContextMenuListener mOnCreateContextMenuListener;
+ /**
+ * Listener used to build the context menu.
+ * This field should be made private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ protected OnCreateContextMenuListener mOnCreateContextMenuListener;
- private OnKeyListener mOnKeyListener;
+ private OnKeyListener mOnKeyListener;
- private OnTouchListener mOnTouchListener;
+ private OnTouchListener mOnTouchListener;
- private OnHoverListener mOnHoverListener;
+ private OnHoverListener mOnHoverListener;
- private OnGenericMotionListener mOnGenericMotionListener;
+ private OnGenericMotionListener mOnGenericMotionListener;
- private OnDragListener mOnDragListener;
+ private OnDragListener mOnDragListener;
- private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
+ private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
+ }
+
+ ListenerInfo mListenerInfo;
/**
* The application environment this view lives in.
@@ -3346,13 +3350,21 @@
return mVerticalScrollbarPosition;
}
+ ListenerInfo getListenerInfo() {
+ if (mListenerInfo != null) {
+ return mListenerInfo;
+ }
+ mListenerInfo = new ListenerInfo();
+ return mListenerInfo;
+ }
+
/**
* Register a callback to be invoked when focus of this view changed.
*
* @param l The callback that will run.
*/
public void setOnFocusChangeListener(OnFocusChangeListener l) {
- mOnFocusChangeListener = l;
+ getListenerInfo().mOnFocusChangeListener = l;
}
/**
@@ -3362,11 +3374,12 @@
* @param listener The listener that will be called when layout bounds change.
*/
public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
- if (mOnLayoutChangeListeners == null) {
- mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
+ ListenerInfo li = getListenerInfo();
+ if (li.mOnLayoutChangeListeners == null) {
+ li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
}
- if (!mOnLayoutChangeListeners.contains(listener)) {
- mOnLayoutChangeListeners.add(listener);
+ if (!li.mOnLayoutChangeListeners.contains(listener)) {
+ li.mOnLayoutChangeListeners.add(listener);
}
}
@@ -3376,10 +3389,11 @@
* @param listener The listener for layout bounds change.
*/
public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
- if (mOnLayoutChangeListeners == null) {
+ ListenerInfo li = mListenerInfo;
+ if (li == null || li.mOnLayoutChangeListeners == null) {
return;
}
- mOnLayoutChangeListeners.remove(listener);
+ li.mOnLayoutChangeListeners.remove(listener);
}
/**
@@ -3393,10 +3407,12 @@
* @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
*/
public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
- if (mOnAttachStateChangeListeners == null) {
- mOnAttachStateChangeListeners = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
+ ListenerInfo li = getListenerInfo();
+ if (li.mOnAttachStateChangeListeners == null) {
+ li.mOnAttachStateChangeListeners
+ = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
}
- mOnAttachStateChangeListeners.add(listener);
+ li.mOnAttachStateChangeListeners.add(listener);
}
/**
@@ -3407,10 +3423,11 @@
* @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
*/
public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
- if (mOnAttachStateChangeListeners == null) {
+ ListenerInfo li = mListenerInfo;
+ if (li == null || li.mOnAttachStateChangeListeners == null) {
return;
}
- mOnAttachStateChangeListeners.remove(listener);
+ li.mOnAttachStateChangeListeners.remove(listener);
}
/**
@@ -3419,7 +3436,8 @@
* @return The callback, or null if one is not registered.
*/
public OnFocusChangeListener getOnFocusChangeListener() {
- return mOnFocusChangeListener;
+ ListenerInfo li = mListenerInfo;
+ return li != null ? li.mOnFocusChangeListener : null;
}
/**
@@ -3434,7 +3452,16 @@
if (!isClickable()) {
setClickable(true);
}
- mOnClickListener = l;
+ getListenerInfo().mOnClickListener = l;
+ }
+
+ /**
+ * Return whether this view has an attached OnClickListener. Returns
+ * true if there is a listener, false if there is none.
+ */
+ public boolean hasOnClickListeners() {
+ ListenerInfo li = mListenerInfo;
+ return (li != null && li.mOnClickListener != null);
}
/**
@@ -3449,7 +3476,7 @@
if (!isLongClickable()) {
setLongClickable(true);
}
- mOnLongClickListener = l;
+ getListenerInfo().mOnLongClickListener = l;
}
/**
@@ -3463,11 +3490,13 @@
if (!isLongClickable()) {
setLongClickable(true);
}
- mOnCreateContextMenuListener = l;
+ getListenerInfo().mOnCreateContextMenuListener = l;
}
/**
- * Call this view's OnClickListener, if it is defined.
+ * Call this view's OnClickListener, if it is defined. Performs all normal
+ * actions associated with clicking: reporting accessibility event, playing
+ * a sound, etc.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
@@ -3475,9 +3504,10 @@
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
- if (mOnClickListener != null) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
- mOnClickListener.onClick(this);
+ li.mOnClickListener.onClick(this);
return true;
}
@@ -3485,6 +3515,23 @@
}
/**
+ * Directly call any attached OnClickListener. Unlike {@link #performClick()},
+ * this only calls the listener, and does not do any associated clicking
+ * actions like reporting an accessibility event.
+ *
+ * @return True there was an assigned OnClickListener that was called, false
+ * otherwise is returned.
+ */
+ public boolean callOnClick() {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnClickListener != null) {
+ li.mOnClickListener.onClick(this);
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
* OnLongClickListener did not consume the event.
*
@@ -3494,8 +3541,9 @@
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
boolean handled = false;
- if (mOnLongClickListener != null) {
- handled = mOnLongClickListener.onLongClick(View.this);
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnLongClickListener != null) {
+ handled = li.mOnLongClickListener.onLongClick(View.this);
}
if (!handled) {
handled = showContextMenu();
@@ -3563,7 +3611,7 @@
* @param l the key listener to attach to this view
*/
public void setOnKeyListener(OnKeyListener l) {
- mOnKeyListener = l;
+ getListenerInfo().mOnKeyListener = l;
}
/**
@@ -3571,7 +3619,7 @@
* @param l the touch listener to attach to this view
*/
public void setOnTouchListener(OnTouchListener l) {
- mOnTouchListener = l;
+ getListenerInfo().mOnTouchListener = l;
}
/**
@@ -3579,7 +3627,7 @@
* @param l the generic motion listener to attach to this view
*/
public void setOnGenericMotionListener(OnGenericMotionListener l) {
- mOnGenericMotionListener = l;
+ getListenerInfo().mOnGenericMotionListener = l;
}
/**
@@ -3587,7 +3635,7 @@
* @param l the hover listener to attach to this view
*/
public void setOnHoverListener(OnHoverListener l) {
- mOnHoverListener = l;
+ getListenerInfo().mOnHoverListener = l;
}
/**
@@ -3598,7 +3646,7 @@
* @param l An implementation of {@link android.view.View.OnDragListener}.
*/
public void setOnDragListener(OnDragListener l) {
- mOnDragListener = l;
+ getListenerInfo().mOnDragListener = l;
}
/**
@@ -3804,8 +3852,9 @@
}
invalidate(true);
- if (mOnFocusChangeListener != null) {
- mOnFocusChangeListener.onFocusChange(this, gainFocus);
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnFocusChangeListener != null) {
+ li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
}
if (mAttachInfo != null) {
@@ -4122,10 +4171,12 @@
bounds.offset(locationOnScreen[0], locationOnScreen[1]);
info.setBoundsInScreen(bounds);
- ViewParent parent = getParent();
- if (parent instanceof View) {
- View parentView = (View) parent;
- info.setParent(parentView);
+ if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+ ViewParent parent = getParent();
+ if (parent instanceof View) {
+ View parentView = (View) parent;
+ info.setParent(parentView);
+ }
}
info.setPackageName(mContext.getPackageName());
@@ -5439,8 +5490,9 @@
// Give any attached key listener a first crack at the event.
//noinspection SimplifiableIfStatement
- if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
- && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
+ && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
}
@@ -5479,8 +5531,9 @@
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
- if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
- mOnTouchListener.onTouch(this, event)) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
+ && li.mOnTouchListener.onTouch(this, event)) {
return true;
}
@@ -5572,8 +5625,10 @@
private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
//noinspection SimplifiableIfStatement
- if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
- && mOnGenericMotionListener.onGenericMotion(this, event)) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnGenericMotionListener != null
+ && (mViewFlags & ENABLED_MASK) == ENABLED
+ && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
return true;
}
@@ -5599,8 +5654,10 @@
*/
protected boolean dispatchHoverEvent(MotionEvent event) {
//noinspection SimplifiableIfStatement
- if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
- && mOnHoverListener.onHover(this, event)) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnHoverListener != null
+ && (mViewFlags & ENABLED_MASK) == ENABLED
+ && li.mOnHoverListener.onHover(this, event)) {
return true;
}
@@ -5884,7 +5941,8 @@
mAttachInfo.mKeepScreenOn = true;
}
mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
- if (mOnSystemUiVisibilityChangeListener != null) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
mAttachInfo.mHasSystemUiListeners = true;
}
}
@@ -6118,8 +6176,9 @@
((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
onCreateContextMenu(menu);
- if (mOnCreateContextMenuListener != null) {
- mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnCreateContextMenuListener != null) {
+ li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
}
// Clear the extra information so subsequent items that aren't mine don't
@@ -9723,8 +9782,9 @@
performCollectViewAttributes(visibility);
onAttachedToWindow();
+ ListenerInfo li = mListenerInfo;
final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
- mOnAttachStateChangeListeners;
+ li != null ? li.mOnAttachStateChangeListeners : null;
if (listeners != null && listeners.size() > 0) {
// NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
// perform the dispatching. The iterator is a safe guard against listeners that
@@ -9756,8 +9816,9 @@
onDetachedFromWindow();
+ ListenerInfo li = mListenerInfo;
final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
- mOnAttachStateChangeListeners;
+ li != null ? li.mOnAttachStateChangeListeners : null;
if (listeners != null && listeners.size() > 0) {
// NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
// perform the dispatching. The iterator is a safe guard against listeners that
@@ -11193,9 +11254,10 @@
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~LAYOUT_REQUIRED;
- if (mOnLayoutChangeListeners != null) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnLayoutChangeListeners != null) {
ArrayList<OnLayoutChangeListener> listenersCopy =
- (ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone();
+ (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
int numListeners = listenersCopy.size();
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
@@ -13065,7 +13127,7 @@
* @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
*/
public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
- mOnSystemUiVisibilityChangeListener = l;
+ getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
mParent.recomputeViewAttributes(this);
}
@@ -13076,8 +13138,9 @@
* the view hierarchy.
*/
public void dispatchSystemUiVisibilityChanged(int visibility) {
- if (mOnSystemUiVisibilityChangeListener != null) {
- mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
+ li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
}
}
@@ -13349,8 +13412,9 @@
*/
public boolean dispatchDragEvent(DragEvent event) {
//noinspection SimplifiableIfStatement
- if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
- && mOnDragListener.onDrag(this, event)) {
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
+ && li.mOnDragListener.onDrag(this, event)) {
return true;
}
return onDragEvent(event);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 62b20b3..e366e72 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -352,7 +352,7 @@
private static final int ARRAY_CAPACITY_INCREMENT = 12;
// Used to draw cached views
- private final Paint mCachePaint = new Paint();
+ private Paint mCachePaint;
// Used to animate add/remove changes in layout
private LayoutTransition mTransition;
@@ -405,8 +405,6 @@
mChildren = new View[ARRAY_INITIAL_CAPACITY];
mChildrenCount = 0;
- mCachePaint.setDither(false);
-
mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE;
}
@@ -2231,14 +2229,10 @@
@Override
void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
- // If the view is not the topmost one in the view hierarchy and it is
- // marked as the logical root of a view hierarchy, do not go any deeper.
- if ((!(getParent() instanceof ViewRootImpl)) && (mPrivateFlags & IS_ROOT_NAMESPACE) != 0) {
- return;
- }
for (int i = 0, count = mChildrenCount; i < count; i++) {
View child = mChildren[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+ if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
info.addChild(child);
}
}
@@ -2909,6 +2903,11 @@
if (layerType == LAYER_TYPE_NONE) {
cachePaint = mCachePaint;
+ if (cachePaint == null) {
+ cachePaint = new Paint();
+ cachePaint.setDither(false);
+ mCachePaint = cachePaint;
+ }
if (alpha < 1.0f) {
cachePaint.setAlpha((int) (alpha * 255));
mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 9cbe8db4..e0403ff 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,8 +16,6 @@
package android.widget;
-import com.android.internal.R;
-
import android.annotation.Widget;
import android.app.Service;
import android.content.Context;
@@ -31,7 +29,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
-import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -44,6 +41,8 @@
import android.view.ViewGroup;
import android.widget.AbsListView.OnScrollListener;
+import com.android.internal.R;
+
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -121,11 +120,6 @@
private static final int SCROLL_CHANGE_DELAY = 40;
/**
- * String for formatting the month name in the title text view.
- */
- private static final String FORMAT_MONTH_NAME = "MMMM, yyyy";
-
- /**
* String for parsing dates.
*/
private static final String DATE_FORMAT = "MM/dd/yyyy";
@@ -940,11 +934,17 @@
* @param calendar A day in the new focus month.
*/
private void setMonthDisplayed(Calendar calendar) {
- mMonthName.setText(DateFormat.format(FORMAT_MONTH_NAME, calendar));
- mMonthName.invalidate();
- mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
- mAdapter.setFocusMonth(mCurrentMonthDisplayed);
- // TODO Send Accessibility Event
+ final int newMonthDisplayed = calendar.get(Calendar.MONTH);
+ if (mCurrentMonthDisplayed != newMonthDisplayed) {
+ mCurrentMonthDisplayed = newMonthDisplayed;
+ mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
+ | DateUtils.FORMAT_SHOW_YEAR;
+ final long millis = calendar.getTimeInMillis();
+ String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
+ mMonthName.setText(newMonthName);
+ mMonthName.invalidate();
+ }
}
/**
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 320c650..5ab99dc 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -203,6 +203,11 @@
private final EditText mInputText;
/**
+ * The min height of this widget.
+ */
+ private final int mMinHeight;
+
+ /**
* The max height of this widget.
*/
private final int mMaxHeight;
@@ -210,7 +215,17 @@
/**
* The max width of this widget.
*/
- private final int mMaxWidth;
+ private final int mMinWidth;
+
+ /**
+ * The max width of this widget.
+ */
+ private int mMaxWidth;
+
+ /**
+ * Flag whether to compute the max width.
+ */
+ private final boolean mComputeMaxWidth;
/**
* The height of the text.
@@ -527,8 +542,19 @@
getResources().getDisplayMetrics());
mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
- mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight, 0);
- mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth, 0);
+ mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight, 0);
+ mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight,
+ Integer.MAX_VALUE);
+ if (mMinHeight > mMaxHeight) {
+ throw new IllegalArgumentException("minHeight > maxHeight");
+ }
+ mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth, 0);
+ mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth,
+ Integer.MAX_VALUE);
+ if (mMinWidth > mMaxWidth) {
+ throw new IllegalArgumentException("minWidth > maxWidth");
+ }
+ mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE);
attributesArray.recycle();
mShowInputControlsAnimimationDuration = getResources().getInteger(
@@ -677,37 +703,33 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (mMaxHeight <= 0 && mMaxWidth <= 0) {
- super.onLayout(changed, left, top, right, bottom);
- } else {
- final int msrdWdth = getMeasuredWidth();
- final int msrdHght = getMeasuredHeight();
+ final int msrdWdth = getMeasuredWidth();
+ final int msrdHght = getMeasuredHeight();
- // Increment button at the top.
- final int inctBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
- final int incrBtnLeft = (msrdWdth - inctBtnMsrdWdth) / 2;
- final int incrBtnTop = 0;
- final int incrBtnRight = incrBtnLeft + inctBtnMsrdWdth;
- final int incrBtnBottom = incrBtnTop + mIncrementButton.getMeasuredHeight();
- mIncrementButton.layout(incrBtnLeft, incrBtnTop, incrBtnRight, incrBtnBottom);
+ // Increment button at the top.
+ final int inctBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
+ final int incrBtnLeft = (msrdWdth - inctBtnMsrdWdth) / 2;
+ final int incrBtnTop = 0;
+ final int incrBtnRight = incrBtnLeft + inctBtnMsrdWdth;
+ final int incrBtnBottom = incrBtnTop + mIncrementButton.getMeasuredHeight();
+ mIncrementButton.layout(incrBtnLeft, incrBtnTop, incrBtnRight, incrBtnBottom);
- // Input text centered horizontally.
- final int inptTxtMsrdWdth = mInputText.getMeasuredWidth();
- final int inptTxtMsrdHght = mInputText.getMeasuredHeight();
- final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2;
- final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2;
- final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth;
- final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght;
- mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom);
+ // Input text centered horizontally.
+ final int inptTxtMsrdWdth = mInputText.getMeasuredWidth();
+ final int inptTxtMsrdHght = mInputText.getMeasuredHeight();
+ final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2;
+ final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2;
+ final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth;
+ final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght;
+ mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom);
- // Decrement button at the top.
- final int decrBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
- final int decrBtnLeft = (msrdWdth - decrBtnMsrdWdth) / 2;
- final int decrBtnTop = msrdHght - mDecrementButton.getMeasuredHeight();
- final int decrBtnRight = decrBtnLeft + decrBtnMsrdWdth;
- final int decrBtnBottom = msrdHght;
- mDecrementButton.layout(decrBtnLeft, decrBtnTop, decrBtnRight, decrBtnBottom);
- }
+ // Decrement button at the top.
+ final int decrBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
+ final int decrBtnLeft = (msrdWdth - decrBtnMsrdWdth) / 2;
+ final int decrBtnTop = msrdHght - mDecrementButton.getMeasuredHeight();
+ final int decrBtnRight = decrBtnLeft + decrBtnMsrdWdth;
+ final int decrBtnBottom = msrdHght;
+ mDecrementButton.layout(decrBtnLeft, decrBtnTop, decrBtnRight, decrBtnBottom);
if (!mScrollWheelAndFadingEdgesInitialized) {
mScrollWheelAndFadingEdgesInitialized = true;
@@ -719,20 +741,9 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- final int measuredWidth;
- if (mMaxWidth > 0) {
- measuredWidth = getMaxSize(widthMeasureSpec, mMaxWidth);
- } else {
- measuredWidth = getMeasuredWidth();
- }
- final int measuredHeight;
- if (mMaxHeight > 0) {
- measuredHeight = getMaxSize(heightMeasureSpec, mMaxHeight);
- } else {
- measuredHeight = getMeasuredHeight();
- }
- setMeasuredDimension(measuredWidth, measuredHeight);
+ final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMinWidth, mMaxWidth);
+ final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMinHeight, mMaxHeight);
+ super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
}
@Override
@@ -1034,6 +1045,49 @@
}
/**
+ * Computes the max width if no such specified as an attribute.
+ */
+ private void tryComputeMaxWidth() {
+ if (!mComputeMaxWidth) {
+ return;
+ }
+ int maxTextWidth = 0;
+ if (mDisplayedValues == null) {
+ float maxDigitWidth = 0;
+ for (int i = 0; i <= 9; i++) {
+ final float digitWidth = mSelectorWheelPaint.measureText(String.valueOf(i));
+ if (digitWidth > maxDigitWidth) {
+ maxDigitWidth = digitWidth;
+ }
+ }
+ int numberOfDigits = 0;
+ int current = mMaxValue;
+ while (current > 0) {
+ numberOfDigits++;
+ current = current / 10;
+ }
+ maxTextWidth = (int) (numberOfDigits * maxDigitWidth);
+ } else {
+ final int valueCount = mDisplayedValues.length;
+ for (int i = 0; i < valueCount; i++) {
+ final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValues[i]);
+ if (textWidth > maxTextWidth) {
+ maxTextWidth = (int) textWidth;
+ }
+ }
+ }
+ maxTextWidth += mInputText.getPaddingLeft() + mInputText.getPaddingRight();
+ if (mMaxWidth != maxTextWidth) {
+ if (maxTextWidth > mMinWidth) {
+ mMaxWidth = maxTextWidth;
+ } else {
+ mMaxWidth = mMinWidth;
+ }
+ invalidate();
+ }
+ }
+
+ /**
* Gets whether the selector wheel wraps when reaching the min/max value.
*
* @return True if the selector wheel wraps.
@@ -1119,6 +1173,7 @@
setWrapSelectorWheel(wrapSelectorWheel);
initializeSelectorWheelIndices();
updateInputTextView();
+ tryComputeMaxWidth();
}
/**
@@ -1150,6 +1205,7 @@
setWrapSelectorWheel(wrapSelectorWheel);
initializeSelectorWheelIndices();
updateInputTextView();
+ tryComputeMaxWidth();
}
/**
@@ -1298,24 +1354,28 @@
}
/**
- * Gets the max value for a size based on the measure spec passed by
- * the parent and the max value for that size.
+ * Makes a measure spec that tries greedily to use the max value.
*
* @param measureSpec The measure spec.
* @param maxValue The max value for the size.
- * @return The max size.
+ * @return A measure spec greedily imposing the max size.
*/
- private int getMaxSize(int measureSpec, int maxValue) {
+ private int makeMeasureSpec(int measureSpec, int minValue, int maxValue) {
+ final int size = MeasureSpec.getSize(measureSpec);
+ if (size < minValue) {
+ throw new IllegalArgumentException("Available space is less than min size: "
+ + size + " < " + minValue);
+ }
final int mode = MeasureSpec.getMode(measureSpec);
switch (mode) {
case MeasureSpec.EXACTLY:
- return MeasureSpec.getSize(measureSpec);
+ return measureSpec;
case MeasureSpec.AT_MOST:
- return Math.min(MeasureSpec.getSize(measureSpec), maxValue);
+ return MeasureSpec.makeMeasureSpec(Math.min(size, maxValue), MeasureSpec.EXACTLY);
case MeasureSpec.UNSPECIFIED:
- return maxValue;
+ return MeasureSpec.makeMeasureSpec(maxValue, MeasureSpec.EXACTLY);
default:
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Unknown measure mode: " + mode);
}
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 6df80e4..399d217 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1187,6 +1187,8 @@
*/
@Override
public void onActionViewExpanded() {
+ if (mExpandedInActionView) return;
+
mExpandedInActionView = true;
mCollapsedImeOptions = mQueryTextView.getImeOptions();
mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9257534..a8680d4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -271,7 +271,7 @@
private static final int SIGNED = 2;
private static final int DECIMAL = 4;
- class Drawables {
+ static class Drawables {
final Rect mCompoundRect = new Rect();
Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
mDrawableStart, mDrawableEnd;
@@ -304,7 +304,7 @@
private int mMarqueeRepeatLimit = 3;
- class InputContentType {
+ static class InputContentType {
int imeOptions = EditorInfo.IME_NULL;
String privateImeOptions;
CharSequence imeActionLabel;
@@ -315,7 +315,7 @@
}
InputContentType mInputContentType;
- class InputMethodState {
+ static class InputMethodState {
Rect mCursorRectInWindow = new Rect();
RectF mTmpRectF = new RectF();
float[] mTmpOffset = new float[2];
@@ -5363,7 +5363,7 @@
// don't let it be inserted into the text.
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
|| shouldAdvanceFocusOnEnter()) {
- if (mOnClickListener != null) {
+ if (hasOnClickListeners()) {
return 0;
}
return -1;
@@ -5497,7 +5497,7 @@
* call performClick(), but that won't do anything in
* this case.)
*/
- if (mOnClickListener == null) {
+ if (hasOnClickListeners()) {
if (mMovement != null && mText instanceof Editable
&& mLayout != null && onCheckIsTextEditor()) {
InputMethodManager imm = InputMethodManager.peekInstance();
@@ -5535,7 +5535,7 @@
* call performClick(), but that won't do anything in
* this case.)
*/
- if (mOnClickListener == null) {
+ if (hasOnClickListeners()) {
View v = focusSearch(FOCUS_DOWN);
if (v != null) {
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
index c5fa18c..eb372ca 100644
--- a/core/java/android/widget/ZoomButton.java
+++ b/core/java/android/widget/ZoomButton.java
@@ -29,8 +29,8 @@
private final Handler mHandler;
private final Runnable mRunnable = new Runnable() {
public void run() {
- if ((mOnClickListener != null) && mIsInLongpress && isEnabled()) {
- mOnClickListener.onClick(ZoomButton.this);
+ if (hasOnClickListeners() && mIsInLongpress && isEnabled()) {
+ callOnClick();
mHandler.postDelayed(this, mZoomSpeed);
}
}
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 8ee1d8b..79aa43b 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -444,7 +444,11 @@
LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d",
dirFlags, rc, paraDir);
#endif
- if (!U_SUCCESS(status) || rc <= 1) {
+ if (U_SUCCESS(status) && rc == 1) {
+ // Normal case: one run, status is ok
+ isRTL = (paraDir == 1);
+ useSingleRun = true;
+ } else if (!U_SUCCESS(status) || rc < 1) {
LOGW("computeValuesWithHarfbuzz -- need to force to single run");
isRTL = (paraDir == 1);
useSingleRun = true;
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
index 004d52a..f9b247f 100644
--- a/core/res/res/layout-sw600dp/date_picker_dialog.xml
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -22,4 +22,6 @@
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:spinnersShown="true"
+ android:calendarViewShown="true"
/>
diff --git a/core/res/res/layout-sw600dp/number_picker.xml b/core/res/res/layout-sw600dp/number_picker.xml
deleted file mode 100644
index 807daf2..0000000
--- a/core/res/res/layout-sw600dp/number_picker.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, 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.
-*/
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <ImageButton android:id="@+id/increment"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="?android:attr/numberPickerUpButtonStyle"
- android:contentDescription="@string/number_picker_increment_button" />
-
- <EditText android:id="@+id/numberpicker_input"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="?android:attr/numberPickerInputTextStyle" />
-
- <ImageButton android:id="@+id/decrement"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="?android:attr/numberPickerDownButtonStyle"
- android:contentDescription="@string/number_picker_decrement_button" />
-
-</merge>
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 1649466..6f0517d 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -40,7 +40,7 @@
<!-- Month -->
<NumberPicker
android:id="@+id/month"
- android:layout_width="80dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dip"
android:layout_marginRight="1dip"
@@ -51,7 +51,7 @@
<!-- Day -->
<NumberPicker
android:id="@+id/day"
- android:layout_width="80dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dip"
android:layout_marginRight="1dip"
@@ -62,7 +62,7 @@
<!-- Year -->
<NumberPicker
android:id="@+id/year"
- android:layout_width="95dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dip"
android:layout_marginRight="1dip"
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 8627637..57b5614 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -23,8 +23,8 @@
depending on the date format selected by the user.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:gravity="center">
@@ -32,7 +32,6 @@
<LinearLayout android:id="@+id/pickers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="22dip"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center">
@@ -40,10 +39,10 @@
<!-- Month -->
<NumberPicker
android:id="@+id/month"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
@@ -51,10 +50,10 @@
<!-- Day -->
<NumberPicker
android:id="@+id/day"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
@@ -62,10 +61,10 @@
<!-- Year -->
<NumberPicker
android:id="@+id/year"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index ca6fe2d..29c97b7 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -28,10 +28,10 @@
<!-- hour -->
<NumberPicker
android:id="@+id/hour"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
- android:layout_marginRight="20dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="14dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
@@ -47,10 +47,10 @@
<!-- minute -->
<NumberPicker
android:id="@+id/minute"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="20dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="14dip"
+ android:layout_marginRight="16dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
@@ -58,10 +58,10 @@
<!-- AM / PM -->
<NumberPicker
android:id="@+id/amPm"
- android:layout_width="48dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 936482df..a40e24c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3576,8 +3576,14 @@
<attr name="selectionDivider" format="reference" />
<!-- @hide The height of the selection divider. -->
<attr name="selectionDividerHeight" format="dimension" />
+ <!-- @hide The min height of the NumberPicker. -->
+ <attr name="minHeight" />
<!-- @hide The max height of the NumberPicker. -->
<attr name="maxHeight" />
+ <!-- @hide The min width of the NumberPicker. -->
+ <attr name="minWidth" />
+ <!-- @hide The max width of the NumberPicker. -->
+ <attr name="maxWidth" />
<!-- @hide The max width of the NumberPicker. -->
<attr name="maxWidth" />
</declare-styleable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bde2c72..48e8f1e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -182,12 +182,14 @@
<!-- Regex of wired ethernet ifaces -->
<string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
- <!-- If the mobile hotspot feature requires provisioning, an intent string can be provided
- to the launch a supported application that provisions the devices.
+ <!-- If the mobile hotspot feature requires provisioning, a package name and class name
+ can be provided to launch a supported application that provisions the devices.
Example Usage:
- Intent intent = new Intent(R.string.config_mobile_hotspot_provision_intent);
+ String[] appDetails = getStringArray(R.array.config_mobile_hotspot_provision_app);
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(appDetails[0], appDetails[1]);
startActivityForResult(intent, 0);
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
@@ -202,7 +204,14 @@
See src/com/android/settings/TetherSettings.java for more details.
-->
- <string translatable="false" name="config_mobile_hotspot_provision_intent"></string>
+ <!-- The first element is the package name and the second element is the class name
+ of the provisioning app -->
+ <string-array translatable="false" name="config_mobile_hotspot_provision_app">
+ <!--
+ <item>com.example.provisioning</item>
+ <item>com.example.provisioning.Activity</item>
+ -->
+ </string-array>
<!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
<!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8356985..8d95d86e5 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1654,8 +1654,8 @@
<item name="android:flingable">true</item>
<item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
<item name="android:selectionDividerHeight">2dip</item>
- <item name="android:maxHeight">180dip</item>
- <item name="android:maxWidth">56dip</item>
+ <item name="android:minWidth">48dip</item>
+ <item name="android:maxHeight">200dip</item>
</style>
<style name="Widget.Holo.TimePicker" parent="Widget.TimePicker">
@@ -1684,6 +1684,8 @@
<style name="Widget.Holo.EditText.NumberPickerInputText">
<item name="android:paddingTop">13sp</item>
<item name="android:paddingBottom">13sp</item>
+ <item name="android:paddingLeft">2sp</item>
+ <item name="android:paddingRight">2sp</item>
<item name="android:gravity">center</item>
<item name="android:singleLine">true</item>
<item name="android:textSize">18sp</item>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 20ce701..61337b7 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -321,6 +321,10 @@
<li>{@link android.widget.ProgressBar}</li>
<li>{@link android.widget.TextView}</li>
<li>{@link android.widget.ViewFlipper}</li>
+ <li>{@link android.widget.ListView}</li>
+ <li>{@link android.widget.GridView}</li>
+ <li>{@link android.widget.StackView}</li>
+ <li>{@link android.widget.AdapterViewFlipper}</li>
</ul>
<p>Descendants of these classes are not supported.</p>
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f8a7d6a..310ace0 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -408,6 +408,12 @@
ProcessRecord mHomeProcess;
/**
+ * This is the process holding the activity the user last visited that
+ * is in a different process from the one they are currently in.
+ */
+ ProcessRecord mPreviousProcess;
+
+ /**
* Packages that the user has asked to have run in screen size
* compatibility mode instead of filling the screen.
*/
@@ -8114,6 +8120,7 @@
pw.println();
pw.println(" mHomeProcess: " + mHomeProcess);
+ pw.println(" mPreviousProcess: " + mPreviousProcess);
if (mHeavyWeightProcess != null) {
pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
}
@@ -8212,6 +8219,7 @@
pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
+ pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
@@ -8228,6 +8236,7 @@
pw.println();
pw.println(" mHomeProcess: " + mHomeProcess);
+ pw.println(" mPreviousProcess: " + mPreviousProcess);
if (mHeavyWeightProcess != null) {
pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
}
@@ -9009,6 +9018,8 @@
oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
} else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
+ } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
+ oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
} else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
} else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
@@ -9287,12 +9298,13 @@
ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
- ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
+ ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
};
final String[] oomLabel = new String[] {
"System", "Persistent", "Foreground",
"Visible", "Perceptible", "Heavy Weight",
- "Backup", "A Services", "Home", "B Services", "Background"
+ "Backup", "A Services", "Home", "Previous",
+ "B Services", "Background"
};
long oomPss[] = new long[oomLabel.length];
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length];
@@ -9714,7 +9726,10 @@
if (app == mHomeProcess) {
mHomeProcess = null;
}
-
+ if (app == mPreviousProcess) {
+ mPreviousProcess = null;
+ }
+
if (restart) {
// We have components that still need to be running in the
// process, so re-launch it.
@@ -13112,6 +13127,17 @@
app.adjType = "home";
}
+ if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
+ && app.activities.size() > 0) {
+ // This was the previous process that showed UI to the user.
+ // We want to try to keep it around more aggressively, to give
+ // a good experience around switching between two apps.
+ adj = ProcessList.PREVIOUS_APP_ADJ;
+ schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ app.hidden = false;
+ app.adjType = "previous";
+ }
+
if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
+ " reason=" + app.adjType);
@@ -13841,7 +13867,8 @@
} else {
numBg++;
}
- } else if (app.curAdj >= ProcessList.HOME_APP_ADJ) {
+ } else if (app.curAdj >= ProcessList.HOME_APP_ADJ
+ && app.curAdj != ProcessList.SERVICE_B_ADJ) {
numBg++;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 28c3bae..a47502e 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1363,6 +1363,13 @@
+ ", nowVisible=" + next.nowVisible);
}
}
+
+ if (!prev.finishing && prev.app != null && prev.app != next.app) {
+ // We are switching to a new activity that is in a different
+ // process than the previous one. Note the previous process,
+ // so we can try to keep it around.
+ mService.mPreviousProcess = prev.app;
+ }
}
// Launching this app's activity, make sure the app is no longer
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index f368a70..af7b314 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -38,11 +38,19 @@
// This is a process only hosting activities that are not visible,
// so it can be killed without any disruption.
static final int HIDDEN_APP_MAX_ADJ = 15;
- static int HIDDEN_APP_MIN_ADJ = 8;
+ static int HIDDEN_APP_MIN_ADJ = 9;
// The B list of SERVICE_ADJ -- these are the old and decrepit
// services that aren't as shiny and interesting as the ones in the A list.
- static final int SERVICE_B_ADJ = 7;
+ static final int SERVICE_B_ADJ = 8;
+
+ // This is the process of the previous application that the user was in.
+ // This process is kept above other things, because it is very common to
+ // switch back to the previous app. This is important both for recent
+ // task switch (toggling between the two top recent apps) as well as normal
+ // UI flow such as clicking on a URI in the e-mail app to view in the browser,
+ // and then pressing back to return to e-mail.
+ static final int PREVIOUS_APP_ADJ = 7;
// This is a process holding the home application -- we want to try
// avoiding killing it, even if it would normally be in the background,
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index e610782..bdad82a 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -186,8 +186,10 @@
private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
- private static final int MSG_RULES_CHANGED = 0x1;
- private static final int MSG_METERED_IFACES_CHANGED = 0x2;
+ private static final int MSG_RULES_CHANGED = 1;
+ private static final int MSG_METERED_IFACES_CHANGED = 2;
+ private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
+ private static final int MSG_PROCESS_DIED = 4;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -335,37 +337,13 @@
private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@Override
public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
- // only someone like AMS should only be calling us
- mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
-
- synchronized (mRulesLock) {
- // because a uid can have multiple pids running inside, we need to
- // remember all pid states and summarize foreground at uid level.
-
- // record foreground for this specific pid
- SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
- if (pidForeground == null) {
- pidForeground = new SparseBooleanArray(2);
- mUidPidForeground.put(uid, pidForeground);
- }
- pidForeground.put(pid, foregroundActivities);
- computeUidForegroundLocked(uid);
- }
+ mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED,
+ pid, uid, foregroundActivities).sendToTarget();
}
@Override
public void onProcessDied(int pid, int uid) {
- // only someone like AMS should only be calling us
- mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
-
- synchronized (mRulesLock) {
- // clear records and recompute, when they exist
- final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
- if (pidForeground != null) {
- pidForeground.delete(pid);
- computeUidForegroundLocked(uid);
- }
- }
+ mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget();
}
};
@@ -1469,6 +1447,40 @@
mListeners.finishBroadcast();
return true;
}
+ case MSG_FOREGROUND_ACTIVITIES_CHANGED: {
+ final int pid = msg.arg1;
+ final int uid = msg.arg2;
+ final boolean foregroundActivities = (Boolean) msg.obj;
+
+ synchronized (mRulesLock) {
+ // because a uid can have multiple pids running inside, we need to
+ // remember all pid states and summarize foreground at uid level.
+
+ // record foreground for this specific pid
+ SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
+ if (pidForeground == null) {
+ pidForeground = new SparseBooleanArray(2);
+ mUidPidForeground.put(uid, pidForeground);
+ }
+ pidForeground.put(pid, foregroundActivities);
+ computeUidForegroundLocked(uid);
+ }
+ return true;
+ }
+ case MSG_PROCESS_DIED: {
+ final int pid = msg.arg1;
+ final int uid = msg.arg2;
+
+ synchronized (mRulesLock) {
+ // clear records and recompute, when they exist
+ final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
+ if (pidForeground != null) {
+ pidForeground.delete(pid);
+ computeUidForegroundLocked(uid);
+ }
+ }
+ return true;
+ }
default: {
return false;
}
diff --git a/tests/FrameworkPerf/AndroidManifest.xml b/tests/FrameworkPerf/AndroidManifest.xml
index c3fc837..aa663f3 100644
--- a/tests/FrameworkPerf/AndroidManifest.xml
+++ b/tests/FrameworkPerf/AndroidManifest.xml
@@ -3,7 +3,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk android:minSdkVersion="5" />
- <application>
+ <application android:hardwareAccelerated="false">
<activity android:name="FrameworkPerfActivity" android:label="Framework Perf">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/FrameworkPerf/res/layout/main.xml b/tests/FrameworkPerf/res/layout/main.xml
index 8b54118..62b1a7a 100644
--- a/tests/FrameworkPerf/res/layout/main.xml
+++ b/tests/FrameworkPerf/res/layout/main.xml
@@ -64,6 +64,23 @@
android:orientation="horizontal"
android:layout_marginTop="10dp"
>
+ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="Test time (ms): "
+ />
+ <EditText android:id="@+id/testtime"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:text="5000"
+ />
+ </LinearLayout>
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginTop="10dp"
+ >
<Button android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 66e788c..5e15224 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -58,6 +58,7 @@
Spinner mFgSpinner;
Spinner mBgSpinner;
TextView mLog;
+ TextView mTestTime;
PowerManager.WakeLock mPartialWakeLock;
long mMaxRunTime = 5000;
@@ -110,6 +111,7 @@
};
final Op[] mAvailOps = new Op[] {
+ null,
new NoOp(),
new CpuOp(),
new SchedulerOp(),
@@ -122,6 +124,8 @@
new ReadFileOp(),
new ParseXmlResOp(),
new ParseLargeXmlResOp(),
+ new LayoutInflaterOp(),
+ new LayoutInflaterLargeOp(),
new LoadSmallBitmapOp(),
new LoadLargeBitmapOp(),
new LoadSmallScaledBitmapOp(),
@@ -170,11 +174,14 @@
mAvailOpDescriptions = new String[mAvailOps.length];
for (int i=0; i<mAvailOps.length; i++) {
Op op = mAvailOps[i];
- if (op.getClass() == NoOp.class) {
+ if (op == null) {
mAvailOpLabels[i] = "All";
mAvailOpDescriptions[i] = "All tests";
} else {
mAvailOpLabels[i] = op.getName();
+ if (mAvailOpLabels[i] == null) {
+ mAvailOpLabels[i] = "Nothing";
+ }
mAvailOpDescriptions[i] = op.getLongName();
}
}
@@ -211,6 +218,7 @@
stopRunning();
}
});
+ mTestTime = (TextView)findViewById(R.id.testtime);
mLog = (TextView)findViewById(R.id.log);
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
@@ -221,11 +229,7 @@
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == mFgSpinner || parent == mBgSpinner) {
- Spinner spinner = (Spinner)parent;
Op op = mAvailOps[position];
- if (op.getClass() == NoOp.class) {
- op = null;
- }
if (parent == mFgSpinner) {
mFgTest = op;
((TextView)findViewById(R.id.fgtext)).setText(mAvailOpDescriptions[position]);
@@ -238,8 +242,6 @@
@Override
public void onNothingSelected(AdapterView<?> parent) {
- // TODO Auto-generated method stub
-
}
@Override
@@ -314,6 +316,7 @@
updateWakeLock();
startService(new Intent(this, SchedulerService.class));
mCurOpIndex = 0;
+ mMaxRunTime = Integer.parseInt(mTestTime.getText().toString());
mResults.clear();
startCurOp();
}