diff options
Diffstat (limited to 'core/java')
21 files changed, 570 insertions, 378 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 66b82eb..b4b3c99 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3618,13 +3618,15 @@ public class Activity extends ContextThemeWrapper } // Get the primary color and update the RecentsActivityValues for this activity - TypedArray a = getTheme().obtainStyledAttributes(com.android.internal.R.styleable.Theme); - int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0); - a.recycle(); - if (colorPrimary != 0) { - ActivityManager.RecentsActivityValues v = new ActivityManager.RecentsActivityValues(); - v.colorPrimary = colorPrimary; - setRecentsActivityValues(v); + if (theme != null) { + TypedArray a = theme.obtainStyledAttributes(com.android.internal.R.styleable.Theme); + int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0); + a.recycle(); + if (colorPrimary != 0) { + ActivityManager.RecentsActivityValues v = new ActivityManager.RecentsActivityValues(); + v.colorPrimary = colorPrimary; + setRecentsActivityValues(v); + } } } diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 347de97..8ab9ac3 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -43,4 +43,5 @@ interface IUiAutomationConnection { WindowContentFrameStats getWindowContentFrameStats(int windowId); void clearWindowAnimationFrameStats(); WindowAnimationFrameStats getWindowAnimationFrameStats(); + void executeShellCommand(String command, in ParcelFileDescriptor fd); } diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index aab6ed8..db91742a 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -44,8 +44,8 @@ public class KeyguardManager { * you to disable / reenable the keyguard. */ public class KeyguardLock { - private IBinder mToken = new Binder(); - private String mTag; + private final IBinder mToken = new Binder(); + private final String mTag; KeyguardLock(String tag) { mTag = tag; diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 9405325..64e3484 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -26,6 +26,7 @@ import android.graphics.Canvas; import android.graphics.Point; import android.hardware.display.DisplayManagerGlobal; import android.os.Looper; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; @@ -40,7 +41,9 @@ import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.IAccessibilityInteractionConnection; +import libcore.io.IoUtils; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; @@ -840,6 +843,44 @@ public final class UiAutomation { return null; } + /** + * Executes a shell command. This method returs a file descriptor that points + * to the standard output stream. The command execution is similar to running + * "adb shell <command>" from a host connected to the device. + * <p> + * <strong>Note:</strong> It is your responsibility to close the retunred file + * descriptor once you are done reading. + * </p> + * + * @param command The command to execute. + * @return A file descriptor to the standard output stream. + */ + public ParcelFileDescriptor executeShellCommand(String command) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + + ParcelFileDescriptor source = null; + ParcelFileDescriptor sink = null; + + try { + ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); + source = pipe[0]; + sink = pipe[1]; + + // Calling out without a lock held. + mUiAutomationConnection.executeShellCommand(command, sink); + } catch (IOException ioe) { + Log.e(LOG_TAG, "Error executing shell command!", ioe); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error executing shell command!", re); + } finally { + IoUtils.closeQuietly(sink); + } + + return source; + } + private static float getDegreesForRotation(int value) { switch (value) { case Surface.ROTATION_90: { diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index fa40286..81bcb39 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -23,6 +23,7 @@ import android.graphics.Bitmap; import android.hardware.input.InputManager; import android.os.Binder; import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -33,6 +34,12 @@ import android.view.WindowAnimationFrameStats; import android.view.WindowContentFrameStats; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.IAccessibilityManager; +import libcore.io.IoUtils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** * This is a remote object that is passed from the shell to an instrumentation @@ -50,8 +57,8 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Service.WINDOW_SERVICE)); - private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub.asInterface( - ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); + private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub + .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); private final Object mLock = new Object(); @@ -220,6 +227,41 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { } @Override + public void executeShellCommand(String command, ParcelFileDescriptor sink) + throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + + InputStream in = null; + OutputStream out = null; + + try { + java.lang.Process process = Runtime.getRuntime().exec(command); + + in = process.getInputStream(); + out = new FileOutputStream(sink.getFileDescriptor()); + + final byte[] buffer = new byte[8192]; + while (true) { + final int readByteCount = in.read(buffer); + if (readByteCount < 0) { + break; + } + out.write(buffer, 0, readByteCount); + } + } catch (IOException ioe) { + throw new RuntimeException("Error running shell command", ioe); + } finally { + IoUtils.closeQuietly(in); + IoUtils.closeQuietly(out); + IoUtils.closeQuietly(sink); + } + } + + @Override public void shutdown() { synchronized (mLock) { if (isConnectedLocked()) { diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index f161f3a..0ca9161 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -458,7 +458,19 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { * brightness</p> * <p>For example, if EV step is 0.333, '6' will mean an * exposure compensation of +2 EV; -3 will mean an exposure - * compensation of -1</p> + * compensation of -1 EV. Note that this control will only be effective + * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when + * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p> + * <p>In the event of exposure compensation value being changed, camera device + * may take several frames to reach the newly requested exposure target. + * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING + * state. Once the new exposure target is reached, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} will + * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or + * FLASH_REQUIRED (if the scene is too dark for still capture).</p> + * + * @see CaptureRequest#CONTROL_AE_LOCK + * @see CaptureRequest#CONTROL_AE_MODE + * @see CaptureResult#CONTROL_AE_STATE */ public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION = new Key<Integer>("android.control.aeExposureCompensation", int.class); @@ -469,6 +481,8 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { * <p>Note that even when AE is locked, the flash may be * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH / * ON_AUTO_FLASH_REDEYE.</p> + * <p>When {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation} is changed, even if the AE lock + * is ON, the camera device will still adjust its exposure value.</p> * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) * when AE is already locked, the camera device will not change the exposure time * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}) @@ -477,6 +491,7 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p> * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p> * + * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION * @see CaptureRequest#CONTROL_AE_MODE * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER * @see CaptureResult#CONTROL_AE_STATE diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 51ea447..42a3de8 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -275,7 +275,19 @@ public final class CaptureResult extends CameraMetadata { * brightness</p> * <p>For example, if EV step is 0.333, '6' will mean an * exposure compensation of +2 EV; -3 will mean an exposure - * compensation of -1</p> + * compensation of -1 EV. Note that this control will only be effective + * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when + * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p> + * <p>In the event of exposure compensation value being changed, camera device + * may take several frames to reach the newly requested exposure target. + * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING + * state. Once the new exposure target is reached, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} will + * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or + * FLASH_REQUIRED (if the scene is too dark for still capture).</p> + * + * @see CaptureRequest#CONTROL_AE_LOCK + * @see CaptureRequest#CONTROL_AE_MODE + * @see CaptureResult#CONTROL_AE_STATE */ public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION = new Key<Integer>("android.control.aeExposureCompensation", int.class); @@ -286,6 +298,8 @@ public final class CaptureResult extends CameraMetadata { * <p>Note that even when AE is locked, the flash may be * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH / * ON_AUTO_FLASH_REDEYE.</p> + * <p>When {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation} is changed, even if the AE lock + * is ON, the camera device will still adjust its exposure value.</p> * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) * when AE is already locked, the camera device will not change the exposure time * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}) @@ -294,6 +308,7 @@ public final class CaptureResult extends CameraMetadata { * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p> * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p> * + * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION * @see CaptureRequest#CONTROL_AE_MODE * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER * @see CaptureResult#CONTROL_AE_STATE diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index cec90cd..e58c54d 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -156,6 +156,9 @@ public abstract class DisplayManagerInternal { // If true, enables automatic brightness control. public boolean useAutoBrightness; + //If true, scales the brightness to half of desired. + public boolean lowPowerMode; + // If true, prevents the screen from completely turning on if it is currently off. // The display does not enter a "ready" state if this flag is true and screen on is // blocked. The window manager policy blocks screen on while it prepares the keyguard to @@ -203,6 +206,7 @@ public abstract class DisplayManagerInternal { screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment; useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; + lowPowerMode = other.lowPowerMode; } @Override @@ -218,7 +222,8 @@ public abstract class DisplayManagerInternal { && screenBrightness == other.screenBrightness && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment && useAutoBrightness == other.useAutoBrightness - && blockScreenOn == other.blockScreenOn; + && blockScreenOn == other.blockScreenOn + && lowPowerMode == other.lowPowerMode; } @Override @@ -233,7 +238,8 @@ public abstract class DisplayManagerInternal { + ", screenBrightness=" + screenBrightness + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment + ", useAutoBrightness=" + useAutoBrightness - + ", blockScreenOn=" + blockScreenOn; + + ", blockScreenOn=" + blockScreenOn + + ", lowPowerMode=" + lowPowerMode; } } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 8b7467f..4857533 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Formatter; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,6 +31,8 @@ import android.telephony.SignalStrength; import android.text.format.DateFormat; import android.util.Printer; import android.util.SparseArray; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; import android.util.TimeUtils; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -537,6 +540,7 @@ public abstract class BatteryStats implements Parcelable { public static final byte CMD_START = 4; public static final byte CMD_CURRENT_TIME = 5; public static final byte CMD_OVERFLOW = 6; + public static final byte CMD_RESET = 7; public byte cmd = CMD_NULL; @@ -620,6 +624,8 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_SYNC = 0x0004; // Number of event types. public static final int EVENT_COUNT = 0x0005; + // Mask to extract out only the type part of the event. + public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START; public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH; @@ -684,7 +690,7 @@ public abstract class BatteryStats implements Parcelable { dest.writeInt(eventCode); eventTag.writeToParcel(dest, flags); } - if (cmd == CMD_CURRENT_TIME) { + if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) { dest.writeLong(currentTime); } } @@ -722,7 +728,7 @@ public abstract class BatteryStats implements Parcelable { eventCode = EVENT_NONE; eventTag = null; } - if (cmd == CMD_CURRENT_TIME) { + if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) { currentTime = src.readLong(); } else { currentTime = 0; @@ -833,7 +839,59 @@ public abstract class BatteryStats implements Parcelable { return true; } } - + + public final static class HistoryEventTracker { + private final HashMap<String, SparseIntArray>[] mActiveEvents + = (HashMap<String, SparseIntArray>[]) new HashMap[HistoryItem.EVENT_COUNT]; + + public boolean updateState(int code, String name, int uid, int poolIdx) { + if ((code&HistoryItem.EVENT_FLAG_START) != 0) { + int idx = code&HistoryItem.EVENT_TYPE_MASK; + HashMap<String, SparseIntArray> active = mActiveEvents[idx]; + if (active == null) { + active = new HashMap<String, SparseIntArray>(); + mActiveEvents[idx] = active; + } + SparseIntArray uids = active.get(name); + if (uids == null) { + uids = new SparseIntArray(); + active.put(name, uids); + } + if (uids.indexOfKey(uid) >= 0) { + // Already set, nothing to do! + return false; + } + uids.put(uid, poolIdx); + } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) { + int idx = code&HistoryItem.EVENT_TYPE_MASK; + HashMap<String, SparseIntArray> active = mActiveEvents[idx]; + if (active == null) { + // not currently active, nothing to do. + return false; + } + SparseIntArray uids = active.get(name); + if (uids == null) { + // not currently active, nothing to do. + return false; + } + idx = uids.indexOfKey(uid); + if (idx < 0) { + // not currently active, nothing to do. + return false; + } + uids.removeAt(idx); + if (uids.size() <= 0) { + active.remove(name); + } + } + return true; + } + + public HashMap<String, SparseIntArray> getStateForEvent(int code) { + return mActiveEvents[code]; + } + } + public static final class BitDescription { public final int mask; public final int shift; @@ -861,7 +919,7 @@ public abstract class BatteryStats implements Parcelable { this.shortValues = shortValues; } } - + public abstract int getHistoryTotalSize(); public abstract int getHistoryUsedSize(); @@ -2958,10 +3016,14 @@ public abstract class BatteryStats implements Parcelable { pw.print(":"); } pw.println("START"); - } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) { + } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME + || rec.cmd == HistoryItem.CMD_RESET) { if (checkin) { pw.print(":"); } + if (rec.cmd == HistoryItem.CMD_RESET) { + pw.print("RESET:"); + } pw.print("TIME:"); if (checkin) { pw.println(rec.currentTime); @@ -3187,6 +3249,86 @@ public abstract class BatteryStats implements Parcelable { public static final int DUMP_INCLUDE_HISTORY = 1<<3; public static final int DUMP_VERBOSE = 1<<4; + private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) { + final HistoryPrinter hprinter = new HistoryPrinter(); + final HistoryItem rec = new HistoryItem(); + long lastTime = -1; + long baseTime = -1; + boolean printed = false; + HistoryEventTracker tracker = null; + while (getNextHistoryLocked(rec)) { + lastTime = rec.time; + if (baseTime < 0) { + baseTime = lastTime; + } + if (rec.time >= histStart) { + if (histStart >= 0 && !printed) { + if (rec.cmd == HistoryItem.CMD_CURRENT_TIME + || rec.cmd == HistoryItem.CMD_RESET) { + printed = true; + } else if (rec.currentTime != 0) { + printed = true; + byte cmd = rec.cmd; + rec.cmd = HistoryItem.CMD_CURRENT_TIME; + if (checkin) { + pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); + pw.print(HISTORY_DATA); pw.print(','); + } + hprinter.printNextItem(pw, rec, baseTime, checkin, + (flags&DUMP_VERBOSE) != 0); + rec.cmd = cmd; + } + if (tracker != null) { + int oldCode = rec.eventCode; + HistoryTag oldTag = rec.eventTag; + rec.eventTag = new HistoryTag(); + for (int i=0; i<HistoryItem.EVENT_COUNT; i++) { + HashMap<String, SparseIntArray> active + = tracker.getStateForEvent(i); + if (active == null) { + continue; + } + for (HashMap.Entry<String, SparseIntArray> ent + : active.entrySet()) { + SparseIntArray uids = ent.getValue(); + for (int j=0; j<uids.size(); j++) { + rec.eventCode = i; + rec.eventTag.string = ent.getKey(); + rec.eventTag.uid = uids.keyAt(j); + rec.eventTag.poolIdx = uids.valueAt(j); + if (checkin) { + pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); + pw.print(HISTORY_DATA); pw.print(','); + } + hprinter.printNextItem(pw, rec, baseTime, checkin, + (flags&DUMP_VERBOSE) != 0); + } + } + } + rec.eventCode = oldCode; + rec.eventTag = oldTag; + tracker = null; + } + } + if (checkin) { + pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); + pw.print(HISTORY_DATA); pw.print(','); + } + hprinter.printNextItem(pw, rec, baseTime, checkin, + (flags&DUMP_VERBOSE) != 0); + } else if (rec.eventCode != HistoryItem.EVENT_NONE) { + if (tracker == null) { + tracker = new HistoryEventTracker(); + } + tracker.updateState(rec.eventCode, rec.eventTag.string, + rec.eventTag.uid, rec.eventTag.poolIdx); + } + } + if (histStart >= 0) { + pw.print(checkin ? "NEXT: " : " NEXT: "); pw.println(lastTime+1); + } + } + /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * @@ -3200,9 +3342,6 @@ public abstract class BatteryStats implements Parcelable { (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0; if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) { - long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); - - final HistoryItem rec = new HistoryItem(); final long historyTotalSize = getHistoryTotalSize(); final long historyUsedSize = getHistoryUsedSize(); if (startIteratingHistoryLocked()) { @@ -3218,35 +3357,7 @@ public abstract class BatteryStats implements Parcelable { pw.print(" strings using "); printSizeValue(pw, getHistoryStringPoolBytes()); pw.println("):"); - HistoryPrinter hprinter = new HistoryPrinter(); - long lastTime = -1; - long baseTime = -1; - boolean printed = false; - while (getNextHistoryLocked(rec)) { - lastTime = rec.time; - if (baseTime < 0) { - baseTime = lastTime; - } - if (rec.time >= histStart) { - if (histStart >= 0 && !printed) { - if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) { - printed = true; - } else if (rec.currentTime != 0) { - printed = true; - byte cmd = rec.cmd; - rec.cmd = HistoryItem.CMD_CURRENT_TIME; - hprinter.printNextItem(pw, rec, baseTime, false, - (flags&DUMP_VERBOSE) != 0); - rec.cmd = cmd; - } - } - hprinter.printNextItem(pw, rec, baseTime, false, - (flags&DUMP_VERBOSE) != 0); - } - } - if (histStart >= 0) { - pw.print(" NEXT: "); pw.println(lastTime+1); - } + dumpHistoryLocked(pw, flags, histStart, false); pw.println(); } finally { finishIteratingHistoryLocked(); @@ -3255,6 +3366,7 @@ public abstract class BatteryStats implements Parcelable { if (startIteratingOldHistoryLocked()) { try { + final HistoryItem rec = new HistoryItem(); pw.println("Old battery History:"); HistoryPrinter hprinter = new HistoryPrinter(); long baseTime = -1; @@ -3348,7 +3460,6 @@ public abstract class BatteryStats implements Parcelable { (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0; if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) { - final HistoryItem rec = new HistoryItem(); if (startIteratingHistoryLocked()) { try { for (int i=0; i<getHistoryStringPoolSize(); i++) { @@ -3365,37 +3476,7 @@ public abstract class BatteryStats implements Parcelable { pw.print("\""); pw.println(); } - HistoryPrinter hprinter = new HistoryPrinter(); - long lastTime = -1; - long baseTime = -1; - boolean printed = false; - while (getNextHistoryLocked(rec)) { - lastTime = rec.time; - if (baseTime < 0) { - baseTime = lastTime; - } - if (rec.time >= histStart) { - if (histStart >= 0 && !printed) { - if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) { - printed = true; - } else if (rec.currentTime != 0) { - printed = true; - byte cmd = rec.cmd; - rec.cmd = HistoryItem.CMD_CURRENT_TIME; - pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); - pw.print(HISTORY_DATA); pw.print(','); - hprinter.printNextItem(pw, rec, baseTime, true, false); - rec.cmd = cmd; - } - } - pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); - pw.print(HISTORY_DATA); pw.print(','); - hprinter.printNextItem(pw, rec, baseTime, true, false); - } - } - if (histStart >= 0) { - pw.print("NEXT: "); pw.println(lastTime+1); - } + dumpHistoryLocked(pw, flags, histStart, true); } finally { finishIteratingHistoryLocked(); } diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index a675821..be3b6ce 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -21,6 +21,8 @@ import android.graphics.CanvasProperty; import android.graphics.Paint; import android.util.SparseIntArray; +import com.android.internal.util.VirtualRefBasePtr; + import java.lang.ref.WeakReference; /** @@ -70,28 +72,32 @@ public final class RenderNodeAnimator { public static final int DELTA_TYPE_DELTA = 1; private RenderNode mTarget; - private long mNativePtr; + private VirtualRefBasePtr mNativePtr; public int mapViewPropertyToRenderProperty(int viewProperty) { return sViewPropertyAnimatorMap.get(viewProperty); } public RenderNodeAnimator(int property, int deltaType, float deltaValue) { - mNativePtr = nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), - property, deltaType, deltaValue); + init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), + property, deltaType, deltaValue)); } public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) { - mNativePtr = nCreateCanvasPropertyFloatAnimator( + init(nCreateCanvasPropertyFloatAnimator( new WeakReference<RenderNodeAnimator>(this), - property.getNativeContainer(), deltaType, deltaValue); + property.getNativeContainer(), deltaType, deltaValue)); } public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, int deltaType, float deltaValue) { - mNativePtr = nCreateCanvasPropertyPaintAnimator( + init(nCreateCanvasPropertyPaintAnimator( new WeakReference<RenderNodeAnimator>(this), - property.getNativeContainer(), paintField, deltaType, deltaValue); + property.getNativeContainer(), paintField, deltaType, deltaValue)); + } + + private void init(long ptr) { + mNativePtr = new VirtualRefBasePtr(ptr); } public void start(View target) { @@ -115,11 +121,11 @@ public final class RenderNodeAnimator { } public void setDuration(int duration) { - nSetDuration(mNativePtr, duration); + nSetDuration(mNativePtr.get(), duration); } long getNativeAnimator() { - return mNativePtr; + return mNativePtr.get(); } private void onFinished() { @@ -134,16 +140,6 @@ public final class RenderNodeAnimator { } } - @Override - protected void finalize() throws Throwable { - try { - nUnref(mNativePtr); - mNativePtr = 0; - } finally { - super.finalize(); - } - } - private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, int property, int deltaValueType, float deltaValue); private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis, @@ -151,5 +147,4 @@ public final class RenderNodeAnimator { private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis, long canvasProperty, int paintField, int deltaValueType, float deltaValue); private static native void nSetDuration(long nativePtr, int duration); - private static native void nUnref(long nativePtr); } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index e1c6f52..be0c27d 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -49,7 +49,6 @@ import android.view.InputEventSender; import android.view.KeyEvent; import android.view.View; import android.view.ViewRootImpl; -import android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -322,8 +321,6 @@ public final class InputMethodManager { * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}. */ private final int[] mViewTopLeft = new int[2]; - private final CursorAnchorInfoBuilder mCursorAnchorInfoBuilder = new CursorAnchorInfoBuilder(); - // ----------------------------------------------------------- /** diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 25bcd44..ac12357 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -50,28 +50,6 @@ public final class WebViewFactory { private static WebViewFactoryProvider sProviderInstance; private static final Object sProviderLock = new Object(); - public static boolean isExperimentalWebViewAvailable() { - // TODO: Remove callers of this method then remove it. - return false; // Hide the toggle in Developer Settings. - } - - /** @hide */ - public static void setUseExperimentalWebView(boolean enable) { - // TODO: Remove callers of this method then remove it. - } - - /** @hide */ - public static boolean useExperimentalWebView() { - // TODO: Remove callers of this method then remove it. - return true; - } - - /** @hide */ - public static boolean isUseExperimentalWebViewSet() { - // TODO: Remove callers of this method then remove it. - return false; // User has not modifed Developer Settings - } - static WebViewFactoryProvider getProvider() { synchronized (sProviderLock) { // For now the main purpose of this function (and the factory abstraction) is to keep diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 17db689..5fa63e5 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -3267,7 +3267,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } - private boolean startScrollIfNeeded(int y, MotionEvent vtev) { + private boolean startScrollIfNeeded(int x, int y, MotionEvent vtev) { // Check if we have moved far enough that it looks more like a // scroll than a tap final int deltaY = y - mMotionY; @@ -3296,14 +3296,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } - scrollIfNeeded(y, vtev); + scrollIfNeeded(x, y, vtev); return true; } return false; } - private void scrollIfNeeded(int y, MotionEvent vtev) { + private void scrollIfNeeded(int x, int y, MotionEvent vtev) { int rawDeltaY = y - mMotionY; int scrollOffsetCorrection = 0; int scrollConsumedCorrection = 0; @@ -3387,33 +3387,39 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te vtev.offsetLocation(0, mScrollOffset[1]); } } else { - overScrollBy(0, overscroll, 0, mScrollY, 0, 0, - 0, mOverscrollDistance, true); - if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) { - // Don't allow overfling if we're at the edge. - if (mVelocityTracker != null) { - mVelocityTracker.clear(); - } + final boolean atOverscrollEdge = overScrollBy(0, overscroll, + 0, mScrollY, 0, 0, 0, mOverscrollDistance, true); + + if (atOverscrollEdge && mVelocityTracker != null) { + // Don't allow overfling if we're at the edge + mVelocityTracker.clear(); } final int overscrollMode = getOverScrollMode(); if (overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits())) { - mDirection = 0; // Reset when entering overscroll. - mTouchMode = TOUCH_MODE_OVERSCROLL; - if (deltaY > 0) { - mEdgeGlowTop.onPull((float) overscroll / getHeight()); + if (!atOverscrollEdge) { + mDirection = 0; // Reset when entering overscroll. + mTouchMode = TOUCH_MODE_OVERSCROLL; + } + if (incrementalDeltaY > 0) { + mEdgeGlowTop.onPull((float) overscroll / getHeight(), + (float) x / getWidth()); if (!mEdgeGlowBottom.isFinished()) { mEdgeGlowBottom.onRelease(); } - invalidate(mEdgeGlowTop.getBounds(false)); - } else if (deltaY < 0) { - mEdgeGlowBottom.onPull((float) overscroll / getHeight()); + invalidate(0, 0, getWidth(), + mEdgeGlowTop.getMaxHeight() + getPaddingTop()); + } else if (incrementalDeltaY < 0) { + mEdgeGlowBottom.onPull((float) overscroll / getHeight(), + 1.f - (float) x / getWidth()); if (!mEdgeGlowTop.isFinished()) { mEdgeGlowTop.onRelease(); } - invalidate(mEdgeGlowBottom.getBounds(true)); + invalidate(0, getHeight() - getPaddingBottom() - + mEdgeGlowBottom.getMaxHeight(), getWidth(), + getHeight()); } } } @@ -3448,17 +3454,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits())) { if (rawDeltaY > 0) { - mEdgeGlowTop.onPull((float) overScrollDistance / getHeight()); + mEdgeGlowTop.onPull((float) overScrollDistance / getHeight(), + (float) x / getWidth()); if (!mEdgeGlowBottom.isFinished()) { mEdgeGlowBottom.onRelease(); } - invalidate(mEdgeGlowTop.getBounds(false)); + invalidate(0, 0, getWidth(), + mEdgeGlowTop.getMaxHeight() + getPaddingTop()); } else if (rawDeltaY < 0) { - mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight()); + mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(), + 1.f - (float) x / getWidth()); if (!mEdgeGlowTop.isFinished()) { mEdgeGlowTop.onRelease(); } - invalidate(mEdgeGlowBottom.getBounds(true)); + invalidate(0, getHeight() - getPaddingBottom() - + mEdgeGlowBottom.getMaxHeight(), getWidth(), + getHeight()); } } } @@ -3706,7 +3717,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case TOUCH_MODE_DONE_WAITING: // Check if we have moved far enough that it looks more like a // scroll than a tap. If so, we'll enter scrolling mode. - if (startScrollIfNeeded(y, vtev)) { + if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, vtev)) { break; } // Otherwise, check containment within list bounds. If we're @@ -3726,7 +3737,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te break; case TOUCH_MODE_SCROLL: case TOUCH_MODE_OVERSCROLL: - scrollIfNeeded(y, vtev); + scrollIfNeeded((int) ev.getX(pointerIndex), y, vtev); break; } } @@ -4025,8 +4036,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te canvas.translate(leftPadding, edgeY); mEdgeGlowTop.setSize(width, getHeight()); if (mEdgeGlowTop.draw(canvas)) { - mEdgeGlowTop.setPosition(leftPadding, edgeY); - invalidate(mEdgeGlowTop.getBounds(false)); + invalidate(0, 0, getWidth(), + mEdgeGlowTop.getMaxHeight() + getPaddingTop()); } canvas.restoreToCount(restoreCount); } @@ -4043,9 +4054,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te canvas.rotate(180, width, 0); mEdgeGlowBottom.setSize(width, height); if (mEdgeGlowBottom.draw(canvas)) { - // Account for the rotation - mEdgeGlowBottom.setPosition(edgeX + width, edgeY); - invalidate(mEdgeGlowBottom.getBounds(true)); + invalidate(0, getHeight() - getPaddingBottom() - + mEdgeGlowBottom.getMaxHeight(), getWidth(), + getHeight()); } canvas.restoreToCount(restoreCount); } @@ -4164,7 +4175,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int y = (int) ev.getY(pointerIndex); initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - if (startScrollIfNeeded(y, null)) { + if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) { return true; } break; diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java index fa37443..83fbe8f 100644 --- a/core/java/android/widget/EdgeEffect.java +++ b/core/java/android/widget/EdgeEffect.java @@ -16,7 +16,14 @@ package android.widget; +import android.content.res.TypedArray; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Xfermode; +import android.util.Log; import com.android.internal.R; import android.content.Context; @@ -59,12 +66,10 @@ public class EdgeEffect { private static final int PULL_DECAY_TIME = 1000; private static final float MAX_ALPHA = 1.f; - private static final float HELD_EDGE_SCALE_Y = 0.5f; - private static final float MAX_GLOW_HEIGHT = 4.f; + private static final float MAX_GLOW_HEIGHT = 1.5f; - private static final float PULL_GLOW_BEGIN = 1.f; - private static final float PULL_EDGE_BEGIN = 0.6f; + private static final float PULL_GLOW_BEGIN = 0.f; // Minimum velocity that will be absorbed private static final int MIN_VELOCITY = 100; @@ -73,24 +78,11 @@ public class EdgeEffect { private static final float EPSILON = 0.001f; - private final Drawable mEdge; - private final Drawable mGlow; - private int mWidth; - private int mHeight; - private int mX; - private int mY; - private static final int MIN_WIDTH = 300; - private final int mMinWidth; - - private float mEdgeAlpha; - private float mEdgeScaleY; + private static final float SIN_45 = (float) Math.sin(Math.PI / 4); + private float mGlowAlpha; private float mGlowScaleY; - private float mEdgeAlphaStart; - private float mEdgeAlphaFinish; - private float mEdgeScaleYStart; - private float mEdgeScaleYFinish; private float mGlowAlphaStart; private float mGlowAlphaFinish; private float mGlowScaleYStart; @@ -107,16 +99,11 @@ public class EdgeEffect { private static final int STATE_RECEDE = 3; private static final int STATE_PULL_DECAY = 4; - // How much dragging should effect the height of the edge image. - // Number determined by user testing. - private static final int PULL_DISTANCE_EDGE_FACTOR = 7; - // How much dragging should effect the height of the glow image. // Number determined by user testing. private static final int PULL_DISTANCE_GLOW_FACTOR = 7; private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f; - private static final int VELOCITY_EDGE_FACTOR = 8; private static final int VELOCITY_GLOW_FACTOR = 12; private int mState = STATE_IDLE; @@ -124,30 +111,26 @@ public class EdgeEffect { private float mPullDistance; private final Rect mBounds = new Rect(); - - private final int mEdgeHeight; - private final int mGlowHeight; - private final int mGlowWidth; - private final int mMaxEffectHeight; + private final RectF mArcRect = new RectF(); + private final Paint mPaint = new Paint(); + private float mRadius; + private float mDisplacement = 0.5f; + private float mTargetDisplacement = 0.5f; /** * Construct a new EdgeEffect with a theme appropriate for the provided context. * @param context Context used to provide theming and resource information for the EdgeEffect */ public EdgeEffect(Context context) { - final Resources res = context.getResources(); - mEdge = context.getDrawable(R.drawable.overscroll_edge); - mGlow = context.getDrawable(R.drawable.overscroll_glow); - - mEdgeHeight = mEdge.getIntrinsicHeight(); - mGlowHeight = mGlow.getIntrinsicHeight(); - mGlowWidth = mGlow.getIntrinsicWidth(); - - mMaxEffectHeight = (int) (Math.min( - mGlowHeight * MAX_GLOW_HEIGHT * mGlowHeight / mGlowWidth * 0.6f, - mGlowHeight * MAX_GLOW_HEIGHT) + 0.5f); - - mMinWidth = (int) (res.getDisplayMetrics().density * MIN_WIDTH + 0.5f); + mPaint.setAntiAlias(true); + final TypedArray a = context.obtainStyledAttributes( + com.android.internal.R.styleable.EdgeEffect); + final int themeColor = a.getColor( + com.android.internal.R.styleable.EdgeEffect_colorPrimaryLight, 0xff666666); + a.recycle(); + mPaint.setColor((themeColor & 0xffffff) | 0x66000000); + mPaint.setStyle(Paint.Style.FILL); + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); mInterpolator = new DecelerateInterpolator(); } @@ -158,20 +141,12 @@ public class EdgeEffect { * @param height Effect height in pixels */ public void setSize(int width, int height) { - mWidth = width; - mHeight = height; - } + final float r = width * 0.5f / SIN_45; + final float y = SIN_45 * r; + final float h = r - y; + mRadius = r; - /** - * Set the position of this edge effect in pixels. This position is - * only used by {@link #getBounds(boolean)}. - * - * @param x The position of the edge effect on the X axis - * @param y The position of the edge effect on the Y axis - */ - void setPosition(int x, int y) { - mX = x; - mY = y; + mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h)); } /** @@ -199,17 +174,38 @@ public class EdgeEffect { * The host view should always {@link android.view.View#invalidate()} after this * and draw the results accordingly. * + * <p>Views using EdgeEffect should favor {@link #onPull(float, float)} when the displacement + * of the pull point is known.</p> + * * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to * 1.f (full length of the view) or negative values to express change * back toward the edge reached to initiate the effect. */ public void onPull(float deltaDistance) { + onPull(deltaDistance, 0.5f); + } + + /** + * A view should call this when content is pulled away from an edge by the user. + * This will update the state of the current visual effect and its associated animation. + * The host view should always {@link android.view.View#invalidate()} after this + * and draw the results accordingly. + * + * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to + * 1.f (full length of the view) or negative values to express change + * back toward the edge reached to initiate the effect. + * @param displacement The displacement from the starting side of the effect of the point + * initiating the pull. In the case of touch this is the finger position. + * Values may be from 0-1. + */ + public void onPull(float deltaDistance, float displacement) { final long now = AnimationUtils.currentAnimationTimeMillis(); + mTargetDisplacement = displacement; if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) { return; } if (mState != STATE_PULL) { - mGlowScaleY = PULL_GLOW_BEGIN; + mGlowScaleY = Math.max(PULL_GLOW_BEGIN, mGlowScaleY); } mState = STATE_PULL; @@ -217,15 +213,10 @@ public class EdgeEffect { mDuration = PULL_TIME; mPullDistance += deltaDistance; - float distance = Math.abs(mPullDistance); - - mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA)); - mEdgeScaleY = mEdgeScaleYStart = Math.max( - HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f)); mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA, mGlowAlpha + - (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR)); + (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR)); float glowChange = Math.abs(deltaDistance); if (deltaDistance > 0 && mPullDistance < 0) { @@ -239,8 +230,6 @@ public class EdgeEffect { mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max( 0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR)); - mEdgeAlphaFinish = mEdgeAlpha; - mEdgeScaleYFinish = mEdgeScaleY; mGlowAlphaFinish = mGlowAlpha; mGlowScaleYFinish = mGlowScaleY; } @@ -259,13 +248,9 @@ public class EdgeEffect { } mState = STATE_RECEDE; - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; mGlowAlphaStart = mGlowAlpha; mGlowScaleYStart = mGlowScaleY; - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; mGlowAlphaFinish = 0.f; mGlowScaleYFinish = 0.f; @@ -290,30 +275,21 @@ public class EdgeEffect { mStartTime = AnimationUtils.currentAnimationTimeMillis(); mDuration = 0.15f + (velocity * 0.02f); - // The edge should always be at least partially visible, regardless - // of velocity. - mEdgeAlphaStart = 0.f; - mEdgeScaleY = mEdgeScaleYStart = 0.f; // The glow depends more on the velocity, and therefore starts out // nearly invisible. mGlowAlphaStart = 0.3f; - mGlowScaleYStart = 0.f; + mGlowScaleYStart = Math.max(mGlowScaleY, 0.f); - // Factor the velocity by 8. Testing on device shows this works best to - // reflect the strength of the user's scrolling. - mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1)); - // Edge should never get larger than the size of its asset. - mEdgeScaleYFinish = Math.max( - HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f)); // Growth for the size of the glow should be quadratic to properly // respond // to a user's scrolling speed. The faster the scrolling speed, the more // intense the effect should be for both the size and the saturation. - mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f); + mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2, 1.f); // Alpha should change for the glow as well as size. mGlowAlphaFinish = Math.max( mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA)); + mTargetDisplacement = 0.5f; } @@ -330,52 +306,42 @@ public class EdgeEffect { public boolean draw(Canvas canvas) { update(); - mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255)); - - int glowBottom = (int) Math.min( - mGlowHeight * mGlowScaleY * mGlowHeight / mGlowWidth * 0.6f, - mGlowHeight * MAX_GLOW_HEIGHT); - if (mWidth < mMinWidth) { - // Center the glow and clip it. - int glowLeft = (mWidth - mMinWidth)/2; - mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom); - } else { - // Stretch the glow to fit. - mGlow.setBounds(0, 0, mWidth, glowBottom); - } + final int count = canvas.save(); - mGlow.draw(canvas); + final float y = mBounds.height(); + final float centerY = y - mRadius; + final float centerX = mBounds.centerX(); + mArcRect.set(centerX - mRadius, centerY - mRadius, centerX + mRadius, centerY + mRadius); + canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0); - mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255)); - - int edgeBottom = (int) (mEdgeHeight * mEdgeScaleY); - if (mWidth < mMinWidth) { - // Center the edge and clip it. - int edgeLeft = (mWidth - mMinWidth)/2; - mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom); - } else { - // Stretch the edge to fit. - mEdge.setBounds(0, 0, mWidth, edgeBottom); + final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f; + float translateX = mBounds.width() * displacement; + float translateY = 0; + if (mGlowScaleY > 1.f) { + translateY = (mGlowScaleY - 1.f) * mBounds.height(); } - mEdge.draw(canvas); - - if (mState == STATE_RECEDE && glowBottom == 0 && edgeBottom == 0) { + canvas.clipRect(Float.MIN_VALUE, mBounds.top, + Float.MAX_VALUE, Float.MAX_VALUE); + canvas.translate(translateX, translateY); + canvas.drawArc(mArcRect, 0, 180, true, mPaint); + canvas.restoreToCount(count); + + boolean oneLastFrame = false; + if (mState == STATE_RECEDE && mGlowScaleY == 0) { mState = STATE_IDLE; + oneLastFrame = true; } - return mState != STATE_IDLE; + return mState != STATE_IDLE || oneLastFrame; } /** - * Returns the bounds of the edge effect. - * - * @hide + * Return the maximum height that the edge effect will be drawn at given the original + * {@link #setSize(int, int) input size}. + * @return The maximum height of the edge effect */ - public Rect getBounds(boolean reverse) { - mBounds.set(0, 0, mWidth, mMaxEffectHeight); - mBounds.offset(mX, mY - (reverse ? mMaxEffectHeight : 0)); - - return mBounds; + public int getMaxHeight() { + return (int) (mBounds.height() * MAX_GLOW_HEIGHT + 0.5f); } private void update() { @@ -384,10 +350,9 @@ public class EdgeEffect { final float interp = mInterpolator.getInterpolation(t); - mEdgeAlpha = mEdgeAlphaStart + (mEdgeAlphaFinish - mEdgeAlphaStart) * interp; - mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp; mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp; mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp; + mDisplacement = (mDisplacement + mTargetDisplacement) / 2; if (t >= 1.f - EPSILON) { switch (mState) { @@ -396,14 +361,10 @@ public class EdgeEffect { mStartTime = AnimationUtils.currentAnimationTimeMillis(); mDuration = RECEDE_TIME; - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; mGlowAlphaStart = mGlowAlpha; mGlowScaleYStart = mGlowScaleY; - // After absorb, the glow and edge should fade to nothing. - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; + // After absorb, the glow should fade to nothing. mGlowAlphaFinish = 0.f; mGlowScaleYFinish = 0.f; break; @@ -412,26 +373,14 @@ public class EdgeEffect { mStartTime = AnimationUtils.currentAnimationTimeMillis(); mDuration = PULL_DECAY_TIME; - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; mGlowAlphaStart = mGlowAlpha; mGlowScaleYStart = mGlowScaleY; - // After pull, the glow and edge should fade to nothing. - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; + // After pull, the glow should fade to nothing. mGlowAlphaFinish = 0.f; mGlowScaleYFinish = 0.f; break; case STATE_PULL_DECAY: - // When receding, we want edge to decrease more slowly - // than the glow. - float factor = mGlowScaleYFinish != 0 ? 1 - / (mGlowScaleYFinish * mGlowScaleYFinish) - : Float.MAX_VALUE; - mEdgeScaleY = mEdgeScaleYStart + - (mEdgeScaleYFinish - mEdgeScaleYStart) * - interp * factor; mState = STATE_RECEDE; break; case STATE_RECEDE: diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 25d4f42..0c65c50 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -616,12 +616,14 @@ public class HorizontalScrollView extends FrameLayout { if (canOverscroll) { final int pulledToX = oldX + deltaX; if (pulledToX < 0) { - mEdgeGlowLeft.onPull((float) deltaX / getWidth()); + mEdgeGlowLeft.onPull((float) deltaX / getWidth(), + 1.f - ev.getY(activePointerIndex) / getHeight()); if (!mEdgeGlowRight.isFinished()) { mEdgeGlowRight.onRelease(); } } else if (pulledToX > range) { - mEdgeGlowRight.onPull((float) deltaX / getWidth()); + mEdgeGlowRight.onPull((float) deltaX / getWidth(), + ev.getY(activePointerIndex) / getHeight()); if (!mEdgeGlowLeft.isFinished()) { mEdgeGlowLeft.onRelease(); } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 0fa75a6..fd04890 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -669,12 +669,14 @@ public class ScrollView extends FrameLayout { } else if (canOverscroll) { final int pulledToY = oldY + deltaY; if (pulledToY < 0) { - mEdgeGlowTop.onPull((float) deltaY / getHeight()); + mEdgeGlowTop.onPull((float) deltaY / getHeight(), + ev.getX(activePointerIndex) / getWidth()); if (!mEdgeGlowBottom.isFinished()) { mEdgeGlowBottom.onRelease(); } } else if (pulledToY > range) { - mEdgeGlowBottom.onPull((float) deltaY / getHeight()); + mEdgeGlowBottom.onPull((float) deltaY / getHeight(), + 1.f - ev.getX(activePointerIndex) / getWidth()); if (!mEdgeGlowTop.isFinished()) { mEdgeGlowTop.onRelease(); } diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 4726da7..b568121 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -26,6 +26,7 @@ import android.content.DialogInterface; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.text.TextUtils; @@ -38,6 +39,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.Window; +import android.view.WindowInsets; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; @@ -240,6 +242,7 @@ public class AlertController { mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setContentView(mAlertDialogLayout); setupView(); + setupDecor(); } public void setTitle(CharSequence title) { @@ -415,7 +418,28 @@ public class AlertController { public boolean onKeyUp(int keyCode, KeyEvent event) { return mScrollView != null && mScrollView.executeKeyEvent(event); } - + + private void setupDecor() { + final View decor = mWindow.getDecorView(); + final View parent = mWindow.findViewById(R.id.parentPanel); + if (parent != null && decor != null) { + decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) { + if (insets.isRound()) { + // TODO: Get the padding as a function of the window size. + int roundOffset = mContext.getResources().getDimensionPixelOffset( + R.dimen.alert_dialog_round_padding); + parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset); + } + return insets.consumeSystemWindowInsets(); + } + }); + decor.setFitsSystemWindows(true); + decor.requestApplyInsets(); + } + } + private void setupView() { LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel); setupContent(contentPanel); @@ -636,14 +660,31 @@ public class AlertController { private void setBackground(TypedArray a, View topPanel, View contentPanel, View customPanel, View buttonPanel, boolean hasTitle, boolean hasCustomView, boolean hasButtons) { - final int topBright = a.getResourceId( - R.styleable.AlertDialog_topBright, R.drawable.popup_top_bright); - final int topDark = a.getResourceId( - R.styleable.AlertDialog_topDark, R.drawable.popup_top_dark); - final int centerBright = a.getResourceId( - R.styleable.AlertDialog_centerBright, R.drawable.popup_center_bright); - final int centerDark = a.getResourceId( - R.styleable.AlertDialog_centerDark, R.drawable.popup_center_dark); + int fullDark = 0; + int topDark = 0; + int centerDark = 0; + int bottomDark = 0; + int fullBright = 0; + int topBright = 0; + int centerBright = 0; + int bottomBright = 0; + int bottomMedium = 0; + if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT) { + fullDark = R.drawable.popup_full_dark; + topDark = R.drawable.popup_top_dark; + centerDark = R.drawable.popup_center_dark; + bottomDark = R.drawable.popup_bottom_dark; + fullBright = R.drawable.popup_full_bright; + topBright = R.drawable.popup_top_bright; + centerBright = R.drawable.popup_center_bright; + bottomBright = R.drawable.popup_bottom_bright; + bottomMedium = R.drawable.popup_bottom_medium; + } + topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright); + topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark); + centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright); + centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark); + /* We now set the background of all of the sections of the alert. * First collect together each section that is being displayed along @@ -707,22 +748,17 @@ public class AlertController { if (lastView != null) { if (setView) { - final int bottomBright = a.getResourceId( - R.styleable.AlertDialog_bottomBright, R.drawable.popup_bottom_bright); - final int bottomMedium = a.getResourceId( - R.styleable.AlertDialog_bottomMedium, R.drawable.popup_bottom_medium); - final int bottomDark = a.getResourceId( - R.styleable.AlertDialog_bottomDark, R.drawable.popup_bottom_dark); + bottomBright = a.getResourceId(R.styleable.AlertDialog_bottomBright, bottomBright); + bottomMedium = a.getResourceId(R.styleable.AlertDialog_bottomMedium, bottomMedium); + bottomDark = a.getResourceId(R.styleable.AlertDialog_bottomDark, bottomDark); // ListViews will use the Bright background, but buttons use the // Medium background. lastView.setBackgroundResource( lastLight ? (hasButtons ? bottomMedium : bottomBright) : bottomDark); } else { - final int fullBright = a.getResourceId( - R.styleable.AlertDialog_fullBright, R.drawable.popup_full_bright); - final int fullDark = a.getResourceId( - R.styleable.AlertDialog_fullDark, R.drawable.popup_full_dark); + fullBright = a.getResourceId(R.styleable.AlertDialog_fullBright, fullBright); + fullDark = a.getResourceId(R.styleable.AlertDialog_fullDark, fullDark); lastView.setBackgroundResource(lastLight ? fullBright : fullDark); } diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java index 882bec9..41f3337 100644 --- a/core/java/com/android/internal/app/ProcessStats.java +++ b/core/java/com/android/internal/app/ProcessStats.java @@ -1108,13 +1108,6 @@ public final class ProcessStats implements Parcelable { mRuntime = runtime; } } - String webview = WebViewFactory.useExperimentalWebView() ? "chromeview" : "webview"; - if (!Objects.equals(webview, mWebView)) { - changed = true; - if (update) { - mWebView = webview; - } - } return changed; } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 1aff190..7bd5b12 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -188,8 +188,7 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mShuttingDown; - HashMap<String, SparseBooleanArray>[] mActiveEvents - = (HashMap<String, SparseBooleanArray>[]) new HashMap[HistoryItem.EVENT_COUNT]; + final HistoryEventTracker mActiveEvents = new HistoryEventTracker(); long mHistoryBaseTime; boolean mHaveBatteryLevel = false; @@ -2297,44 +2296,8 @@ public final class BatteryStatsImpl extends BatteryStats { public void noteEventLocked(int code, String name, int uid) { uid = mapUid(uid); - if ((code&HistoryItem.EVENT_FLAG_START) != 0) { - int idx = code&~HistoryItem.EVENT_FLAG_START; - HashMap<String, SparseBooleanArray> active = mActiveEvents[idx]; - if (active == null) { - active = new HashMap<String, SparseBooleanArray>(); - mActiveEvents[idx] = active; - } - SparseBooleanArray uids = active.get(name); - if (uids == null) { - uids = new SparseBooleanArray(); - active.put(name, uids); - } - if (uids.get(uid)) { - // Already set, nothing to do! - return; - } - uids.put(uid, true); - } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) { - int idx = code&~HistoryItem.EVENT_FLAG_FINISH; - HashMap<String, SparseBooleanArray> active = mActiveEvents[idx]; - if (active == null) { - // not currently active, nothing to do. - return; - } - SparseBooleanArray uids = active.get(name); - if (uids == null) { - // not currently active, nothing to do. - return; - } - idx = uids.indexOfKey(uid); - if (idx < 0 || !uids.valueAt(idx)) { - // not currently active, nothing to do. - return; - } - uids.removeAt(idx); - if (uids.size() <= 0) { - active.remove(name); - } + if (!mActiveEvents.updateState(code, name, uid, 0)) { + return; } final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); @@ -2348,6 +2311,9 @@ public final class BatteryStatsImpl extends BatteryStats { } } + private String mInitialAcquireWakeName; + private int mInitialAcquireWakeUid = -1; + public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) { uid = mapUid(uid); @@ -2360,8 +2326,9 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: " + Integer.toHexString(mHistoryCur.states)); mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.string = historyName != null ? historyName : name; - mHistoryCur.wakelockTag.uid = uid; + mHistoryCur.wakelockTag.string = mInitialAcquireWakeName + = historyName != null ? historyName : name; + mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; mWakeLockImportant = !unimportantForLogging; addHistoryRecordLocked(elapsedRealtime, uptime); } else if (!mWakeLockImportant && !unimportantForLogging) { @@ -2369,8 +2336,9 @@ public final class BatteryStatsImpl extends BatteryStats { // We'll try to update the last tag. mHistoryLastWritten.wakelockTag = null; mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; - mHistoryCur.wakelockTag.string = historyName != null ? historyName : name; - mHistoryCur.wakelockTag.uid = uid; + mHistoryCur.wakelockTag.string = mInitialAcquireWakeName + = historyName != null ? historyName : name; + mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; addHistoryRecordLocked(elapsedRealtime, uptime); } mWakeLockImportant = true; @@ -2395,6 +2363,14 @@ public final class BatteryStatsImpl extends BatteryStats { mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: " + Integer.toHexString(mHistoryCur.states)); + if ((name != null && !name.equals(mInitialAcquireWakeName)) + || uid != mInitialAcquireWakeUid) { + mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; + mHistoryCur.wakelockTag.string = name; + mHistoryCur.wakelockTag.uid = uid; + } + mInitialAcquireWakeName = null; + mInitialAcquireWakeUid = -1; addHistoryRecordLocked(elapsedRealtime, uptime); } } @@ -5699,7 +5675,8 @@ public final class BatteryStatsImpl extends BatteryStats { final long lastRealtime = out.time; final long lastWalltime = out.currentTime; readHistoryDelta(mHistoryBuffer, out); - if (out.cmd != HistoryItem.CMD_CURRENT_TIME && lastWalltime != 0) { + if (out.cmd != HistoryItem.CMD_CURRENT_TIME + && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) { out.currentTime = lastWalltime + (out.time - lastRealtime); } return true; @@ -5845,17 +5822,15 @@ public final class BatteryStatsImpl extends BatteryStats { private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) { for (int i=0; i<HistoryItem.EVENT_COUNT; i++) { - HashMap<String, SparseBooleanArray> active = mActiveEvents[i]; + HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i); if (active == null) { continue; } - for (HashMap.Entry<String, SparseBooleanArray> ent : active.entrySet()) { - SparseBooleanArray uids = ent.getValue(); + for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) { + SparseIntArray uids = ent.getValue(); for (int j=0; j<uids.size(); j++) { - if (uids.valueAt(j)) { - addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(), - uids.keyAt(j)); - } + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(), + uids.keyAt(j)); } } } @@ -5971,7 +5946,8 @@ public final class BatteryStatsImpl extends BatteryStats { boolean reset) { mRecordingHistory = true; mHistoryCur.currentTime = System.currentTimeMillis(); - addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME, + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, + reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME, mHistoryCur); mHistoryCur.currentTime = 0; if (reset) { diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java index 52281d9..34f62ba 100644 --- a/core/java/com/android/internal/util/AsyncChannel.java +++ b/core/java/com/android/internal/util/AsyncChannel.java @@ -450,6 +450,7 @@ public class AsyncChannel { public void disconnect() { if ((mConnection != null) && (mSrcContext != null)) { mSrcContext.unbindService(mConnection); + mConnection = null; } try { // Send the DISCONNECTED, although it may not be received @@ -463,10 +464,12 @@ public class AsyncChannel { // Tell source we're disconnected. if (mSrcHandler != null) { replyDisconnected(STATUS_SUCCESSFUL); + mSrcHandler = null; } // Unlink only when bindService isn't used if (mConnection == null && mDstMessenger != null && mDeathMonitor!= null) { mDstMessenger.getBinder().unlinkToDeath(mDeathMonitor, 0); + mDeathMonitor = null; } } diff --git a/core/java/com/android/internal/util/VirtualRefBasePtr.java b/core/java/com/android/internal/util/VirtualRefBasePtr.java new file mode 100644 index 0000000..0bd4d3a --- /dev/null +++ b/core/java/com/android/internal/util/VirtualRefBasePtr.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +/** + * Helper class that contains a strong reference to a VirtualRefBase native + * object. This will incStrong in the ctor, and decStrong in the finalizer + */ +public final class VirtualRefBasePtr { + private long mNativePtr; + + public VirtualRefBasePtr(long ptr) { + mNativePtr = ptr; + nIncStrong(mNativePtr); + } + + public long get() { + return mNativePtr; + } + + @Override + protected void finalize() throws Throwable { + try { + nDecStrong(mNativePtr); + mNativePtr = 0; + } finally { + super.finalize(); + } + } + + private static native void nIncStrong(long ptr); + private static native void nDecStrong(long ptr); +} |
