diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/os/BatteryStats.java | 112 | ||||
| -rw-r--r-- | core/java/android/os/IPowerManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/PowerManager.java | 25 | ||||
| -rw-r--r-- | core/java/android/os/PowerManagerInternal.java | 4 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 72 |
5 files changed, 186 insertions, 28 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index cab03da..26e6b85 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -613,6 +613,9 @@ public abstract class BatteryStats implements Parcelable { if ((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) { out.append('p'); } + if ((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0) { + out.append('i'); + } switch ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) { case Display.STATE_OFF: out.append('F'); break; case Display.STATE_ON: out.append('O'); break; @@ -622,6 +625,9 @@ public abstract class BatteryStats implements Parcelable { if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) { out.append('P'); } + if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0) { + out.append('I'); + } out.append('-'); appendHex(level, 4, out); out.append('-'); @@ -648,6 +654,9 @@ public abstract class BatteryStats implements Parcelable { case 'p': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE) << STEP_LEVEL_INITIAL_MODE_SHIFT); break; + case 'i': out |= (((long)STEP_LEVEL_MODE_DEVICE_IDLE) + << STEP_LEVEL_INITIAL_MODE_SHIFT); + break; case 'F': out |= (((long)Display.STATE_OFF-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT); break; case 'O': out |= (((long)Display.STATE_ON-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT); @@ -660,6 +669,9 @@ public abstract class BatteryStats implements Parcelable { case 'P': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE) << STEP_LEVEL_MODIFIED_MODE_SHIFT); break; + case 'I': out |= (((long)STEP_LEVEL_MODE_DEVICE_IDLE) + << STEP_LEVEL_MODIFIED_MODE_SHIFT); + break; } } i++; @@ -820,11 +832,18 @@ public abstract class BatteryStats implements Parcelable { } } + public static final class PackageChange { + public String mPackageName; + public boolean mUpdate; + public int mVersionCode; + } + public static final class DailyItem { public long mStartTime; public long mEndTime; public LevelStepTracker mDischargeSteps; public LevelStepTracker mChargeSteps; + public ArrayList<PackageChange> mPackageChanges; } public abstract DailyItem getDailyItemLocked(int daysAgo); @@ -1524,6 +1543,23 @@ public abstract class BatteryStats implements Parcelable { public abstract int getDeviceIdleModeEnabledCount(int which); /** + * Returns the time in microseconds that device has been in idling while on + * battery. This is broader than {@link #getDeviceIdleModeEnabledTime} -- it + * counts all of the time that we consider the device to be idle, whether or not + * it is currently in the actual device idle mode. + * + * {@hide} + */ + public abstract long getDeviceIdlingTime(long elapsedRealtimeUs, int which); + + /** + * Returns the number of times that the devie has started idling. + * + * {@hide} + */ + public abstract int getDeviceIdlingCount(int which); + + /** * Returns the number of times that connectivity state changed. * * {@hide} @@ -2069,45 +2105,44 @@ public abstract class BatteryStats implements Parcelable { // Step duration mode: power save is on. public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04; + // Step duration mode: device is currently in idle mode. + public static final int STEP_LEVEL_MODE_DEVICE_IDLE = 0x08; + public static final int[] STEP_LEVEL_MODES_OF_INTEREST = new int[] { STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, + STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE, + STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE, STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, - STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, - STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE, + STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE, + STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE, }; public static final int[] STEP_LEVEL_MODE_VALUES = new int[] { (Display.STATE_OFF-1), (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE, + (Display.STATE_OFF-1)|STEP_LEVEL_MODE_DEVICE_IDLE, (Display.STATE_ON-1), (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE, (Display.STATE_DOZE-1), (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE, (Display.STATE_DOZE_SUSPEND-1), (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE, + (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_DEVICE_IDLE, }; public static final String[] STEP_LEVEL_MODE_LABELS = new String[] { "screen off", "screen off power save", + "screen off device idle", "screen on", "screen on power save", "screen doze", "screen doze power save", "screen doze-suspend", "screen doze-suspend power save", - }; - public static final String[] STEP_LEVEL_MODE_TAGS = new String[] { - "off", - "off-save", - "on", - "on-save", - "doze", - "doze-save", - "susp", - "susp-save", + "screen doze-suspend device idle", }; /** @@ -2140,6 +2175,8 @@ public abstract class BatteryStats implements Parcelable { */ public abstract LevelStepTracker getDailyChargeLevelStepTracker(); + public abstract ArrayList<PackageChange> getDailyPackageChanges(); + public abstract Map<String, ? extends Timer> getWakeupReasonStats(); public abstract Map<String, ? extends Timer> getKernelWakelockStats(); @@ -2338,6 +2375,7 @@ public abstract class BatteryStats implements Parcelable { final long interactiveTime = getInteractiveTime(rawRealtime, which); final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which); final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which); + final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which); final int connChanges = getNumConnectivityChange(which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); @@ -2410,7 +2448,8 @@ public abstract class BatteryStats implements Parcelable { 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000, getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000, powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000, - getDeviceIdleModeEnabledCount(which)); + getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000, + getDeviceIdlingCount(which)); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -2879,6 +2918,7 @@ public abstract class BatteryStats implements Parcelable { final long interactiveTime = getInteractiveTime(rawRealtime, which); final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which); final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which); + final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); @@ -2923,10 +2963,21 @@ public abstract class BatteryStats implements Parcelable { sb.append(")"); pw.println(sb.toString()); } - if (deviceIdleModeEnabledTime != 0) { + if (deviceIdlingTime != 0) { sb.setLength(0); sb.append(prefix); sb.append(" Device idling: "); + formatTimeMs(sb, deviceIdlingTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime)); + sb.append(") "); sb.append(getDeviceIdlingCount(which)); + sb.append("x"); + pw.println(sb.toString()); + } + if (deviceIdleModeEnabledTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Idle mode time: "); formatTimeMs(sb, deviceIdleModeEnabledTime / 1000); sb.append("("); sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime)); @@ -4403,6 +4454,11 @@ public abstract class BatteryStats implements Parcelable { } else { lineArgs[3] = ""; } + if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) { + lineArgs[3] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-"; + } else { + lineArgs[3] = ""; + } dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs); } else { pw.print(prefix); @@ -4427,6 +4483,12 @@ public abstract class BatteryStats implements Parcelable { ? "power-save-on" : "power-save-off"); haveModes = true; } + if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) { + pw.print(haveModes ? ", " : " ("); + pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 + ? "device-idle-on" : "device-idle-off"); + haveModes = true; + } if (haveModes) { pw.print(")"); } @@ -4558,6 +4620,23 @@ public abstract class BatteryStats implements Parcelable { } } + private void dumpDailyPackageChanges(PrintWriter pw, String prefix, + ArrayList<PackageChange> changes) { + if (changes == null) { + return; + } + pw.print(prefix); pw.println("Package changes:"); + for (int i=0; i<changes.size(); i++) { + PackageChange pc = changes.get(i); + if (pc.mUpdate) { + pw.print(prefix); pw.print(" Update "); pw.print(pc.mPackageName); + pw.print(" vers="); pw.println(pc.mVersionCode); + } else { + pw.print(prefix); pw.print(" Uninstall "); pw.println(pc.mPackageName); + } + } + } + /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * @@ -4688,7 +4767,8 @@ public abstract class BatteryStats implements Parcelable { int[] outInt = new int[1]; LevelStepTracker dsteps = getDailyDischargeLevelStepTracker(); LevelStepTracker csteps = getDailyChargeLevelStepTracker(); - if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0) { + ArrayList<PackageChange> pkgc = getDailyPackageChanges(); + if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) { if ((flags&DUMP_DAILY_ONLY) != 0) { if (dumpDurationSteps(pw, " ", " Current daily discharge step durations:", dsteps, false)) { @@ -4700,6 +4780,7 @@ public abstract class BatteryStats implements Parcelable { dumpDailyLevelStepSummary(pw, " ", "Charge", csteps, sb, outInt); } + dumpDailyPackageChanges(pw, " ", pkgc); } else { pw.println(" Current daily steps:"); dumpDailyLevelStepSummary(pw, " ", "Discharge", dsteps, @@ -4731,6 +4812,7 @@ public abstract class BatteryStats implements Parcelable { dumpDailyLevelStepSummary(pw, " ", "Charge", dit.mChargeSteps, sb, outInt); } + dumpDailyPackageChanges(pw, " ", dit.mPackageChanges); } else { dumpDailyLevelStepSummary(pw, " ", "Discharge", dit.mDischargeSteps, sb, outInt); diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 16dac7d..418641f 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -43,6 +43,7 @@ interface IPowerManager boolean isInteractive(); boolean isPowerSaveMode(); boolean setPowerSaveMode(boolean mode); + boolean isDeviceIdleMode(); void reboot(boolean confirm, String reason, boolean wait); void shutdown(boolean confirm, boolean wait); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index de970cb..81745b3 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -856,6 +856,23 @@ public final class PowerManager { } /** + * Returns true if the device is currently in idle mode. This happens when a device + * has been sitting unused and unmoving for a sufficiently long period of time, so that + * it decides to go into a lower power-use state. This may involve things like turning + * off network access to apps. You can monitor for changes to this state with + * {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}. + * + * @return Returns true if currently in low power mode, else false. + */ + public boolean isDeviceIdleMode() { + try { + return mService.isDeviceIdleMode(); + } catch (RemoteException e) { + return false; + } + } + + /** * Turn off the device. * * @param confirm If true, shows a shutdown confirmation dialog. @@ -879,6 +896,14 @@ public final class PowerManager { = "android.os.action.POWER_SAVE_MODE_CHANGED"; /** + * Intent that is broadcast when the state of {@link #isDeviceIdleMode()} changes. + * This broadcast is only sent to registered receivers. + */ + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_DEVICE_IDLE_MODE_CHANGED + = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change. * This broadcast is only sent to registered receivers. * diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 6f31768..00ab262 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -117,7 +117,7 @@ public abstract class PowerManagerInternal { /** * Used by the dream manager to override certain properties while dozing. * - * @param screenState The overridden screen state, or {@link Display.STATE_UNKNOWN} + * @param screenState The overridden screen state, or {@link Display#STATE_UNKNOWN} * to disable the override. * @param screenBrightness The overridden screen brightness, or * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override. @@ -132,4 +132,6 @@ public abstract class PowerManagerInternal { public interface LowPowerModeListener { public void onLowPowerModeChanged(boolean enabled); } + + public abstract void setDeviceIdleMode(boolean enabled); } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3fca463..87fcd81 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3348,7 +3348,7 @@ public class Editor { // Minimum touch target size for handles private int mMinSize; // Indicates the line of text that the handle is on. - protected int mLine = -1; + protected int mPrevLine = -1; public HandleView(Drawable drawableLtr, Drawable drawableRtl) { super(mTextView.getContext()); @@ -3499,7 +3499,7 @@ public class Editor { addPositionToTouchUpFilter(offset); } final int line = layout.getLineForOffset(offset); - mLine = line; + mPrevLine = line; mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX - getHorizontalOffset() + getCursorOffset()); @@ -3839,19 +3839,22 @@ public class Editor { public void updatePosition(float x, float y) { final int trueOffset = mTextView.getOffsetForPosition(x, y); final int currLine = mTextView.getLineAtCoordinate(y); - int offset = trueOffset; - boolean positionCursor = false; + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return; + + boolean positionCursor = false; + int offset = trueOffset; int end = getWordEnd(offset, true); int start = getWordStart(offset); if (offset < mPrevOffset) { // User is increasing the selection. - if (!mInWord || currLine < mLine) { + if (!mInWord || currLine < mPrevLine) { // We're not in a word, or we're on a different line so we'll expand by // word. First ensure the user has at least entered the next word. int offsetToWord = Math.min((end - start) / 2, 2); - if (offset <= end - offsetToWord || currLine < mLine) { + if (offset <= end - offsetToWord || currLine < mPrevLine) { offset = start; } else { offset = mPrevOffset; @@ -3863,7 +3866,7 @@ public class Editor { positionCursor = true; } else if (offset - mTouchWordOffset > mPrevOffset) { // User is shrinking the selection. - if (currLine > mLine) { + if (currLine > mPrevLine) { // We're on a different line, so we'll snap to word boundaries. offset = end; } @@ -3878,7 +3881,7 @@ public class Editor { final int selectionEnd = mTextView.getSelectionEnd(); if (offset >= selectionEnd) { // We can't cross the handles so let's just constrain the Y value. - int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x); + int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x); if (alteredOffset >= selectionEnd) { // Can't pass the other drag handle. offset = Math.max(0, selectionEnd - 1); @@ -3939,6 +3942,10 @@ public class Editor { public void updatePosition(float x, float y) { final int trueOffset = mTextView.getOffsetForPosition(x, y); final int currLine = mTextView.getLineAtCoordinate(y); + + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return; + int offset = trueOffset; boolean positionCursor = false; @@ -3947,11 +3954,11 @@ public class Editor { if (offset > mPrevOffset) { // User is increasing the selection. - if (!mInWord || currLine > mLine) { + if (!mInWord || currLine > mPrevLine) { // We're not in a word, or we're on a different line so we'll expand by // word. First ensure the user has at least entered the next word. int midPoint = Math.min((end - start) / 2, 2); - if (offset >= start + midPoint || currLine > mLine) { + if (offset >= start + midPoint || currLine > mPrevLine) { offset = end; } else { offset = mPrevOffset; @@ -3963,7 +3970,7 @@ public class Editor { positionCursor = true; } else if (offset + mTouchWordOffset < mPrevOffset) { // User is shrinking the selection. - if (currLine > mLine) { + if (currLine > mPrevLine) { // We're on a different line, so we'll snap to word boundaries. offset = getWordStart(offset); } @@ -3977,7 +3984,7 @@ public class Editor { final int selectionStart = mTextView.getSelectionStart(); if (offset <= selectionStart) { // We can't cross the handles so let's just constrain the Y value. - int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x); + int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x); int length = mTextView.getText().length(); if (alteredOffset <= selectionStart) { // Can't pass the other drag handle. @@ -4002,6 +4009,36 @@ public class Editor { } /** + * Checks whether selection is happening on a different line than previous and + * if that line only contains whitespace up to the touch location. + * + * @param prevLine The previous line the selection was on. + * @param currLine The current line being selected. + * @param offset The offset in the text where the touch occurred. + * @return Whether or not it was just a white space line being selected. + */ + private boolean isWhitespaceLine(int prevLine, int currLine, int offset) { + if (prevLine == currLine) { + // Same line; don't care. + return false; + } + CharSequence text = mTextView.getText(); + if (offset == text.length()) { + // No character at the last position. + return false; + } + int lineEndOffset = mTextView.getLayout().getLineEnd(currLine); + for (int cp, i = offset; i < lineEndOffset; i += Character.charCount(cp)) { + cp = Character.codePointAt(text, i); + if (!Character.isSpaceChar(cp) && !Character.isWhitespace(cp)) { + // There are non white space chars on the line. + return false; + } + } + return true; + } + + /** * A CursorController instance can be used to control a cursor in the text. */ private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener { @@ -4081,6 +4118,8 @@ public class Editor { private int mStartOffset = -1; // Indicates whether the user is selecting text and using the drag accelerator. private boolean mDragAcceleratorActive; + // Indicates the line of text the drag accelerator is on. + private int mPrevLine = -1; SelectionModifierCursorController() { resetTouchOffsets(); @@ -4173,6 +4212,8 @@ public class Editor { } } + // New selection, reset line. + mPrevLine = mTextView.getLineAtCoordinate(y); mDownPositionX = x; mDownPositionY = y; mGestureStayedInTapRegion = true; @@ -4229,6 +4270,13 @@ public class Editor { if (my > fingerOffset) my -= fingerOffset; offset = mTextView.getOffsetForPosition(mx, my); + int currLine = mTextView.getLineAtCoordinate(my); + + // Don't select white space on different lines. + if (isWhitespaceLine(mPrevLine, currLine, offset)) return; + + mPrevLine = currLine; + // Perform the check for closeness at edge of view, if we're very close // don't adjust the offset to be in front of the finger - otherwise the // user can't select words at the edge. |
