Merge "Reduce lock thrashing in native Looper." into gingerbread
diff --git a/api/current.xml b/api/current.xml
index aff615c..8651c4d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -5828,28 +5828,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad58"
- type="int"
- transient="false"
- volatile="false"
- value="16843463"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="kraken_resource_pad59"
- type="int"
- transient="false"
- volatile="false"
- value="16843462"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad6"
type="int"
transient="false"
@@ -5861,17 +5839,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad60"
- type="int"
- transient="false"
- volatile="false"
- value="16843461"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad7"
type="int"
transient="false"
@@ -9513,6 +9480,39 @@
visibility="public"
>
</field>
+<field name="textSelectHandle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843463"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="textSelectHandleLeft"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843461"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="textSelectHandleRight"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843462"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textSize"
type="int"
transient="false"
@@ -223937,8 +223937,19 @@
visibility="public"
>
</method>
+<method name="isShowing"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="onTouchEvent"
- return="void"
+ return="boolean"
abstract="true"
native="false"
synchronized="false"
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index f182a7a..1e88c56 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -56,9 +56,9 @@
public static final int SENSOR = 3;
/**
- * A constant indicating a a wifi turn on timer
+ * A constant indicating a a wifi running timer
*/
- public static final int WIFI_TURNED_ON = 4;
+ public static final int WIFI_RUNNING = 4;
/**
* A constant indicating a full wifi lock timer
@@ -249,8 +249,8 @@
*/
public abstract long getTcpBytesSent(int which);
- public abstract void noteWifiTurnedOnLocked();
- public abstract void noteWifiTurnedOffLocked();
+ public abstract void noteWifiRunningLocked();
+ public abstract void noteWifiStoppedLocked();
public abstract void noteFullWifiLockAcquiredLocked();
public abstract void noteFullWifiLockReleasedLocked();
public abstract void noteScanWifiLockAcquiredLocked();
@@ -261,7 +261,7 @@
public abstract void noteAudioTurnedOffLocked();
public abstract void noteVideoTurnedOnLocked();
public abstract void noteVideoTurnedOffLocked();
- public abstract long getWifiTurnedOnTime(long batteryRealtime, int which);
+ public abstract long getWifiRunningTime(long batteryRealtime, int which);
public abstract long getFullWifiLockTime(long batteryRealtime, int which);
public abstract long getScanWifiLockTime(long batteryRealtime, int which);
public abstract long getWifiMulticastTime(long batteryRealtime,
@@ -701,7 +701,7 @@
*
* {@hide}
*/
- public abstract long getWifiRunningTime(long batteryRealtime, int which);
+ public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
/**
* Returns the time in microseconds that bluetooth has been on while the device was
@@ -977,7 +977,7 @@
final long screenOnTime = getScreenOnTime(batteryRealtime, which);
final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
- final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
+ final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
StringBuilder sb = new StringBuilder(128);
@@ -1091,14 +1091,14 @@
long tx = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
- long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
+ long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
- || wifiTurnedOnTime != 0) {
+ || uidWifiRunningTime != 0) {
dumpLine(pw, uid, category, WIFI_LOCK_DATA,
- fullWifiLockOnTime, scanWifiLockOnTime, wifiTurnedOnTime);
+ fullWifiLockOnTime, scanWifiLockOnTime, uidWifiRunningTime);
}
if (u.hasUserActivity()) {
@@ -1240,7 +1240,7 @@
final long screenOnTime = getScreenOnTime(batteryRealtime, which);
final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
- final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
+ final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
sb.setLength(0);
@@ -1449,7 +1449,7 @@
long tcpSent = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
- long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
+ long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
if (tcpReceived != 0 || tcpSent != 0) {
pw.print(prefix); pw.print(" Network: ");
@@ -1480,11 +1480,11 @@
}
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
- || wifiTurnedOnTime != 0) {
+ || uidWifiRunningTime != 0) {
sb.setLength(0);
- sb.append(prefix); sb.append(" Turned Wifi On: ");
- formatTimeMs(sb, wifiTurnedOnTime / 1000);
- sb.append("("); sb.append(formatRatioLocked(wifiTurnedOnTime,
+ sb.append(prefix); sb.append(" Wifi Running: ");
+ formatTimeMs(sb, uidWifiRunningTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
whichBatteryRealtime)); sb.append(")\n");
sb.append(prefix); sb.append(" Full Wifi Lock: ");
formatTimeMs(sb, fullWifiLockOnTime / 1000);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b794a6a..6e395c8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1551,6 +1551,12 @@
private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
+ * Indicates that this view has a visible/touchable overlay.
+ * @hide
+ */
+ static final int HAS_OVERLAY = 0x10000000;
+
+ /**
* Always allow a user to overscroll this view, provided it is a
* view that can scroll.
*
@@ -2837,6 +2843,57 @@
resetPressedState();
}
+ /**
+ * Enable or disable drawing overlays after a full drawing pass. This enables a view to
+ * draw on a topmost overlay layer after normal drawing completes and get right of first
+ * refusal for touch events in the window.
+ *
+ * <em>Warning:</em> Views that use this feature should take care to disable/enable overlay
+ * appropriately when they are attached/detached from their window. All overlays should be
+ * disabled when detached.
+ *
+ * @param enabled true if overlay drawing should be enabled for this view, false otherwise
+ *
+ * @see #onDrawOverlay(Canvas)
+ *
+ * @hide
+ */
+ protected void setOverlayEnabled(boolean enabled) {
+ final boolean oldValue = (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
+ mPrivateFlags = (mPrivateFlags & ~HAS_OVERLAY) | (enabled ? HAS_OVERLAY : 0);
+ if (enabled != oldValue) {
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ try {
+ parent.childOverlayStateChanged(this);
+ } catch (AbstractMethodError e) {
+ Log.e(VIEW_LOG_TAG, "Could not propagate hasOverlay state", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return true if this View has an overlay enabled.
+ *
+ * @see #setOverlayEnabled(boolean)
+ * @see #onDrawOverlay(Canvas)
+ *
+ * @hide
+ */
+ public boolean isOverlayEnabled() {
+ return (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
+ }
+
+ /**
+ * Override this method to draw on an overlay layer above all other views in the window
+ * after the standard drawing pass is complete. This allows a view to draw outside its
+ * normal boundaries.
+ * @hide
+ */
+ public void onDrawOverlay(Canvas canvas) {
+ }
+
private void resetPressedState() {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 28bed3a..fd6769c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -228,6 +228,11 @@
protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
/**
+ * When set, at least one child of this ViewGroup will return true from hasOverlay.
+ */
+ private static final int FLAG_CHILD_HAS_OVERLAY = 0x100000;
+
+ /**
* Indicates which types of drawing caches are to be kept in memory.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
@@ -854,6 +859,34 @@
final int scrolledYInt = (int) scrolledYFloat;
final View[] children = mChildren;
final int count = mChildrenCount;
+
+ // Check for children with overlays first. They don't rely on hit rects to determine
+ // if they can accept a new touch event.
+ if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
+ for (int i = count - 1; i >= 0; i--) {
+ final View child = children[i];
+ // Don't let children respond to events as an overlay during an animation.
+ if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && child.getAnimation() == null
+ && child.isOverlayEnabled()) {
+ // offset the event to the view's coordinate system
+ final float xc = scrolledXFloat - child.mLeft;
+ final float yc = scrolledYFloat - child.mTop;
+ ev.setLocation(xc, yc);
+ child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+ if (child.dispatchTouchEvent(ev)) {
+ // Event handled, we have a target now.
+ mMotionTarget = child;
+ return true;
+ }
+ // The event didn't get handled, try the next view.
+ // Don't reset the event's location, it's not
+ // necessary here.
+ }
+ }
+ }
+
+ // Now check views normally.
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
@@ -2312,6 +2345,8 @@
if (clearChildFocus != null) {
clearChildFocus(clearChildFocus);
}
+
+ mGroupFlags &= ~FLAG_CHILD_HAS_OVERLAY;
}
/**
@@ -2534,7 +2569,8 @@
final int left = mLeft;
final int top = mTop;
- if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+ if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY ||
+ dirty.intersect(0, 0, mRight - left, mBottom - top) ||
(mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
@@ -3453,6 +3489,69 @@
}
/**
+ * Called when a child's overlay state changes between enabled/disabled.
+ * @param child Child view whose state has changed or null
+ * @hide
+ */
+ public void childOverlayStateChanged(View child) {
+ boolean childHasOverlay = false;
+ if (child != null) {
+ childHasOverlay = child.isOverlayEnabled();
+ } else {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (childHasOverlay |= getChildAt(i).isOverlayEnabled()) {
+ break;
+ }
+ }
+ }
+
+ final boolean hasChildWithOverlay = childHasOverlay ||
+ (mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY;
+
+ final boolean oldValue = isOverlayEnabled();
+ mGroupFlags = (mGroupFlags & ~FLAG_CHILD_HAS_OVERLAY) |
+ (hasChildWithOverlay ? FLAG_CHILD_HAS_OVERLAY : 0);
+ if (isOverlayEnabled() != oldValue) {
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ try {
+ parent.childOverlayStateChanged(this);
+ } catch (AbstractMethodError e) {
+ Log.e("ViewGroup", "Could not propagate hasOverlay state", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isOverlayEnabled() {
+ return super.isOverlayEnabled() ||
+ ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void onDrawOverlay(Canvas canvas) {
+ if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child.isOverlayEnabled()) {
+ canvas.translate(child.mLeft + child.mScrollX, child.mTop + child.mScrollY);
+ child.onDrawOverlay(canvas);
+ canvas.translate(-(child.mLeft + child.mScrollX),
+ -(child.mTop + child.mScrollY));
+ }
+ }
+ }
+ }
+
+ /**
* LayoutParams are used by views to tell their parents how they want to be
* laid out. See
* {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index b456c5d..a0d3618 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -208,4 +208,11 @@
*/
public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
boolean immediate);
+
+ /**
+ * Called when a child view's overlay state changes between enabled/disabled.
+ * @param child Child view whose state changed or null.
+ * @hide
+ */
+ public void childOverlayStateChanged(View child);
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 57c9055..acec476 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -222,6 +222,8 @@
private final int mDensity;
+ private boolean mHasOverlay;
+
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
@@ -1518,6 +1520,9 @@
canvas.setScreenDensity(scalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
+ if (mHasOverlay) {
+ mView.onDrawOverlay(canvas);
+ }
} finally {
mAttachInfo.mIgnoreDirtyState = false;
canvas.restoreToCount(saveCount);
@@ -2914,6 +2919,19 @@
return scrollToRectOrFocus(rectangle, immediate);
}
+ /**
+ * @hide
+ */
+ public void childOverlayStateChanged(View child) {
+ final boolean oldState = mHasOverlay;
+ mHasOverlay = child.isOverlayEnabled();
+ // Invalidate the whole thing when we change overlay states just in case
+ // something left chunks of data drawn someplace it shouldn't have.
+ if (mHasOverlay != oldState) {
+ child.invalidate();
+ }
+ }
+
class TakenSurfaceHolder extends BaseSurfaceHolder {
@Override
public boolean onAllowLockCanvas() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e97bbfb..a14d004 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -285,6 +285,10 @@
}
InputMethodState mInputMethodState;
+ private int mTextSelectHandleLeftRes;
+ private int mTextSelectHandleRightRes;
+ private int mTextSelectHandleRes;
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -705,6 +709,18 @@
Log.w(LOG_TAG, "Failure reading input extras", e);
}
break;
+
+ case com.android.internal.R.styleable.TextView_textSelectHandleLeft:
+ mTextSelectHandleLeftRes = a.getResourceId(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextView_textSelectHandleRight:
+ mTextSelectHandleRightRes = a.getResourceId(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextView_textSelectHandle:
+ mTextSelectHandleRes = a.getResourceId(attr, 0);
+ break;
}
}
a.recycle();
@@ -3733,6 +3749,8 @@
showError();
mShowErrorAfterAttach = false;
}
+
+ updateOverlay();
}
@Override
@@ -3750,6 +3768,8 @@
if (mError != null) {
hideError();
}
+
+ setOverlayEnabled(false);
}
@Override
@@ -4100,7 +4120,13 @@
*/
canvas.restore();
+ }
+ /**
+ * @hide
+ */
+ @Override
+ public void onDrawOverlay(Canvas canvas) {
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.draw(canvas);
}
@@ -6679,10 +6705,31 @@
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
+ // Check to see if we're testing for our anchor overlay.
+ boolean handled = false;
+ final float x = event.getX();
+ final float y = event.getY();
+ if (x < 0 || x >= mRight - mLeft || y < 0 || y >= mBottom - mTop) {
+ if (mInsertionPointCursorController != null) {
+ handled |= mInsertionPointCursorController.onTouchEvent(event);
+ }
+ if (mSelectionModifierCursorController != null) {
+ handled |= mSelectionModifierCursorController.onTouchEvent(event);
+ }
+
+ if (!handled) {
+ return false;
+ }
+ }
+
// Reset this state; it will be re-set if super.onTouchEvent
// causes focus to move to the view.
mTouchFocusSelected = false;
mScrolled = false;
+
+ if (handled) {
+ return true;
+ }
}
final boolean superResult = super.onTouchEvent(event);
@@ -7571,6 +7618,17 @@
}
}
+ private void updateOverlay() {
+ boolean enableOverlay = false;
+ if (mSelectionModifierCursorController != null) {
+ enableOverlay |= mSelectionModifierCursorController.isShowing();
+ }
+ if (mInsertionPointCursorController != null) {
+ enableOverlay |= mInsertionPointCursorController.isShowing();
+ }
+ setOverlayEnabled(enableOverlay);
+ }
+
/**
* A CursorController instance can be used to control a cursor in the text.
*
@@ -7594,6 +7652,11 @@
public void hide();
/**
+ * @return true if the CursorController is currently visible
+ */
+ public boolean isShowing();
+
+ /**
* Update the controller's position.
*/
public void updatePosition(int x, int y);
@@ -7615,7 +7678,7 @@
* a chance to become active and/or visible.
* @param event The touch event
*/
- public void onTouchEvent(MotionEvent event);
+ public boolean onTouchEvent(MotionEvent event);
/**
* Draws a visual representation of the controller on the canvas.
@@ -7649,10 +7712,10 @@
final Rect bounds = sCursorControllerTempRect;
bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0)
+ mScrollX;
- bounds.top = (bottom ? lineBottom : lineTop) - drawableHeight / 2 + mScrollY;
+ bounds.top = (bottom ? lineBottom : lineTop) + mScrollY;
mTopExtension = bottom ? 0 : drawableHeight / 2;
- mBottomExtension = drawableHeight;
+ mBottomExtension = 0; //drawableHeight / 4;
// Extend touch region up when editing the last line of text (or a single line) so that
// it is easier to grab.
@@ -7710,7 +7773,7 @@
InsertionPointCursorController() {
Resources res = mContext.getResources();
- mHandle = new Handle(res.getDrawable(com.android.internal.R.drawable.text_select_handle));
+ mHandle = new Handle(res.getDrawable(mTextSelectHandleRes));
}
public void show() {
@@ -7718,6 +7781,7 @@
// Has to be done after updateDrawablePosition, so that previous position invalidate
// in only done if necessary.
mIsVisible = true;
+ updateOverlay();
}
public void hide() {
@@ -7731,6 +7795,10 @@
}
}
+ public boolean isShowing() {
+ return mIsVisible;
+ }
+
public void draw(Canvas canvas) {
if (mIsVisible) {
int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
@@ -7746,6 +7814,7 @@
} else {
mHandle.mDrawable.setAlpha(0);
mIsVisible = false;
+ updateOverlay();
}
}
mHandle.mDrawable.draw(canvas);
@@ -7774,6 +7843,7 @@
// Should never happen, safety check.
Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
mIsVisible = false;
+ updateOverlay();
return;
}
@@ -7783,7 +7853,7 @@
mHandle.mDrawable.setAlpha(255);
}
- public void onTouchEvent(MotionEvent event) {
+ public boolean onTouchEvent(MotionEvent event) {
if (isFocused() && isTextEditable() && mIsVisible) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN : {
@@ -7811,8 +7881,9 @@
mOffsetY += viewportToContentVerticalOffset();
mOnDownTimerStart = event.getEventTime();
+ return true;
}
- break;
+ return false;
}
case MotionEvent.ACTION_UP : {
@@ -7830,6 +7901,7 @@
}
}
}
+ return false;
}
public float getOffsetX() {
@@ -7859,8 +7931,8 @@
SelectionModifierCursorController() {
Resources res = mContext.getResources();
- mStartHandle = new Handle(res.getDrawable(com.android.internal.R.drawable.text_select_handle));
- mEndHandle = new Handle(res.getDrawable(com.android.internal.R.drawable.text_select_handle));
+ mStartHandle = new Handle(res.getDrawable(mTextSelectHandleLeftRes));
+ mEndHandle = new Handle(res.getDrawable(mTextSelectHandleRightRes));
}
public void show() {
@@ -7868,6 +7940,7 @@
// Has to be done after updateDrawablePositions, so that previous position invalidate
// in only done if necessary.
mIsVisible = true;
+ updateOverlay();
mFadeOutTimerStart = -1;
hideInsertionPointCursorController();
}
@@ -7880,8 +7953,13 @@
}
}
+ public boolean isShowing() {
+ return mIsVisible;
+ }
+
public void cancelFadeOutAnimation() {
mIsVisible = false;
+ updateOverlay();
mStartHandle.postInvalidate();
mEndHandle.postInvalidate();
}
@@ -7900,6 +7978,7 @@
mStartHandle.mDrawable.setAlpha(0);
mEndHandle.mDrawable.setAlpha(0);
mIsVisible = false;
+ updateOverlay();
}
}
mStartHandle.mDrawable.draw(canvas);
@@ -7957,6 +8036,7 @@
// Should never happen, safety check.
Log.w(LOG_TAG, "Update selection controller position called with no cursor");
mIsVisible = false;
+ updateOverlay();
return;
}
@@ -7969,7 +8049,7 @@
mEndHandle.mDrawable.setAlpha(255);
}
- public void onTouchEvent(MotionEvent event) {
+ public boolean onTouchEvent(MotionEvent event) {
if (isTextEditable()) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
@@ -8004,6 +8084,7 @@
mOnDownTimerStart = event.getEventTime();
((ArrowKeyMovementMethod)mMovement).setCursorController(this);
+ return true;
}
}
}
@@ -8029,6 +8110,7 @@
break;
}
}
+ return false;
}
/**
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index bd87a0d..351714e 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -49,10 +49,11 @@
void notePhoneSignalStrength(in SignalStrength signalStrength);
void notePhoneDataConnectionState(int dataType, boolean hasData);
void notePhoneState(int phoneState);
- void noteWifiOn(int uid);
- void noteWifiOff(int uid);
- void noteWifiRunning();
- void noteWifiStopped();
+ void noteWifiOn();
+ void noteWifiOff();
+ void noteWifiRunning(in WorkSource ws);
+ void noteWifiRunningChanged(in WorkSource oldWs, in WorkSource newWs);
+ void noteWifiStopped(in WorkSource ws);
void noteBluetoothOn();
void noteBluetoothOff();
void noteFullWifiLockAcquired(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 753dbf0..c2d003e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -66,7 +66,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 50;
+ private static final int VERSION = 51;
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -129,6 +129,10 @@
final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
= new SparseArray<ArrayList<StopwatchTimer>>();
+ final ArrayList<StopwatchTimer> mWifiRunningTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mScanWifiLockTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>();
// Last partial timers we use for distributing CPU usage.
final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
@@ -194,8 +198,8 @@
StopwatchTimer mWifiOnTimer;
int mWifiOnUid = -1;
- boolean mWifiRunning;
- StopwatchTimer mWifiRunningTimer;
+ boolean mGlobalWifiRunning;
+ StopwatchTimer mGlobalWifiRunningTimer;
boolean mBluetoothOn;
StopwatchTimer mBluetoothOnTimer;
@@ -1769,7 +1773,7 @@
}
}
- public void noteWifiOnLocked(int uid) {
+ public void noteWifiOnLocked() {
if (!mWifiOn) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
@@ -1778,16 +1782,9 @@
mWifiOn = true;
mWifiOnTimer.startRunningLocked(this);
}
- if (mWifiOnUid != uid) {
- if (mWifiOnUid >= 0) {
- getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
- }
- mWifiOnUid = uid;
- getUidStatsLocked(uid).noteWifiTurnedOnLocked();
- }
}
- public void noteWifiOffLocked(int uid) {
+ public void noteWifiOffLocked() {
if (mWifiOn) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_ON_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: "
@@ -1797,7 +1794,7 @@
mWifiOnTimer.stopRunningLocked(this);
}
if (mWifiOnUid >= 0) {
- getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
+ getUidStatsLocked(mWifiOnUid).noteWifiStoppedLocked();
mWifiOnUid = -1;
}
}
@@ -1850,25 +1847,52 @@
getUidStatsLocked(uid).noteVideoTurnedOffLocked();
}
- public void noteWifiRunningLocked() {
- if (!mWifiRunning) {
+ public void noteWifiRunningLocked(WorkSource ws) {
+ if (!mGlobalWifiRunning) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(SystemClock.elapsedRealtime());
- mWifiRunning = true;
- mWifiRunningTimer.startRunningLocked(this);
+ mGlobalWifiRunning = true;
+ mGlobalWifiRunningTimer.startRunningLocked(this);
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ getUidStatsLocked(ws.get(i)).noteWifiRunningLocked();
+ }
+ } else {
+ Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
}
}
- public void noteWifiStoppedLocked() {
- if (mWifiRunning) {
+ public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) {
+ if (mGlobalWifiRunning) {
+ int N = oldWs.size();
+ for (int i=0; i<N; i++) {
+ getUidStatsLocked(oldWs.get(i)).noteWifiStoppedLocked();
+ }
+ N = newWs.size();
+ for (int i=0; i<N; i++) {
+ getUidStatsLocked(newWs.get(i)).noteWifiRunningLocked();
+ }
+ } else {
+ Log.w(TAG, "noteWifiRunningChangedLocked -- called while WIFI not running");
+ }
+ }
+
+ public void noteWifiStoppedLocked(WorkSource ws) {
+ if (mGlobalWifiRunning) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RUNNING_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(SystemClock.elapsedRealtime());
- mWifiRunning = false;
- mWifiRunningTimer.stopRunningLocked(this);
+ mGlobalWifiRunning = false;
+ mGlobalWifiRunningTimer.stopRunningLocked(this);
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ getUidStatsLocked(ws.get(i)).noteWifiStoppedLocked();
+ }
+ } else {
+ Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
}
}
@@ -2056,8 +2080,8 @@
return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
- @Override public long getWifiRunningTime(long batteryRealtime, int which) {
- return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
+ @Override public long getGlobalWifiRunningTime(long batteryRealtime, int which) {
+ return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getBluetoothOnTime(long batteryRealtime, int which) {
@@ -2090,8 +2114,8 @@
long mStartedTcpBytesReceived = -1;
long mStartedTcpBytesSent = -1;
- boolean mWifiTurnedOn;
- StopwatchTimer mWifiTurnedOnTimer;
+ boolean mWifiRunning;
+ StopwatchTimer mWifiRunningTimer;
boolean mFullWifiLockOut;
StopwatchTimer mFullWifiLockTimer;
@@ -2137,14 +2161,14 @@
public Uid(int uid) {
mUid = uid;
- mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
- null, mUnpluggables);
+ mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
+ mWifiRunningTimers, mUnpluggables);
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- null, mUnpluggables);
+ mFullWifiLockTimers, mUnpluggables);
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- null, mUnpluggables);
+ mScanWifiLockTimers, mUnpluggables);
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- null, mUnpluggables);
+ mWifiMulticastTimers, mUnpluggables);
mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables);
mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
@@ -2212,22 +2236,22 @@
}
@Override
- public void noteWifiTurnedOnLocked() {
- if (!mWifiTurnedOn) {
- mWifiTurnedOn = true;
- if (mWifiTurnedOnTimer == null) {
- mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
- null, mUnpluggables);
+ public void noteWifiRunningLocked() {
+ if (!mWifiRunning) {
+ mWifiRunning = true;
+ if (mWifiRunningTimer == null) {
+ mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
+ mWifiRunningTimers, mUnpluggables);
}
- mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+ mWifiRunningTimer.startRunningLocked(BatteryStatsImpl.this);
}
}
@Override
- public void noteWifiTurnedOffLocked() {
- if (mWifiTurnedOn) {
- mWifiTurnedOn = false;
- mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ public void noteWifiStoppedLocked() {
+ if (mWifiRunning) {
+ mWifiRunning = false;
+ mWifiRunningTimer.stopRunningLocked(BatteryStatsImpl.this);
}
}
@@ -2237,7 +2261,7 @@
mFullWifiLockOut = true;
if (mFullWifiLockTimer == null) {
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- null, mUnpluggables);
+ mFullWifiLockTimers, mUnpluggables);
}
mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
}
@@ -2257,7 +2281,7 @@
mScanWifiLockOut = true;
if (mScanWifiLockTimer == null) {
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- null, mUnpluggables);
+ mScanWifiLockTimers, mUnpluggables);
}
mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
}
@@ -2277,7 +2301,7 @@
mWifiMulticastEnabled = true;
if (mWifiMulticastTimer == null) {
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- null, mUnpluggables);
+ mWifiMulticastTimers, mUnpluggables);
}
mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
}
@@ -2332,11 +2356,11 @@
}
@Override
- public long getWifiTurnedOnTime(long batteryRealtime, int which) {
- if (mWifiTurnedOnTimer == null) {
+ public long getWifiRunningTime(long batteryRealtime, int which) {
+ if (mWifiRunningTimer == null) {
return 0;
}
- return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
+ return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override
@@ -2422,9 +2446,9 @@
boolean reset() {
boolean active = false;
- if (mWifiTurnedOnTimer != null) {
- active |= !mWifiTurnedOnTimer.reset(BatteryStatsImpl.this, false);
- active |= mWifiTurnedOn;
+ if (mWifiRunningTimer != null) {
+ active |= !mWifiRunningTimer.reset(BatteryStatsImpl.this, false);
+ active |= mWifiRunning;
}
if (mFullWifiLockTimer != null) {
active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
@@ -2517,8 +2541,8 @@
mPids.clear();
if (!active) {
- if (mWifiTurnedOnTimer != null) {
- mWifiTurnedOnTimer.detach();
+ if (mWifiRunningTimer != null) {
+ mWifiRunningTimer.detach();
}
if (mFullWifiLockTimer != null) {
mFullWifiLockTimer.detach();
@@ -2580,9 +2604,9 @@
out.writeLong(computeCurrentTcpBytesSent());
out.writeLong(mTcpBytesReceivedAtLastUnplug);
out.writeLong(mTcpBytesSentAtLastUnplug);
- if (mWifiTurnedOnTimer != null) {
+ if (mWifiRunningTimer != null) {
out.writeInt(1);
- mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
+ mWifiRunningTimer.writeToParcel(out, batteryRealtime);
} else {
out.writeInt(0);
}
@@ -2674,31 +2698,31 @@
mCurrentTcpBytesSent = in.readLong();
mTcpBytesReceivedAtLastUnplug = in.readLong();
mTcpBytesSentAtLastUnplug = in.readLong();
- mWifiTurnedOn = false;
+ mWifiRunning = false;
if (in.readInt() != 0) {
- mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
- null, mUnpluggables, in);
+ mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
+ mWifiRunningTimers, mUnpluggables, in);
} else {
- mWifiTurnedOnTimer = null;
+ mWifiRunningTimer = null;
}
mFullWifiLockOut = false;
if (in.readInt() != 0) {
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
- null, mUnpluggables, in);
+ mFullWifiLockTimers, mUnpluggables, in);
} else {
mFullWifiLockTimer = null;
}
mScanWifiLockOut = false;
if (in.readInt() != 0) {
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
- null, mUnpluggables, in);
+ mScanWifiLockTimers, mUnpluggables, in);
} else {
mScanWifiLockTimer = null;
}
mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
- null, mUnpluggables, in);
+ mWifiMulticastTimers, mUnpluggables, in);
} else {
mWifiMulticastTimer = null;
}
@@ -3771,7 +3795,7 @@
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
}
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
- mWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
+ mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
@@ -3861,7 +3885,7 @@
mPhoneDataConnectionsTimer[i].reset(this, false);
}
mWifiOnTimer.reset(this, false);
- mWifiRunningTimer.reset(this, false);
+ mGlobalWifiRunningTimer.reset(this, false);
mBluetoothOnTimer.reset(this, false);
for (int i=0; i<mUidStats.size(); i++) {
@@ -4280,6 +4304,57 @@
return u.getServiceStatsLocked(pkg, name);
}
+ /**
+ * Massage data to distribute any reasonable work down to more specific
+ * owners. Must only be called on a dead BatteryStats object!
+ */
+ public void distributeWorkLocked(int which) {
+ // Aggregate all CPU time associated with WIFI.
+ Uid wifiUid = mUidStats.get(Process.WIFI_UID);
+ if (wifiUid != null) {
+ long uSecTime = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
+ for (Uid.Proc proc : wifiUid.mProcessStats.values()) {
+ long totalRunningTime = getGlobalWifiRunningTime(uSecTime, which);
+ for (int i=0; i<mUidStats.size(); i++) {
+ Uid uid = mUidStats.valueAt(i);
+ if (uid.mUid != Process.WIFI_UID) {
+ long uidRunningTime = uid.getWifiRunningTime(uSecTime, which);
+ if (uidRunningTime > 0) {
+ Uid.Proc uidProc = uid.getProcessStatsLocked("*wifi*");
+ long time = proc.getUserTime(which);
+ time = (time*uidRunningTime)/totalRunningTime;
+ uidProc.mUserTime += time;
+ proc.mUserTime -= time;
+ time = proc.getSystemTime(which);
+ time = (time*uidRunningTime)/totalRunningTime;
+ uidProc.mSystemTime += time;
+ proc.mSystemTime -= time;
+ time = proc.getForegroundTime(which);
+ time = (time*uidRunningTime)/totalRunningTime;
+ uidProc.mForegroundTime += time;
+ proc.mForegroundTime -= time;
+ for (int sb=0; sb<proc.mSpeedBins.length; sb++) {
+ SamplingCounter sc = proc.mSpeedBins[sb];
+ if (sc != null) {
+ time = sc.getCountLocked(which);
+ time = (time*uidRunningTime)/totalRunningTime;
+ SamplingCounter uidSc = uidProc.mSpeedBins[sb];
+ if (uidSc == null) {
+ uidSc = new SamplingCounter(mUnpluggables);
+ uidProc.mSpeedBins[sb] = uidSc;
+ }
+ uidSc.mCount.addAndGet((int)time);
+ sc.mCount.addAndGet((int)-time);
+ }
+ }
+ totalRunningTime -= uidRunningTime;
+ }
+ }
+ }
+ }
+ }
+ }
+
public void shutdownLocked() {
writeLocked();
mShuttingDown = true;
@@ -4442,8 +4517,8 @@
}
mWifiOn = false;
mWifiOnTimer.readSummaryFromParcelLocked(in);
- mWifiRunning = false;
- mWifiRunningTimer.readSummaryFromParcelLocked(in);
+ mGlobalWifiRunning = false;
+ mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
mBluetoothOn = false;
mBluetoothOnTimer.readSummaryFromParcelLocked(in);
@@ -4471,9 +4546,9 @@
Uid u = new Uid(uid);
mUidStats.put(uid, u);
- u.mWifiTurnedOn = false;
+ u.mWifiRunning = false;
if (in.readInt() != 0) {
- u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in);
+ u.mWifiRunningTimer.readSummaryFromParcelLocked(in);
}
u.mFullWifiLockOut = false;
if (in.readInt() != 0) {
@@ -4547,6 +4622,14 @@
p.mUserTime = p.mLoadedUserTime = in.readLong();
p.mSystemTime = p.mLoadedSystemTime = in.readLong();
p.mStarts = p.mLoadedStarts = in.readInt();
+ int NSB = in.readInt();
+ p.mSpeedBins = new SamplingCounter[NSB];
+ for (int i=0; i<NSB; i++) {
+ if (in.readInt() != 0) {
+ p.mSpeedBins[i] = new SamplingCounter(mUnpluggables);
+ p.mSpeedBins[i].readSummaryFromParcelLocked(in);
+ }
+ }
p.readExcessiveWakeFromParcelLocked(in);
}
@@ -4614,7 +4697,7 @@
mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
}
mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
- mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
out.writeInt(mKernelWakelockStats.size());
@@ -4636,9 +4719,9 @@
out.writeInt(mUidStats.keyAt(iu));
Uid u = mUidStats.valueAt(iu);
- if (u.mWifiTurnedOnTimer != null) {
+ if (u.mWifiRunningTimer != null) {
out.writeInt(1);
- u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
@@ -4736,6 +4819,16 @@
out.writeLong(ps.mUserTime);
out.writeLong(ps.mSystemTime);
out.writeInt(ps.mStarts);
+ final int N = ps.mSpeedBins.length;
+ out.writeInt(N);
+ for (int i=0; i<N; i++) {
+ if (ps.mSpeedBins[i] != null) {
+ out.writeInt(1);
+ ps.mSpeedBins[i].writeSummaryFromParcelLocked(out);
+ } else {
+ out.writeInt(0);
+ }
+ }
ps.writeExcessiveWakeToParcelLocked(out);
}
}
@@ -4806,8 +4899,8 @@
}
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
- mWifiRunning = false;
- mWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
+ mGlobalWifiRunning = false;
+ mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mBluetoothOn = false;
mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mUptime = in.readLong();
@@ -4859,6 +4952,10 @@
mPartialTimers.clear();
mFullTimers.clear();
mWindowTimers.clear();
+ mWifiRunningTimers.clear();
+ mFullWifiLockTimers.clear();
+ mScanWifiLockTimers.clear();
+ mWifiMulticastTimers.clear();
sNumSpeedSteps = in.readInt();
@@ -4908,7 +5005,7 @@
mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
}
mWifiOnTimer.writeToParcel(out, batteryRealtime);
- mWifiRunningTimer.writeToParcel(out, batteryRealtime);
+ mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
out.writeLong(mUptime);
out.writeLong(mUptimeStart);
@@ -5006,7 +5103,7 @@
pr.println("*** Wifi timer:");
mWifiOnTimer.logState(pr, " ");
pr.println("*** WifiRunning timer:");
- mWifiRunningTimer.logState(pr, " ");
+ mGlobalWifiRunningTimer.logState(pr, " ");
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
}
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left.png b/core/res/res/drawable-hdpi/text_select_handle_left.png
new file mode 100644
index 0000000..271a6d0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle.png b/core/res/res/drawable-hdpi/text_select_handle_middle.png
new file mode 100644
index 0000000..5a83c6c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right.png b/core/res/res/drawable-hdpi/text_select_handle_right.png
new file mode 100644
index 0000000..dfdf899
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 13c3e7e..ac1c0dd 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -451,6 +451,21 @@
<!-- The preference layout that has the child/tabbed effect. -->
<attr name="preferenceLayoutChild" format="reference" />
+ <!-- ============================ -->
+ <!-- Text selection handle styles -->
+ <!-- ============================ -->
+ <eat-comment />
+
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor on the left side of a selection region. -->
+ <attr name="textSelectHandleLeft" format="reference" />
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor on the right side of a selection region. -->
+ <attr name="textSelectHandleRight" format="reference" />
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor for positioning the cursor within text. -->
+ <attr name="textSelectHandle" format="reference" />
+
</declare-styleable>
<!-- **************************************************************** -->
@@ -2152,6 +2167,16 @@
EditorInfo.extras} field when the input
method is connected. -->
<attr name="editorExtras" format="reference" />
+
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor on the left side of a selection region. -->
+ <attr name="textSelectHandleLeft" />
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor on the right side of a selection region. -->
+ <attr name="textSelectHandleRight" />
+ <!-- Reference to a drawable that will be used to display a text selection
+ anchor for positioning the cursor within text. -->
+ <attr name="textSelectHandle" />
</declare-styleable>
<!-- An <code>input-extras</code> is a container for extra data to supply to
an input method. Contains
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 28a7cca..2c1e91d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1255,6 +1255,9 @@
<public type="attr" name="overscrollHeader" id="0x010102c2" />
<public type="attr" name="overscrollFooter" id="0x010102c3" />
<public type="attr" name="filterTouchesWhenObscured" id="0x010102c4" />
+ <public type="attr" name="textSelectHandleLeft" id="0x010102c5" />
+ <public type="attr" name="textSelectHandleRight" id="0x010102c6" />
+ <public type="attr" name="textSelectHandle" id="0x010102c7" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 1c60ba0..e93b570 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -382,6 +382,9 @@
<style name="Widget.TextView">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:textSelectHandleLeft">?android:attr/textSelectHandleLeft</item>
+ <item name="android:textSelectHandleRight">?android:attr/textSelectHandleRight</item>
+ <item name="android:textSelectHandle">?android:attr/textSelectHandle</item>
</style>
<style name="Widget.TextView.ListSeparator">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 2311bdd..7d6ca06 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -136,6 +136,11 @@
<item name="scrollbarTrackHorizontal">@null</item>
<item name="scrollbarTrackVertical">@null</item>
+ <!-- Text selection handle attributes -->
+ <item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+
<!-- Widget styles -->
<item name="absListViewStyle">@android:style/Widget.AbsListView</item>
<item name="autoCompleteTextViewStyle">@android:style/Widget.AutoCompleteTextView</item>
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f3229c0..c6b2efb 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -590,6 +590,9 @@
break;
case MEDIA_PLAYBACK_COMPLETE:
LOGV("playback complete");
+ if (mCurrentState == MEDIA_PLAYER_IDLE) {
+ LOGE("playback complete in idle state");
+ }
if (!mLoop) {
mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index f11c0f7..371f22e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -189,6 +189,12 @@
private static final int SCAN_RESULT_BUFFER_SIZE = 512;
private boolean mNeedReconfig;
+ /**
+ * Temporary for computing UIDS that are responsible for starting WIFI.
+ * Protected by mWifiStateTracker lock.
+ */
+ private final WorkSource mTmpWorkSource = new WorkSource();
+
/*
* Last UID that asked to enable WIFI.
*/
@@ -529,9 +535,9 @@
long ident = Binder.clearCallingIdentity();
try {
if (wifiState == WIFI_STATE_ENABLED) {
- mBatteryStats.noteWifiOn(uid);
+ mBatteryStats.noteWifiOn();
} else if (wifiState == WIFI_STATE_DISABLED) {
- mBatteryStats.noteWifiOff(uid);
+ mBatteryStats.noteWifiOff();
}
} catch (RemoteException e) {
} finally {
@@ -788,9 +794,9 @@
long ident = Binder.clearCallingIdentity();
try {
if (wifiAPState == WIFI_AP_STATE_ENABLED) {
- mBatteryStats.noteWifiOn(uid);
+ mBatteryStats.noteWifiOn();
} else if (wifiAPState == WIFI_AP_STATE_DISABLED) {
- mBatteryStats.noteWifiOff(uid);
+ mBatteryStats.noteWifiOff();
}
} catch (RemoteException e) {
} finally {
@@ -1664,6 +1670,9 @@
mAlarmManager.cancel(mIdleIntent);
mDeviceIdle = false;
mScreenOff = false;
+ // Once the screen is on, we are not keeping WIFI running
+ // because of any locks so clear that tracking immediately.
+ reportStartWorkSource();
mWifiStateTracker.enableRssiPolling(true);
/* DHCP or other temporary failures in the past can prevent
* a disabled network from being connected to, enable on screen on
@@ -1705,6 +1714,7 @@
} else if (action.equals(ACTION_DEVICE_IDLE)) {
Slog.d(TAG, "got ACTION_DEVICE_IDLE");
mDeviceIdle = true;
+ reportStartWorkSource();
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1806,6 +1816,18 @@
Message.obtain(mWifiHandler, MESSAGE_ENABLE_NETWORKS).sendToTarget();
}
+ private void reportStartWorkSource() {
+ synchronized (mWifiStateTracker) {
+ mTmpWorkSource.clear();
+ if (mDeviceIdle) {
+ for (int i=0; i<mLocks.mList.size(); i++) {
+ mTmpWorkSource.add(mLocks.mList.get(i).mWorkSource);
+ }
+ }
+ mWifiStateTracker.updateBatteryWorkSourceLocked(mTmpWorkSource);
+ }
+ }
+
private void updateWifiState() {
// send a message so it's all serialized
Message.obtain(mWifiHandler, MESSAGE_UPDATE_STATE, 0, 0).sendToTarget();
@@ -1814,7 +1836,12 @@
private void doUpdateWifiState() {
boolean wifiEnabled = getPersistedWifiEnabled();
boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden;
- boolean lockHeld = mLocks.hasLocks();
+
+ boolean lockHeld;
+ synchronized (mLocks) {
+ lockHeld = mLocks.hasLocks();
+ }
+
int strongestLockMode = WifiManager.WIFI_MODE_FULL;
boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld;
@@ -1922,6 +1949,7 @@
break;
case MESSAGE_START_WIFI:
+ reportStartWorkSource();
mWifiStateTracker.setScanOnlyMode(msg.arg1 == WifiManager.WIFI_MODE_SCAN_ONLY);
mWifiStateTracker.restart();
mWifiStateTracker.setHighPerfMode(msg.arg1 ==
@@ -2198,6 +2226,10 @@
Binder.restoreCallingIdentity(ident);
}
+ // Be aggressive about adding new locks into the accounted state...
+ // we want to over-report rather than under-report.
+ reportStartWorkSource();
+
updateWifiState();
return true;
}
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index bb40967..73a5435 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -218,17 +218,17 @@
}
}
- public void noteWifiOn(int uid) {
+ public void noteWifiOn() {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteWifiOnLocked(uid);
+ mStats.noteWifiOnLocked();
}
}
- public void noteWifiOff(int uid) {
+ public void noteWifiOff() {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteWifiOffLocked(uid);
+ mStats.noteWifiOffLocked();
}
}
@@ -260,17 +260,24 @@
}
}
- public void noteWifiRunning() {
+ public void noteWifiRunning(WorkSource ws) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteWifiRunningLocked();
+ mStats.noteWifiRunningLocked(ws);
}
}
- public void noteWifiStopped() {
+ public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteWifiStoppedLocked();
+ mStats.noteWifiRunningChangedLocked(oldWs, newWs);
+ }
+ }
+
+ public void noteWifiStopped(WorkSource ws) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteWifiStoppedLocked(ws);
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 83496dc..4d8cbf0 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -55,7 +55,8 @@
public final class CallManager {
private static final String LOG_TAG ="Phone";
- private static final boolean LOCAL_DEBUG = true;
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
private static final int EVENT_DISCONNECT = 100;
private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
@@ -434,12 +435,16 @@
public void acceptCall(Call ringingCall) throws CallStateException {
Phone ringingPhone = ringingCall.getPhone();
+ if (VDBG) {
+ Log.d(LOG_TAG, "CallManager.acceptCall " + this);
+ }
+
if ( hasActiveFgCall() ) {
Phone activePhone = getActiveFgCall().getPhone();
boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
boolean sameChannel = (activePhone == ringingPhone);
- if (LOCAL_DEBUG) {
+ if (DBG) {
Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
}
@@ -587,12 +592,16 @@
* handled asynchronously.
*/
public Connection dial(Phone phone, String dialString) throws CallStateException {
+ if (VDBG) {
+ Log.d(LOG_TAG, "CallManager.dial( phone=" + phone + ", dialString="+ dialString + ")");
+ Log.d(LOG_TAG, this.toString());
+ }
if ( hasActiveFgCall() ) {
Phone activePhone = getActiveFgCall().getPhone();
boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
- if (LOCAL_DEBUG) {
- Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + (activePhone != phone));
+ if (DBG) {
+ Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone));
}
if (activePhone != phone) {
@@ -1365,7 +1374,7 @@
* return empty list if there is no active background call
*/
public List<Connection> getBgCallConnections() {
- Call bgCall = getActiveFgCall();
+ Call bgCall = getFirstActiveBgCall();
if ( bgCall != null) {
return bgCall.getConnections();
}
@@ -1504,4 +1513,46 @@
}
}
};
+
+ @Override
+ public String toString() {
+ Call call;
+ StringBuilder b = new StringBuilder();
+
+ b.append("########### Dump CallManager ############");
+ b.append("\nCM state = " + getState());
+ call = getActiveFgCall();
+ b.append("\n - FG call: " + getActiveFgCallState());
+ b.append(" from " + call.getPhone());
+ b.append("\n Conn: ").append(getFgCallConnections());
+ call = getFirstActiveBgCall();
+ b.append("\n - BG call: " + call.getState());
+ b.append(" from " + call.getPhone());
+ b.append("\n Conn: ").append(getBgCallConnections());
+ call = getFirstActiveRingingCall();
+ b.append("\n - RINGING call: " +call.getState());
+ b.append(" from " + call.getPhone());
+
+ b.append("\n");
+ for (Phone phone : getAllPhones()) {
+ if (phone != null) {
+ b.append("\n Phone: " + phone + ", name = " + phone.getPhoneName()
+ + ", state = " + phone.getState());
+ call = phone.getForegroundCall();
+ b.append("\n - FG call: ").append(call);
+ b.append(" State: ").append(call.getState());
+ b.append("\n Conn: ").append(call.getConnections());
+ call = phone.getBackgroundCall();
+ b.append("\n - BG call: ").append(call);
+ b.append(" State: ").append(call.getState());
+ b.append("\n Conn: ").append(call.getConnections());
+ call = phone.getRingingCall();
+ b.append("\n - RINGING call: ").append(call);
+ b.append( " State: ").append(call.getState());
+ b.append("\n Conn: ").append(call.getConnections());
+ }
+ }
+ b.append("\n########## End Dump CallManager ##########");
+ return b.toString();
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 22dbda3..9d27bde 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -38,6 +38,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.WorkSource;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.EventLog;
@@ -323,6 +324,21 @@
private static String[] sDnsPropNames;
/**
+ * Keep track of whether we last told the battery stats we had started.
+ */
+ private boolean mReportedRunning = false;
+
+ /**
+ * Most recently set source of starting WIFI.
+ */
+ private final WorkSource mRunningWifiUids = new WorkSource();
+
+ /**
+ * The last reported UIDs that were responsible for starting WIFI.
+ */
+ private final WorkSource mLastRunningWifiUids = new WorkSource();
+
+ /**
* A structure for supplying information about a supplicant state
* change in the STATE_CHANGE event message that comes from the
* WifiMonitor
@@ -632,12 +648,35 @@
return mRunState == RUN_STATE_STOPPED || mRunState == RUN_STATE_STOPPING;
}
- private void noteRunState() {
+ public void updateBatteryWorkSourceLocked(WorkSource newSource) {
try {
+ if (newSource != null) {
+ mRunningWifiUids.set(newSource);
+ }
if (mRunState == RUN_STATE_RUNNING) {
- mBatteryStats.noteWifiRunning();
+ if (mReportedRunning) {
+ // If the work source has changed since last time, need
+ // to remove old work from battery stats.
+ if (mLastRunningWifiUids.diff(mRunningWifiUids)) {
+ mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids,
+ mRunningWifiUids);
+ mLastRunningWifiUids.set(mRunningWifiUids);
+ }
+ } else {
+ // Now being started, report it.
+ mBatteryStats.noteWifiRunning(mRunningWifiUids);
+ mLastRunningWifiUids.set(mRunningWifiUids);
+ mReportedRunning = true;
+ }
} else if (mRunState == RUN_STATE_STOPPED) {
- mBatteryStats.noteWifiStopped();
+ if (mReportedRunning) {
+ // Last reported we were running, time to stop.
+ mBatteryStats.noteWifiStopped(mLastRunningWifiUids);
+ mLastRunningWifiUids.clear();
+ mReportedRunning = false;
+ }
+ } else {
+ // State in transition -- nothing to update yet.
}
} catch (RemoteException ignore) {
}
@@ -801,7 +840,9 @@
switch (msg.what) {
case EVENT_SUPPLICANT_CONNECTION:
mRunState = RUN_STATE_RUNNING;
- noteRunState();
+ synchronized (this) {
+ updateBatteryWorkSourceLocked(null);
+ }
checkUseStaticIp();
/* Reset notification state on new connection */
resetNotificationTimer();
@@ -875,7 +916,9 @@
case EVENT_SUPPLICANT_DISCONNECT:
mRunState = RUN_STATE_STOPPED;
- noteRunState();
+ synchronized (this) {
+ updateBatteryWorkSourceLocked(null);
+ }
boolean died = mWifiState.get() != WIFI_STATE_DISABLED &&
mWifiState.get() != WIFI_STATE_DISABLING;
if (died) {
@@ -1267,7 +1310,9 @@
mWM.setWifiEnabled(true);
break;
}
- noteRunState();
+ synchronized (this) {
+ updateBatteryWorkSourceLocked(null);
+ }
break;
case EVENT_PASSWORD_KEY_MAY_BE_INCORRECT: