Merge "Remove "final" from TextToSpeechClient class."
diff --git a/Android.mk b/Android.mk
index 84d5dc5..adc9ef1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -420,6 +420,8 @@
frameworks/base/core/java/android/view/MotionEvent.aidl \
frameworks/base/core/java/android/view/Surface.aidl \
frameworks/base/core/java/android/view/WindowManager.aidl \
+ frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \
+ frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
frameworks/base/core/java/android/widget/RemoteViews.aidl \
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
diff --git a/api/current.txt b/api/current.txt
index 71c278d..eeff753 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4453,6 +4453,7 @@
ctor public Notification.Builder(android.content.Context);
method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
+ method public android.app.Notification.Builder addPerson(java.lang.String);
method public android.app.Notification build();
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
@@ -4751,9 +4752,13 @@
}
public final class UiAutomation {
+ method public void clearWindowAnimationFrameStats();
+ method public boolean clearWindowContentFrameStats(int);
method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+ method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
+ method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
method public boolean injectInputEvent(android.view.InputEvent, boolean);
method public final boolean performGlobalAction(int);
@@ -11026,8 +11031,6 @@
method public void setAnimationFraction(float);
method public void setColorFilter(android.graphics.ColorFilter);
method public void setDuration(long);
- method public void setIntrinsicHeight(int);
- method public void setIntrinsicWidth(int);
method public void setPadding(android.graphics.Rect);
method public void setPadding(int, int, int, int);
method public void setRepeatCount(int);
@@ -12155,6 +12158,7 @@
public final class HdmiCecClient {
method public boolean isTvOn();
method public void sendActiveSource();
+ method public void sendGiveDevicePowerStatus(int);
method public void sendImageViewOn();
method public void sendInactiveSource();
method public void sendTextViewOn();
@@ -19732,7 +19736,8 @@
public final class PowerManager {
method public void goToSleep(long);
- method public boolean isScreenOn();
+ method public boolean isInteractive();
+ method public deprecated boolean isScreenOn();
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
method public void userActivity(long, boolean);
@@ -28409,6 +28414,7 @@
method public float getRefreshRate();
method public int getRotation();
method public void getSize(android.graphics.Point);
+ method public int getState();
method public deprecated int getWidth();
method public boolean isValid();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -28416,6 +28422,10 @@
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_SECURE = 2; // 0x2
field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
+ field public static final int STATE_DOZING = 3; // 0x3
+ field public static final int STATE_OFF = 1; // 0x1
+ field public static final int STATE_ON = 2; // 0x2
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public class DragEvent implements android.os.Parcelable {
@@ -28444,6 +28454,18 @@
method public static android.view.FocusFinder getInstance();
}
+ public abstract class FrameStats {
+ ctor public FrameStats();
+ method public final long getEndTimeNano();
+ method public final int getFrameCount();
+ method public final long getFramePresentedTimeNano(int);
+ method public final long getRefreshPeriodNano();
+ method public final long getStartTimeNano();
+ field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
+ field protected long[] mFramesPresentedTimeNano;
+ field protected long mRefreshPeriodNano;
+ }
+
public class GestureDetector {
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler);
ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener);
@@ -28749,7 +28771,7 @@
field public static final int FLAG_SOFT_KEYBOARD = 2; // 0x2
field public static final int FLAG_TRACKING = 512; // 0x200
field public static final int FLAG_VIRTUAL_HARD_KEY = 64; // 0x40
- field public static final int FLAG_WOKE_HERE = 1; // 0x1
+ field public static final deprecated int FLAG_WOKE_HERE = 1; // 0x1
field public static final int KEYCODE_0 = 7; // 0x7
field public static final int KEYCODE_1 = 8; // 0x8
field public static final int KEYCODE_2 = 9; // 0x9
@@ -30768,6 +30790,20 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
}
+ public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public final class WindowContentFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getFramePostedTimeNano(int);
+ method public long getFrameReadyTimeNano(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
public class WindowId implements android.os.Parcelable {
method public int describeContents();
method public boolean isFocused();
@@ -30869,7 +30905,7 @@
field public static final int FLAG_SHOW_WALLPAPER = 1048576; // 0x100000
field public static final int FLAG_SHOW_WHEN_LOCKED = 524288; // 0x80000
field public static final int FLAG_SPLIT_TOUCH = 8388608; // 0x800000
- field public static final int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
+ field public static final deprecated int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
field public static final int FLAG_TRANSLUCENT_NAVIGATION = 134217728; // 0x8000000
field public static final int FLAG_TRANSLUCENT_STATUS = 67108864; // 0x4000000
field public static final int FLAG_TURN_SCREEN_ON = 2097152; // 0x200000
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 3e8d6a0..c520b58 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -138,8 +138,10 @@
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
+static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
+static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif
int main(int argc, char* const argv[])
@@ -185,16 +187,19 @@
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
- niceName = "zygote";
+ niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;
- } else {
+ } else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
+ } else {
+ --i;
+ break;
}
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 09bf829..347de97 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -19,6 +19,8 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.graphics.Bitmap;
import android.view.InputEvent;
+import android.view.WindowContentFrameStats;
+import android.view.WindowAnimationFrameStats;
import android.os.ParcelFileDescriptor;
/**
@@ -26,7 +28,7 @@
* on behalf of an instrumentation that it runs. These operations require
* special permissions which the shell user has but the instrumentation does
* not. Running privileged operations by the shell user on behalf of an
- * instrumentation is needed for running UiTestCases.
+ * instrumentation is needed for running UiTestCases.
*
* {@hide}
*/
@@ -37,4 +39,8 @@
boolean setRotation(int rotation);
Bitmap takeScreenshot(int width, int height);
void shutdown();
+ boolean clearWindowContentFrameStats(int windowId);
+ WindowContentFrameStats getWindowContentFrameStats(int windowId);
+ void clearWindowAnimationFrameStats();
+ WindowAnimationFrameStats getWindowAnimationFrameStats();
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 36d2635..fe629f6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1311,6 +1311,7 @@
private Notification mPublicVersion = null;
private boolean mQuantumTheme;
private final LegacyNotificationUtil mLegacyNotificationUtil;
+ private ArrayList<String> mPeople;
/**
* Constructs a new Builder with the defaults:
@@ -1338,6 +1339,7 @@
mWhen = System.currentTimeMillis();
mAudioStreamType = STREAM_DEFAULT;
mPriority = PRIORITY_DEFAULT;
+ mPeople = new ArrayList<String>();
// TODO: Decide on targetSdk from calling app whether to use quantum theme.
mQuantumTheme = true;
@@ -1723,6 +1725,16 @@
}
/**
+ * Add a person that is relevant to this notification.
+ *
+ * @see Notification#EXTRA_PEOPLE
+ */
+ public Builder addPerson(String handle) {
+ mPeople.add(handle);
+ return this;
+ }
+
+ /**
* Merge additional metadata into this notification.
*
* <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -2149,6 +2161,9 @@
if (mLargeIcon != null) {
extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
}
+ if (!mPeople.isEmpty()) {
+ extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()]));
+ }
}
/**
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 354a19f..8523d0c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -33,6 +33,8 @@
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.Surface;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -674,6 +676,148 @@
}
}
+ /**
+ * Clears the frame statistics for the content of a given window. These
+ * statistics contain information about the most recently rendered content
+ * frames.
+ *
+ * @param windowId The window id.
+ * @return Whether the window is present and its frame statistics
+ * were cleared.
+ *
+ * @see android.view.WindowContentFrameStats
+ * @see #getWindowContentFrameStats(int)
+ * @see #getWindows()
+ * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+ */
+ public boolean clearWindowContentFrameStats(int windowId) {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing content frame stats for window: " + windowId);
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.clearWindowContentFrameStats(windowId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error clearing window content frame stats!", re);
+ }
+ return false;
+ }
+
+ /**
+ * Gets the frame statistics for a given window. These statistics contain
+ * information about the most recently rendered content frames.
+ * <p>
+ * A typical usage requires clearing the window frame statistics via {@link
+ * #clearWindowContentFrameStats(int)} followed by an interaction with the UI and
+ * finally getting the window frame statistics via calling this method.
+ * </p>
+ * <pre>
+ * // Assume we have at least one window.
+ * final int windowId = getWindows().get(0).getId();
+ *
+ * // Start with a clean slate.
+ * uiAutimation.clearWindowContentFrameStats(windowId);
+ *
+ * // Do stuff with the UI.
+ *
+ * // Get the frame statistics.
+ * WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
+ * </pre>
+ *
+ * @param windowId The window id.
+ * @return The window frame statistics, or null if the window is not present.
+ *
+ * @see android.view.WindowContentFrameStats
+ * @see #clearWindowContentFrameStats(int)
+ * @see #getWindows()
+ * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+ */
+ public WindowContentFrameStats getWindowContentFrameStats(int windowId) {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Getting content frame stats for window: " + windowId);
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.getWindowContentFrameStats(windowId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error getting window content frame stats!", re);
+ }
+ return null;
+ }
+
+ /**
+ * Clears the window animation rendering statistics. These statistics contain
+ * information about the most recently rendered window animation frames, i.e.
+ * for window transition animations.
+ *
+ * @see android.view.WindowAnimationFrameStats
+ * @see #getWindowAnimationFrameStats()
+ * @see android.R.styleable#WindowAnimation
+ */
+ public void clearWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Clearing window animation frame stats");
+ }
+ // Calling out without a lock held.
+ mUiAutomationConnection.clearWindowAnimationFrameStats();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error clearing window animation frame stats!", re);
+ }
+ }
+
+ /**
+ * Gets the window animation frame statistics. These statistics contain
+ * information about the most recently rendered window animation frames, i.e.
+ * for window transition animations.
+ *
+ * <p>
+ * A typical usage requires clearing the window animation frame statistics via
+ * {@link #clearWindowAnimationFrameStats()} followed by an interaction that causes
+ * a window transition which uses a window animation and finally getting the window
+ * animation frame statistics by calling this method.
+ * </p>
+ * <pre>
+ * // Start with a clean slate.
+ * uiAutimation.clearWindowAnimationFrameStats();
+ *
+ * // Do stuff to trigger a window transition.
+ *
+ * // Get the frame statistics.
+ * WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
+ * </pre>
+ *
+ * @return The window animation frame statistics.
+ *
+ * @see android.view.WindowAnimationFrameStats
+ * @see #clearWindowAnimationFrameStats()
+ * @see android.R.styleable#WindowAnimation
+ */
+ public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Getting window animation frame stats");
+ }
+ // Calling out without a lock held.
+ return mUiAutomationConnection.getWindowAnimationFrameStats();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error getting window animation frame stats!", re);
+ }
+ return null;
+ }
+
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 91b0d7c..fa40286 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -22,12 +22,15 @@
import android.graphics.Bitmap;
import android.hardware.input.InputManager;
import android.os.Binder;
+import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.SurfaceControl;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
@@ -47,6 +50,9 @@
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 Object mLock = new Object();
private final Binder mToken = new Binder();
@@ -144,6 +150,76 @@
}
@Override
+ public boolean clearWindowContentFrameStats(int windowId) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IBinder token = mAccessibilityManager.getWindowToken(windowId);
+ if (token == null) {
+ return false;
+ }
+ return mWindowManager.clearWindowContentFrameStats(token);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IBinder token = mAccessibilityManager.getWindowToken(windowId);
+ if (token == null) {
+ return null;
+ }
+ return mWindowManager.getWindowContentFrameStats(token);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void clearWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SurfaceControl.clearAnimationFrameStats();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ WindowAnimationFrameStats stats = new WindowAnimationFrameStats();
+ SurfaceControl.getAnimationFrameStats(stats);
+ return stats;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void shutdown() {
synchronized (mLock) {
if (isConnectedLocked()) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9881428..a7d5606 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1417,15 +1417,38 @@
// Standard intent broadcast actions (see action variable).
/**
- * Broadcast Action: Sent after the screen turns off.
+ * Broadcast Action: Sent when the device goes to sleep and becomes non-interactive.
+ * <p>
+ * For historical reasons, the name of this broadcast action refers to the power
+ * state of the screen but it is actually sent in response to changes in the
+ * overall interactive state of the device.
+ * </p><p>
+ * This broadcast is sent when the device becomes non-interactive which may have
+ * nothing to do with the screen turning off. To determine the
+ * actual state of the screen, use {@link android.view.Display#getState}.
+ * </p><p>
+ * See {@link android.os.PowerManager#isInteractive} for details.
+ * </p>
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
+
/**
- * Broadcast Action: Sent after the screen turns on.
+ * Broadcast Action: Sent when the device wakes up and becomes interactive.
+ * <p>
+ * For historical reasons, the name of this broadcast action refers to the power
+ * state of the screen but it is actually sent in response to changes in the
+ * overall interactive state of the device.
+ * </p><p>
+ * This broadcast is sent when the device becomes interactive which may have
+ * nothing to do with the screen turning on. To determine the
+ * actual state of the screen, use {@link android.view.Display#getState}.
+ * </p><p>
+ * See {@link android.os.PowerManager#isInteractive} for details.
+ * </p>
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
new file mode 100644
index 0000000..6587f02
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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 android.hardware.camera2;
+
+/** @hide */
+parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.java b/core/java/android/hardware/camera2/CaptureResultExtras.java
new file mode 100644
index 0000000..e5c2c1c
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.java
@@ -0,0 +1,90 @@
+/*
+ * 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 android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class CaptureResultExtras implements Parcelable {
+ private int requestId;
+ private int subsequenceId;
+ private int afTriggerId;
+ private int precaptureTriggerId;
+ private long frameNumber;
+
+ public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
+ new Parcelable.Creator<CaptureResultExtras>() {
+ @Override
+ public CaptureResultExtras createFromParcel(Parcel in) {
+ return new CaptureResultExtras(in);
+ }
+
+ @Override
+ public CaptureResultExtras[] newArray(int size) {
+ return new CaptureResultExtras[size];
+ }
+ };
+
+ private CaptureResultExtras(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(requestId);
+ dest.writeInt(subsequenceId);
+ dest.writeInt(afTriggerId);
+ dest.writeInt(precaptureTriggerId);
+ dest.writeLong(frameNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ requestId = in.readInt();
+ subsequenceId = in.readInt();
+ afTriggerId = in.readInt();
+ precaptureTriggerId = in.readInt();
+ frameNumber = in.readLong();
+ }
+
+ public int getRequestId() {
+ return requestId;
+ }
+
+ public int getSubsequenceId() {
+ return subsequenceId;
+ }
+
+ public int getAfTriggerId() {
+ return afTriggerId;
+ }
+
+ public int getPrecaptureTriggerId() {
+ return precaptureTriggerId;
+ }
+
+ public long getFrameNumber() {
+ return frameNumber;
+ }
+
+}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 02a73d66..a14d38b 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -17,6 +17,7 @@
package android.hardware.camera2;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.CaptureResultExtras;
/** @hide */
interface ICameraDeviceCallbacks
@@ -25,8 +26,9 @@
* Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
*/
- oneway void onCameraError(int errorCode);
+ oneway void onCameraError(int errorCode, in CaptureResultExtras resultExtras);
oneway void onCameraIdle();
- oneway void onCaptureStarted(int requestId, long timestamp);
- oneway void onResultReceived(int requestId, in CameraMetadataNative result);
+ oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
+ oneway void onResultReceived(in CameraMetadataNative result,
+ in CaptureResultExtras resultExtras);
}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 1936963..d77f3d1 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -20,6 +20,8 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.LongParcelable;
+
/** @hide */
interface ICameraDeviceUser
{
@@ -31,9 +33,13 @@
// ints here are status_t
// non-negative value is the requestId. negative value is status_t
- int submitRequest(in CaptureRequest request, boolean streaming);
+ int submitRequest(in CaptureRequest request, boolean streaming,
+ out LongParcelable lastFrameNumber);
- int cancelRequest(int requestId);
+ int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
+ out LongParcelable lastFrameNumber);
+
+ int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
int deleteStream(int streamId);
@@ -46,5 +52,5 @@
int waitUntilIdle();
- int flush();
+ int flush(out LongParcelable lastFrameNumber);
}
diff --git a/core/java/android/hardware/camera2/LongParcelable.aidl b/core/java/android/hardware/camera2/LongParcelable.aidl
new file mode 100644
index 0000000..7d7e51b
--- /dev/null
+++ b/core/java/android/hardware/camera2/LongParcelable.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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 android.hardware.camera2;
+
+/** @hide */
+parcelable LongParcelable;
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/LongParcelable.java b/core/java/android/hardware/camera2/LongParcelable.java
new file mode 100644
index 0000000..97b0631
--- /dev/null
+++ b/core/java/android/hardware/camera2/LongParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * 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 android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class LongParcelable implements Parcelable {
+ private long number;
+
+ public LongParcelable() {
+ this.number = 0;
+ }
+
+ public LongParcelable(long number) {
+ this.number = number;
+ }
+
+ public static final Parcelable.Creator<LongParcelable> CREATOR =
+ new Parcelable.Creator<LongParcelable>() {
+ @Override
+ public LongParcelable createFromParcel(Parcel in) {
+ return new LongParcelable(in);
+ }
+
+ @Override
+ public LongParcelable[] newArray(int size) {
+ return new LongParcelable[size];
+ }
+ };
+
+ private LongParcelable(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(number);
+ }
+
+ public void readFromParcel(Parcel in) {
+ number = in.readLong();
+ }
+
+ public long getNumber() {
+ return number;
+ }
+
+ public void setNumber(long number) {
+ this.number = number;
+ }
+
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index ecc461e..cd44b51 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -21,8 +21,10 @@
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.LongParcelable;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.os.Handler;
@@ -33,10 +35,12 @@
import android.util.SparseArray;
import android.view.Surface;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.TreeSet;
/**
* HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
@@ -69,10 +73,24 @@
private final String mCameraId;
+ /**
+ * A list tracking request and its expected last frame.
+ * Updated when calling ICameraDeviceUser methods.
+ */
+ private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>>
+ mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>();
+
+ /**
+ * An object tracking received frame numbers.
+ * Updated when receiving callbacks from ICameraDeviceCallbacks.
+ */
+ private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+
// Runnables for all state transitions, except error, which needs the
// error code argument
private final Runnable mCallOnOpened = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onOpened(CameraDevice.this);
@@ -81,6 +99,7 @@
};
private final Runnable mCallOnUnconfigured = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onUnconfigured(CameraDevice.this);
@@ -89,6 +108,7 @@
};
private final Runnable mCallOnActive = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onActive(CameraDevice.this);
@@ -97,6 +117,7 @@
};
private final Runnable mCallOnBusy = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onBusy(CameraDevice.this);
@@ -105,12 +126,14 @@
};
private final Runnable mCallOnClosed = new Runnable() {
+ @Override
public void run() {
mDeviceListener.onClosed(CameraDevice.this);
}
};
private final Runnable mCallOnIdle = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onIdle(CameraDevice.this);
@@ -119,6 +142,7 @@
};
private final Runnable mCallOnDisconnected = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onDisconnected(CameraDevice.this);
@@ -249,22 +273,26 @@
@Override
public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException {
- return submitCaptureRequest(request, listener, handler, /*streaming*/false);
+ if (DEBUG) {
+ Log.d(TAG, "calling capture");
+ }
+ List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+ requestList.add(request);
+ return submitCaptureRequest(requestList, listener, handler, /*streaming*/false);
}
@Override
public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
+ // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
if (requests.isEmpty()) {
Log.w(TAG, "Capture burst request list is empty, do nothing!");
return -1;
}
- // TODO
- throw new UnsupportedOperationException("Burst capture implemented yet");
-
+ return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
}
- private int submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+ private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener,
Handler handler, boolean repeating) throws CameraAccessException {
// Need a valid handler, or current thread needs to have a looper, if
@@ -281,8 +309,13 @@
stopRepeating();
}
+ LongParcelable lastFrameNumberRef = new LongParcelable();
try {
- requestId = mRemoteDevice.submitRequest(request, repeating);
+ requestId = mRemoteDevice.submitRequestList(requestList, repeating,
+ /*out*/lastFrameNumberRef);
+ if (!repeating) {
+ Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
+ }
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -290,12 +323,29 @@
return -1;
}
if (listener != null) {
- mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
- handler, repeating));
+ mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
+ requestList, handler, repeating));
}
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ /**
+ * If it's the first repeating request, then returned lastFrameNumber can be
+ * negative. Otherwise, it should always be non-negative.
+ */
+ if (((lastFrameNumber < 0) && (requestId > 0))
+ || ((lastFrameNumber < 0) && (!repeating))) {
+ throw new AssertionError(String.format("returned bad frame number %d",
+ lastFrameNumber));
+ }
if (repeating) {
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId));
+ }
mRepeatingRequestId = requestId;
+ } else {
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
}
if (mIdle) {
@@ -310,18 +360,20 @@
@Override
public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
Handler handler) throws CameraAccessException {
- return submitCaptureRequest(request, listener, handler, /*streaming*/true);
+ List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+ requestList.add(request);
+ return submitCaptureRequest(requestList, listener, handler, /*streaming*/true);
}
@Override
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
+ // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
if (requests.isEmpty()) {
Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
return -1;
}
- // TODO
- throw new UnsupportedOperationException("Burst capture implemented yet");
+ return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
}
@Override
@@ -340,7 +392,15 @@
}
try {
- mRemoteDevice.cancelRequest(requestId);
+ LongParcelable lastFrameNumberRef = new LongParcelable();
+ mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ if ((lastFrameNumber < 0) && (requestId > 0)) {
+ throw new AssertionError(String.format("returned bad frame number %d",
+ lastFrameNumber));
+ }
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -379,7 +439,17 @@
mDeviceHandler.post(mCallOnBusy);
try {
- mRemoteDevice.flush();
+ LongParcelable lastFrameNumberRef = new LongParcelable();
+ mRemoteDevice.flush(/*out*/lastFrameNumberRef);
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ long lastFrameNumber = lastFrameNumberRef.getNumber();
+ if (lastFrameNumber < 0) {
+ Log.e(TAG, String.format("returned bad frame number %d", lastFrameNumber));
+ }
+ mFrameNumberRequestPairs.add(
+ new SimpleEntry<Long, Integer>(lastFrameNumber, mRepeatingRequestId));
+ mRepeatingRequestId = REQUEST_ID_NONE;
+ }
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -425,18 +495,18 @@
private final boolean mRepeating;
private final CaptureListener mListener;
- private final CaptureRequest mRequest;
+ private final List<CaptureRequest> mRequestList;
private final Handler mHandler;
- CaptureListenerHolder(CaptureListener listener, CaptureRequest request, Handler handler,
- boolean repeating) {
+ CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList,
+ Handler handler, boolean repeating) {
if (listener == null || handler == null) {
throw new UnsupportedOperationException(
"Must have a valid handler and a valid listener");
}
mRepeating = repeating;
mHandler = handler;
- mRequest = request;
+ mRequestList = new ArrayList<CaptureRequest>(requestList);
mListener = listener;
}
@@ -448,8 +518,24 @@
return mListener;
}
+ public CaptureRequest getRequest(int subsequenceId) {
+ if (subsequenceId >= mRequestList.size()) {
+ throw new IllegalArgumentException(
+ String.format(
+ "Requested subsequenceId %d is larger than request list size %d.",
+ subsequenceId, mRequestList.size()));
+ } else {
+ if (subsequenceId < 0) {
+ throw new IllegalArgumentException(String.format(
+ "Requested subsequenceId %d is negative", subsequenceId));
+ } else {
+ return mRequestList.get(subsequenceId);
+ }
+ }
+ }
+
public CaptureRequest getRequest() {
- return mRequest;
+ return getRequest(0);
}
public Handler getHandler() {
@@ -458,6 +544,105 @@
}
+ /**
+ * This class tracks the last frame number for submitted requests.
+ */
+ public class FrameNumberTracker {
+
+ private long mCompletedFrameNumber = -1;
+ private final TreeSet<Long> mFutureErrorSet = new TreeSet<Long>();
+
+ private void update() {
+ Iterator<Long> iter = mFutureErrorSet.iterator();
+ while (iter.hasNext()) {
+ long errorFrameNumber = iter.next();
+ if (errorFrameNumber == mCompletedFrameNumber + 1) {
+ mCompletedFrameNumber++;
+ iter.remove();
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
+ * This function is called every time when a result or an error is received.
+ * @param frameNumber: the frame number corresponding to the result or error
+ * @param isError: true if it is an error, false if it is not an error
+ */
+ public void updateTracker(long frameNumber, boolean isError) {
+ if (isError) {
+ mFutureErrorSet.add(frameNumber);
+ } else {
+ /**
+ * HAL cannot send an OnResultReceived for frame N unless it knows for
+ * sure that all frames prior to N have either errored out or completed.
+ * So if the current frame is not an error, then all previous frames
+ * should have arrived. The following line checks whether this holds.
+ */
+ if (frameNumber != mCompletedFrameNumber + 1) {
+ throw new AssertionError(String.format(
+ "result frame number %d comes out of order",
+ frameNumber));
+ }
+ mCompletedFrameNumber++;
+ }
+ update();
+ }
+
+ public long getCompletedFrameNumber() {
+ return mCompletedFrameNumber;
+ }
+
+ }
+
+ private void checkAndFireSequenceComplete() {
+ long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+ Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator();
+ while (iter.hasNext()) {
+ final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
+ if (frameNumberRequestPair.getKey() <= completedFrameNumber) {
+
+ // remove request from mCaptureListenerMap
+ final int requestId = frameNumberRequestPair.getValue();
+ final CaptureListenerHolder holder;
+ synchronized (mLock) {
+ int index = CameraDevice.this.mCaptureListenerMap.indexOfKey(requestId);
+ holder = (index >= 0) ? CameraDevice.this.mCaptureListenerMap.valueAt(index)
+ : null;
+ if (holder != null) {
+ CameraDevice.this.mCaptureListenerMap.removeAt(index);
+ }
+ }
+ iter.remove();
+
+ // Call onCaptureSequenceCompleted
+ if (holder != null) {
+ Runnable resultDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDevice.this.isClosed()){
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "fire sequence complete for request %d",
+ requestId));
+ }
+
+ holder.getListener().onCaptureSequenceCompleted(
+ CameraDevice.this,
+ requestId,
+ // TODO: this is problematic, crop long to int
+ frameNumberRequestPair.getKey().intValue());
+ }
+ }
+ };
+ holder.getHandler().post(resultDispatch);
+ }
+
+ }
+ }
+ }
+
public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
//
@@ -492,7 +677,7 @@
}
@Override
- public void onCameraError(final int errorCode) {
+ public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) {
Runnable r = null;
if (isClosed()) return;
@@ -507,6 +692,7 @@
case ERROR_CAMERA_DEVICE:
case ERROR_CAMERA_SERVICE:
r = new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
mDeviceListener.onError(CameraDevice.this, errorCode);
@@ -517,6 +703,11 @@
}
CameraDevice.this.mDeviceHandler.post(r);
}
+
+ // Fire onCaptureSequenceCompleted
+ mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true);
+ checkAndFireSequenceComplete();
+
}
@Override
@@ -535,7 +726,8 @@
}
@Override
- public void onCaptureStarted(int requestId, final long timestamp) {
+ public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
+ int requestId = resultExtras.getRequestId();
if (DEBUG) {
Log.d(TAG, "Capture started for id " + requestId);
}
@@ -555,11 +747,12 @@
// Dispatch capture start notice
holder.getHandler().post(
new Runnable() {
+ @Override
public void run() {
if (!CameraDevice.this.isClosed()) {
holder.getListener().onCaptureStarted(
CameraDevice.this,
- holder.getRequest(),
+ holder.getRequest(resultExtras.getSubsequenceId()),
timestamp);
}
}
@@ -567,48 +760,18 @@
}
@Override
- public void onResultReceived(int requestId, CameraMetadataNative result)
- throws RemoteException {
+ public void onResultReceived(CameraMetadataNative result,
+ CaptureResultExtras resultExtras) throws RemoteException {
+ int requestId = resultExtras.getRequestId();
if (DEBUG) {
Log.d(TAG, "Received result for id " + requestId);
}
- final CaptureListenerHolder holder;
+ final CaptureListenerHolder holder =
+ CameraDevice.this.mCaptureListenerMap.get(requestId);
Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
- synchronized (mLock) {
- // TODO: move this whole map into this class to make it more testable,
- // exposing the methods necessary like subscribeToRequest, unsubscribe..
- // TODO: make class static class
-
- holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
-
- // Clean up listener once we no longer expect to see it.
- if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) {
- CameraDevice.this.mCaptureListenerMap.remove(requestId);
- }
-
- // TODO: add 'capture sequence completed' callback to the
- // service, and clean up repeating requests there instead.
-
- // If we received a result for a repeating request and have
- // prior repeating requests queued for deletion, remove those
- // requests from mCaptureListenerMap.
- if (holder != null && holder.isRepeating() && !quirkIsPartialResult
- && mRepeatingRequestIdDeletedList.size() > 0) {
- Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator();
- while (iter.hasNext()) {
- int deletedRequestId = iter.next();
- if (deletedRequestId < requestId) {
- CameraDevice.this.mCaptureListenerMap.remove(deletedRequestId);
- iter.remove();
- }
- }
- }
-
- }
-
// Check if we have a listener for this
if (holder == null) {
return;
@@ -616,7 +779,7 @@
if (isClosed()) return;
- final CaptureRequest request = holder.getRequest();
+ final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());
final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
Runnable resultDispatch = null;
@@ -651,6 +814,12 @@
}
holder.getHandler().post(resultDispatch);
+
+ // Fire onCaptureSequenceCompleted
+ if (!quirkIsPartialResult) {
+ mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false);
+ checkAndFireSequenceComplete();
+ }
}
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 03fa1d5..cec90cd 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -58,16 +58,6 @@
public abstract boolean isProximitySensorAvailable();
/**
- * Called by the power manager to blank all displays.
- */
- public abstract void blankAllDisplaysFromPowerManager();
-
- /**
- * Called by the power manager to unblank all displays.
- */
- public abstract void unblankAllDisplaysFromPowerManager();
-
- /**
* Returns information about the specified logical display.
*
* @param displayId The logical display id.
@@ -254,12 +244,10 @@
void onStateChanged();
void onProximityPositive();
void onProximityNegative();
+ void onDisplayStateChange(int state); // one of the Display state constants
void acquireSuspendBlocker();
void releaseSuspendBlocker();
-
- void blankAllDisplays();
- void unblankAllDisplays();
}
/**
diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java
index 1f382e6..cd86cd8 100644
--- a/core/java/android/hardware/hdmi/HdmiCecClient.java
+++ b/core/java/android/hardware/hdmi/HdmiCecClient.java
@@ -88,7 +88,7 @@
}
/**
- * Send <TextViewOn> message.
+ * Send <Text View On> message.
*/
public void sendTextViewOn() {
try {
@@ -99,7 +99,7 @@
}
/**
- * Send <ImageViewOn> message.
+ * Send <Image View On> message.
*/
public void sendImageViewOn() {
try {
@@ -110,6 +110,20 @@
}
/**
+ * Send <Give Device Power Status> message.
+ *
+ * @param address logical address of the device to send the message to, such as
+ * {@link HdmiCec#ADDR_TV}.
+ */
+ public void sendGiveDevicePowerStatus(int address) {
+ try {
+ mService.sendGiveDevicePowerStatus(mBinder, address);
+ } catch (RemoteException e) {
+ Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e);
+ }
+ }
+
+ /**
* Returns true if the TV or attached display is powered on.
* <p>
* The result of this method is only meaningful on playback devices (where the device
diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
index b5df131..ecdd345 100644
--- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
@@ -33,6 +33,7 @@
void sendInactiveSource(IBinder b);
void sendImageViewOn(IBinder b);
void sendTextViewOn(IBinder b);
+ void sendGiveDevicePowerStatus(IBinder b, int address);
boolean isTvOn(IBinder b);
void sendMessage(IBinder b, in HdmiCecMessage message);
}
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 8be94d0..6a392dd 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -25,12 +25,18 @@
* @hide Only for use within the system server.
*/
public abstract class InputManagerInternal {
+ public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
+
/**
- * Sets information about the displays as needed by the input system.
- * The input system should copy this information if required.
+ * Called by the display manager to set information about the displays as needed
+ * by the input system. The input system must copy this information to retain it.
*/
public abstract void setDisplayViewports(DisplayViewport defaultViewport,
DisplayViewport externalTouchViewport);
- public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
+ /**
+ * Called by the power manager to tell the input manager whether it should start
+ * watching for wake events.
+ */
+ public abstract void setInteractive(boolean interactive);
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index be3c0cc..6c7b08d 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -40,8 +40,8 @@
void wakeUp(long time);
void goToSleep(long time, int reason);
void nap(long time);
+ boolean isInteractive();
- boolean isScreenOn();
void reboot(boolean confirm, String reason, boolean wait);
void shutdown(boolean confirm, boolean wait);
void crash(String message);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a195200..f8d7c3e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -601,21 +601,64 @@
}
/**
- * Returns whether the screen is currently on.
+ * Returns true if the device is in an interactive state.
* <p>
- * Only indicates whether the screen is on. The screen could be either bright or dim.
+ * For historical reasons, the name of this method refers to the power state of
+ * the screen but it actually describes the overall interactive state of
+ * the device. This method has been replaced by {@link #isInteractive}.
* </p><p>
- * {@samplecode
- * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- * boolean isScreenOn = pm.isScreenOn();
- * }
+ * The value returned by this method only indicates whether the device is
+ * in an interactive state which may have nothing to do with the screen being
+ * on or off. To determine the actual state of the screen,
+ * use {@link android.view.Display#getState}.
* </p>
*
- * @return whether the screen is on (bright or dim).
+ * @return True if the device is in an interactive state.
+ *
+ * @deprecated Use {@link #isInteractive} instead.
*/
+ @Deprecated
public boolean isScreenOn() {
+ return isInteractive();
+ }
+
+ /**
+ * Returns true if the device is in an interactive state.
+ * <p>
+ * When this method returns true, the device is awake and ready to interact
+ * with the user (although this is not a guarantee that the user is actively
+ * interacting with the device just this moment). The main screen is usually
+ * turned on while in this state. Certain features, such as the proximity
+ * sensor, may temporarily turn off the screen while still leaving the device in an
+ * interactive state. Note in particular that the device is still considered
+ * to be interactive while dreaming (since dreams can be interactive) but not
+ * when it is dozing or asleep.
+ * </p><p>
+ * When this method returns false, the device is dozing or asleep and must
+ * be awoken before it will become ready to interact with the user again. The
+ * main screen is usually turned off while in this state. Certain features,
+ * such as "ambient mode" may cause the main screen to remain on (albeit in a
+ * low power state) to display system-provided content while the device dozes.
+ * </p><p>
+ * The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on}
+ * or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast
+ * whenever the interactive state of the device changes. For historical reasons,
+ * the names of these broadcasts refer to the power state of the screen
+ * but they are actually sent in response to changes in the overall interactive
+ * state of the device, as described by this method.
+ * </p><p>
+ * Services may use the non-interactive state as a hint to conserve power
+ * since the user is not present.
+ * </p>
+ *
+ * @return True if the device is in an interactive state.
+ *
+ * @see android.content.Intent#ACTION_SCREEN_ON
+ * @see android.content.Intent#ACTION_SCREEN_OFF
+ */
+ public boolean isInteractive() {
try {
- return mService.isScreenOn();
+ return mService.isInteractive();
} catch (RemoteException e) {
return false;
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index de9eeff..2303d65 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -789,10 +789,20 @@
return;
}
- // start it up
- if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
- mStarted = true;
- onDreamingStarted();
+ // We need to defer calling onDreamingStarted until after onWindowAttached,
+ // which is posted to the handler by addView, so we post onDreamingStarted
+ // to the handler also. Need to watch out here in case detach occurs before
+ // this callback is invoked.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mWindow != null) {
+ if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
+ mStarted = true;
+ onDreamingStarted();
+ }
+ }
+ });
}
private void safelyFinish() {
diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java
index 90625d8..90e4177 100644
--- a/core/java/android/tv/TvInputInfo.java
+++ b/core/java/android/tv/TvInputInfo.java
@@ -87,6 +87,34 @@
return 0;
}
+ @Override
+ public int hashCode() {
+ return mId.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof TvInputInfo)) {
+ return false;
+ }
+
+ TvInputInfo obj = (TvInputInfo) o;
+ return mId.equals(obj.mId)
+ && mService.serviceInfo.packageName.equals(obj.mService.serviceInfo.packageName)
+ && mService.serviceInfo.name.equals(obj.mService.serviceInfo.name);
+ }
+
+ @Override
+ public String toString() {
+ return "TvInputInfo{id=" + mId
+ + ", pkg=" + mService.serviceInfo.packageName
+ + ", service=" + mService.serviceInfo.name + "}";
+ }
+
/**
* Used to package this object into a {@link Parcel}.
*
diff --git a/core/java/android/view/AnimationRenderStats.aidl b/core/java/android/view/AnimationRenderStats.aidl
new file mode 100644
index 0000000..4599708
--- /dev/null
+++ b/core/java/android/view/AnimationRenderStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.view;
+
+parcelable AnimationRenderStats;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index d3f63b4..d7a913d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -204,6 +204,36 @@
public static final int TYPE_VIRTUAL = 5;
/**
+ * Display state: The display state is unknown.
+ *
+ * @see #getState
+ */
+ public static final int STATE_UNKNOWN = 0;
+
+ /**
+ * Display state: The display is off.
+ *
+ * @see #getState
+ */
+ public static final int STATE_OFF = 1;
+
+ /**
+ * Display state: The display is on.
+ *
+ * @see #getState
+ */
+ public static final int STATE_ON = 2;
+
+ /**
+ * Display state: The display is dozing in a low-power state; it may be showing
+ * system-provided content while the device is in a non-interactive state.
+ *
+ * @see #getState
+ * @see android.os.PowerManager#isInteractive
+ */
+ public static final int STATE_DOZING = 3;
+
+ /**
* Internal method to create a display.
* Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
* or {@link android.hardware.display.DisplayManager#getDisplay}
@@ -630,6 +660,19 @@
}
/**
+ * Gets the state of the display, such as whether it is on or off.
+ *
+ * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
+ * {@link #STATE_DOZING}, or {@link #STATE_UNKNOWN}.
+ */
+ public int getState() {
+ synchronized (this) {
+ updateDisplayInfoLocked();
+ return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN;
+ }
+ }
+
+ /**
* Returns true if the specified UID has access to this display.
* @hide
*/
@@ -720,5 +763,22 @@
return Integer.toString(type);
}
}
-}
+ /**
+ * @hide
+ */
+ public static String stateToString(int state) {
+ switch (state) {
+ case STATE_UNKNOWN:
+ return "UNKNOWN";
+ case STATE_OFF:
+ return "OFF";
+ case STATE_ON:
+ return "ON";
+ case STATE_DOZING:
+ return "DOZING";
+ default:
+ return Integer.toString(state);
+ }
+ }
+}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 7fd7b83..b0fe0fa 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -180,6 +180,11 @@
public float physicalYDpi;
/**
+ * The state of the display, such as {@link android.view.Display#STATE_ON}.
+ */
+ public int state;
+
+ /**
* The UID of the application that owns this display, or zero if it is owned by the system.
* <p>
* If the display is private, then only the owner can use it.
@@ -248,6 +253,7 @@
&& logicalDensityDpi == other.logicalDensityDpi
&& physicalXDpi == other.physicalXDpi
&& physicalYDpi == other.physicalYDpi
+ && state == other.state
&& ownerUid == other.ownerUid
&& Objects.equal(ownerPackageName, other.ownerPackageName);
}
@@ -280,6 +286,7 @@
logicalDensityDpi = other.logicalDensityDpi;
physicalXDpi = other.physicalXDpi;
physicalYDpi = other.physicalYDpi;
+ state = other.state;
ownerUid = other.ownerUid;
ownerPackageName = other.ownerPackageName;
}
@@ -307,6 +314,7 @@
logicalDensityDpi = source.readInt();
physicalXDpi = source.readFloat();
physicalYDpi = source.readFloat();
+ state = source.readInt();
ownerUid = source.readInt();
ownerPackageName = source.readString();
}
@@ -335,6 +343,7 @@
dest.writeInt(logicalDensityDpi);
dest.writeFloat(physicalXDpi);
dest.writeFloat(physicalYDpi);
+ dest.writeInt(state);
dest.writeInt(ownerUid);
dest.writeString(ownerPackageName);
}
@@ -431,7 +440,7 @@
sb.append(smallestNominalAppHeight);
sb.append(", ");
sb.append(refreshRate);
- sb.append(" fps, rotation");
+ sb.append(" fps, rotation ");
sb.append(rotation);
sb.append(", density ");
sb.append(logicalDensityDpi);
@@ -446,6 +455,8 @@
if (address != null) {
sb.append(", address ").append(address);
}
+ sb.append(", state ");
+ sb.append(Display.stateToString(state));
if (ownerUid != 0 || ownerPackageName != null) {
sb.append(", owner ").append(ownerPackageName);
sb.append(" (uid ").append(ownerUid).append(")");
diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java
new file mode 100644
index 0000000..541b336
--- /dev/null
+++ b/core/java/android/view/FrameStats.java
@@ -0,0 +1,97 @@
+/*
+ * 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 android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This is the base class for frame statistics.
+ */
+public abstract class FrameStats {
+ /**
+ * Undefined time.
+ */
+ public static final long UNDEFINED_TIME_NANO = -1;
+
+ protected long mRefreshPeriodNano;
+ protected long[] mFramesPresentedTimeNano;
+
+ /**
+ * Gets the refresh period of the display hosting the window(s) for
+ * which these statistics apply.
+ *
+ * @return The refresh period in nanoseconds.
+ */
+ public final long getRefreshPeriodNano() {
+ return mRefreshPeriodNano;
+ }
+
+ /**
+ * Gets the number of frames for which there is data.
+ *
+ * @return The number of frames.
+ */
+ public final int getFrameCount() {
+ return mFramesPresentedTimeNano != null
+ ? mFramesPresentedTimeNano.length : 0;
+ }
+
+ /**
+ * Gets the start time of the interval for which these statistics
+ * apply. The start interval is the time when the first frame was
+ * presented.
+ *
+ * @return The start time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if there is no frame data.
+ */
+ public final long getStartTimeNano() {
+ if (getFrameCount() <= 0) {
+ return UNDEFINED_TIME_NANO;
+ }
+ return mFramesPresentedTimeNano[0];
+ }
+
+ /**
+ * Gets the end time of the interval for which these statistics
+ * apply. The end interval is the time when the last frame was
+ * presented.
+ *
+ * @return The end time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if there is no frame data.
+ */
+ public final long getEndTimeNano() {
+ if (getFrameCount() <= 0) {
+ return UNDEFINED_TIME_NANO;
+ }
+ return mFramesPresentedTimeNano[mFramesPresentedTimeNano.length - 1];
+ }
+
+ /**
+ * Get the time a frame at a given index was presented.
+ *
+ * @param index The frame index.
+ * @return The presented time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if the frame is not presented yet.
+ */
+ public final long getFramePresentedTimeNano(int index) {
+ if (mFramesPresentedTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesPresentedTimeNano[index];
+ }
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8f542bb..80d5bf2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -37,6 +37,7 @@
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.IInputFilter;
+import android.view.WindowContentFrameStats;
/**
* System private interface to the window manager.
@@ -233,4 +234,20 @@
* Device is in safe mode.
*/
boolean isSafeModeEnabled();
+
+ /**
+ * Clears the frame statistics for a given window.
+ *
+ * @param token The window token.
+ * @return Whether the frame statistics were cleared.
+ */
+ boolean clearWindowContentFrameStats(IBinder token);
+
+ /**
+ * Gets the content frame statistics for a given window.
+ *
+ * @param token The window token.
+ * @return The frame statistics or null if the window does not exist.
+ */
+ WindowContentFrameStats getWindowContentFrameStats(IBinder token);
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index c183f08..c3f429c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1166,7 +1166,11 @@
/**
* This mask is set if the device woke because of this key event.
+ *
+ * @deprecated This flag will never be set by the system since the system
+ * consumes all wake keys itself.
*/
+ @Deprecated
public static final int FLAG_WOKE_HERE = 0x1;
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5a8d2c8..2d55a01 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -20,7 +20,6 @@
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Region;
-import android.view.Surface;
import android.os.IBinder;
import android.util.Log;
import android.view.Surface.OutOfResourcesException;
@@ -59,6 +58,11 @@
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetLayerStack(long nativeObject, int layerStack);
+ private static native boolean nativeClearContentFrameStats(long nativeObject);
+ private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
+ private static native boolean nativeClearAnimationFrameStats();
+ private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
+
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
private static native IBinder nativeCreateDisplay(String name, boolean secure);
private static native void nativeDestroyDisplay(IBinder displayToken);
@@ -357,6 +361,24 @@
nativeSetTransparentRegionHint(mNativeObject, region);
}
+ public boolean clearContentFrameStats() {
+ checkNotReleased();
+ return nativeClearContentFrameStats(mNativeObject);
+ }
+
+ public boolean getContentFrameStats(WindowContentFrameStats outStats) {
+ checkNotReleased();
+ return nativeGetContentFrameStats(mNativeObject, outStats);
+ }
+
+ public static boolean clearAnimationFrameStats() {
+ return nativeClearAnimationFrameStats();
+ }
+
+ public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
+ return nativeGetAnimationFrameStats(outStats);
+ }
+
/**
* Sets an alpha value for the entire Surface. This value is combined with the
* per-pixel alpha. It may be used with opaque Surfaces.
@@ -542,7 +564,6 @@
return nativeGetBuiltInDisplay(builtInDisplayId);
}
-
/**
* Copy the current screen contents into the provided {@link Surface}
*
@@ -592,7 +613,6 @@
screenshot(display, consumer, 0, 0, 0, 0, true, false);
}
-
/**
* Copy the current screen contents into a bitmap and return it.
*
@@ -626,8 +646,8 @@
}
/**
- * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
- * Surfaces in the screenshot.
+ * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
+ * includes all Surfaces in the screenshot.
*
* @param width The desired width of the returned bitmap; the raw
* screen will be scaled down to this size.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 1ecc3c6..789b761 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -190,12 +190,12 @@
@Override
void detachFunctor(long functor) {
- nDetachFunctor(mNativeProxy, functor);
+ // no-op, we never attach functors to need to detach them
}
@Override
void attachFunctor(AttachInfo attachInfo, long functor) {
- nAttachFunctor(mNativeProxy, functor);
+ invokeFunctor(functor, true);
}
@Override
@@ -289,8 +289,6 @@
private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
private static native void nDestroyCanvas(long nativeProxy);
- private static native void nAttachFunctor(long nativeProxy, long functor);
- private static native void nDetachFunctor(long nativeProxy, long functor);
private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index b05225b..8eae629 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -27,6 +27,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.AudioService;
import android.media.AudioSystem;
@@ -238,6 +240,7 @@
cleanUp();
}
+ @Override
public void onDismiss(DialogInterface unused) {
mContext.unregisterReceiver(this);
cleanUp();
@@ -259,8 +262,8 @@
mAudioService = volumeService;
// For now, only show master volume if master volume is supported
- boolean useMasterVolume = context.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
+ final boolean useMasterVolume = context.getResources().getBoolean(
+ R.bool.config_useMasterVolume);
if (useMasterVolume) {
for (int i = 0; i < STREAMS.length; i++) {
StreamResources streamRes = STREAMS[i];
@@ -268,10 +271,18 @@
}
}
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = mView = inflater.inflate(R.layout.volume_adjust, null);
+ final TypedArray a = context.obtainStyledAttributes(null,
+ com.android.internal.R.styleable.AlertDialog,
+ com.android.internal.R.attr.alertDialogStyle, 0);
+ final Drawable background = a.getDrawable(R.styleable.AlertDialog_fullBright);
+ a.recycle();
+
+ final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ mView = inflater.inflate(R.layout.volume_adjust, null);
+ mView.setBackground(background);
mView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
public boolean onTouch(View v, MotionEvent event) {
resetTimeout();
return false;
@@ -279,10 +290,11 @@
});
mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel);
mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group);
- mMoreButton = (ImageView) mView.findViewById(R.id.expand_button);
- mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider);
+ mMoreButton = mView.findViewById(R.id.expand_button);
+ mDivider = mView.findViewById(R.id.expand_button_divider);
mDialog = new Dialog(context, R.style.Theme_Panel_Volume) {
+ @Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE &&
sConfirmSafeVolumeDialog == null) {
@@ -292,22 +304,25 @@
return false;
}
};
+
mDialog.setTitle("Volume control"); // No need to localize
mDialog.setContentView(mView);
mDialog.setOnDismissListener(new OnDismissListener() {
+ @Override
public void onDismiss(DialogInterface dialog) {
mActiveStreamType = -1;
mAudioManager.forceVolumeControlStream(mActiveStreamType);
}
});
+
// Change some window properties
- Window window = mDialog.getWindow();
+ final Window window = mDialog.getWindow();
window.setGravity(Gravity.TOP);
- LayoutParams lp = window.getAttributes();
+
+ final LayoutParams lp = window.getAttributes();
lp.token = null;
// Offset from the top
- lp.y = mContext.getResources().getDimensionPixelOffset(
- com.android.internal.R.dimen.volume_panel_top);
+ lp.y = mContext.getResources().getDimensionPixelOffset(R.dimen.volume_panel_top);
lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
@@ -320,6 +335,7 @@
mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable);
mShowCombinedVolumes = !mVoiceCapable && !useMasterVolume;
+
// If we don't want to show multiple volumes, hide the settings button and divider
if (!mShowCombinedVolumes) {
mMoreButton.setVisibility(View.GONE);
@@ -328,10 +344,10 @@
mMoreButton.setOnClickListener(this);
}
- boolean masterVolumeOnly = context.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
- boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_useVolumeKeySounds);
+ final boolean masterVolumeOnly = context.getResources().getBoolean(
+ R.bool.config_useMasterVolume);
+ final boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
+ R.bool.config_useVolumeKeySounds);
mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
@@ -347,7 +363,7 @@
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
mContext.registerReceiver(new BroadcastReceiver() {
-
+ @Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
@@ -400,17 +416,21 @@
}
private void createSliders() {
- LayoutInflater inflater = (LayoutInflater) mContext
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ final Resources res = mContext.getResources();
+ final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length);
- Resources res = mContext.getResources();
+
for (int i = 0; i < STREAMS.length; i++) {
StreamResources streamRes = STREAMS[i];
- int streamType = streamRes.streamType;
+
+ final int streamType = streamRes.streamType;
if (mVoiceCapable && streamRes == StreamResources.NotificationStream) {
streamRes = StreamResources.RingerStream;
}
- StreamControl sc = new StreamControl();
+
+ final StreamControl sc = new StreamControl();
sc.streamType = streamType;
sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
sc.group.setTag(sc);
@@ -421,7 +441,7 @@
sc.iconMuteRes = streamRes.iconMuteRes;
sc.icon.setImageResource(sc.iconRes);
sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);
- int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
+ final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
sc.seekbarView.setOnSeekBarChangeListener(this);
@@ -433,7 +453,7 @@
private void reorderSliders(int activeStreamType) {
mSliderGroup.removeAllViews();
- StreamControl active = mStreamControls.get(activeStreamType);
+ final StreamControl active = mStreamControls.get(activeStreamType);
if (active == null) {
Log.e("VolumePanel", "Missing stream type! - " + activeStreamType);
mActiveStreamType = -1;
diff --git a/core/java/android/view/WindowAnimationFrameStats.aidl b/core/java/android/view/WindowAnimationFrameStats.aidl
new file mode 100644
index 0000000..77f544b
--- /dev/null
+++ b/core/java/android/view/WindowAnimationFrameStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.view;
+
+parcelable WindowAnimationFrameStats;
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
new file mode 100644
index 0000000..c60b96c
--- /dev/null
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -0,0 +1,94 @@
+/*
+ * 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 android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window animation frame statistics. For example, a window
+ * animation is usually performed when the application is transitioning from one
+ * activity to another. The frame statistics are a snapshot for the time interval
+ * from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience the system should
+ * run window animations at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the system does not render a frame every refresh
+ * period the user will see irregular window transitions. The time when the frame was
+ * actually presented on the display by calling {@link #getFramePresentedTimeNano(int)}.
+ */
+public final class WindowAnimationFrameStats extends FrameStats implements Parcelable {
+ /**
+ * @hide
+ */
+ public WindowAnimationFrameStats() {
+ /* do nothing */
+ }
+
+ /**
+ * Initializes this isntance.
+ *
+ * @param refreshPeriodNano The display refresh period.
+ * @param framesPresentedTimeNano The presented frame times.
+ *
+ * @hide
+ */
+ public void init(long refreshPeriodNano, long[] framesPresentedTimeNano) {
+ mRefreshPeriodNano = refreshPeriodNano;
+ mFramesPresentedTimeNano = framesPresentedTimeNano;
+ }
+
+ private WindowAnimationFrameStats(Parcel parcel) {
+ mRefreshPeriodNano = parcel.readLong();
+ mFramesPresentedTimeNano = parcel.createLongArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeLong(mRefreshPeriodNano);
+ parcel.writeLongArray(mFramesPresentedTimeNano);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WindowAnimationFrameStats[");
+ builder.append("frameCount:" + getFrameCount());
+ builder.append(", fromTimeNano:" + getStartTimeNano());
+ builder.append(", toTimeNano:" + getEndTimeNano());
+ builder.append(']');
+ return builder.toString();
+ }
+
+ public static final Creator<WindowAnimationFrameStats> CREATOR =
+ new Creator<WindowAnimationFrameStats>() {
+ @Override
+ public WindowAnimationFrameStats createFromParcel(Parcel parcel) {
+ return new WindowAnimationFrameStats(parcel);
+ }
+
+ @Override
+ public WindowAnimationFrameStats[] newArray(int size) {
+ return new WindowAnimationFrameStats[size];
+ }
+ };
+}
diff --git a/core/java/android/view/WindowContentFrameStats.aidl b/core/java/android/view/WindowContentFrameStats.aidl
new file mode 100644
index 0000000..aa9c2d6
--- /dev/null
+++ b/core/java/android/view/WindowContentFrameStats.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.view;
+
+parcelable WindowContentFrameStats;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
new file mode 100644
index 0000000..c6da2fb
--- /dev/null
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -0,0 +1,152 @@
+/*
+ * 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 android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window content frame statistics. For example, a window content
+ * is rendred in frames when a view is scrolled. The frame statistics are a snapshot
+ * for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience an application
+ * has to draw a frame at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the application does not render a frame every refresh
+ * period the user will see irregular UI transitions.
+ * </p>
+ * <p>
+ * An application posts a frame for presentation by synchronously rendering its contents
+ * in a buffer which is then posted or posting a buffer to which the application is
+ * asychronously rendering the content via GL. After the frame is posted and rendered
+ * (potentially asynchronosly) it is presented to the user. The time a frame was posted
+ * can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
+ * was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
+ * and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
+ * </p>
+ */
+public final class WindowContentFrameStats extends FrameStats implements Parcelable {
+ private long[] mFramesPostedTimeNano;
+ private long[] mFramesReadyTimeNano;
+
+ /**
+ * @hide
+ */
+ public WindowContentFrameStats() {
+ /* do nothing */
+ }
+
+ /**
+ * Initializes this isntance.
+ *
+ * @param refreshPeriodNano The display refresh period.
+ * @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
+ * @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
+ * @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
+ *
+ * @hide
+ */
+ public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
+ long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
+ mRefreshPeriodNano = refreshPeriodNano;
+ mFramesPostedTimeNano = framesPostedTimeNano;
+ mFramesPresentedTimeNano = framesPresentedTimeNano;
+ mFramesReadyTimeNano = framesReadyTimeNano;
+ }
+
+ private WindowContentFrameStats(Parcel parcel) {
+ mRefreshPeriodNano = parcel.readLong();
+ mFramesPostedTimeNano = parcel.createLongArray();
+ mFramesPresentedTimeNano = parcel.createLongArray();
+ mFramesReadyTimeNano = parcel.createLongArray();
+ }
+
+ /**
+ * Get the time a frame at a given index was posted by the producer (e.g. the application).
+ * It is either explicitly set or defaulted to the time when the render buffer was posted.
+ * <p>
+ * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+ * asynchronously in GL. To get the time the frame content was completely rendered and
+ * ready to display call {@link #getFrameReadyTimeNano(int)}.
+ * </p>
+ *
+ * @param index The frame index.
+ * @return The posted time in nanoseconds.
+ */
+ public long getFramePostedTimeNano(int index) {
+ if (mFramesPostedTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesPostedTimeNano[index];
+ }
+
+ /**
+ * Get the time a frame at a given index was ready for presentation.
+ * <p>
+ * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+ * asynchronously in GL. In such a case this is the time when the frame contents were
+ * completely rendered.
+ * </p>
+ *
+ * @param index The frame index.
+ * @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+ * if the frame is not ready yet.
+ */
+ public long getFrameReadyTimeNano(int index) {
+ if (mFramesReadyTimeNano == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mFramesReadyTimeNano[index];
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeLong(mRefreshPeriodNano);
+ parcel.writeLongArray(mFramesPostedTimeNano);
+ parcel.writeLongArray(mFramesPresentedTimeNano);
+ parcel.writeLongArray(mFramesReadyTimeNano);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WindowContentFrameStats[");
+ builder.append("frameCount:" + getFrameCount());
+ builder.append(", fromTimeNano:" + getStartTimeNano());
+ builder.append(", toTimeNano:" + getEndTimeNano());
+ builder.append(']');
+ return builder.toString();
+ }
+
+ public static final Parcelable.Creator<WindowContentFrameStats> CREATOR =
+ new Creator<WindowContentFrameStats>() {
+ @Override
+ public WindowContentFrameStats createFromParcel(Parcel parcel) {
+ return new WindowContentFrameStats(parcel);
+ }
+
+ @Override
+ public WindowContentFrameStats[] newArray(int size) {
+ return new WindowContentFrameStats[size];
+ }
+ };
+}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 53a4c0d0..d5a7d33 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -610,7 +610,10 @@
* screen is pressed, you will receive this first touch event. Usually
* the first touch event is consumed by the system since the user can
* not see what they are pressing on.
+ *
+ * @deprecated This flag has no effect.
*/
+ @Deprecated
public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
/** Window flag: as long as this window is visible to the user, keep
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bd203c8..e68d4c0 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -90,8 +90,7 @@
public final static int FLAG_FILTERED = 0x04000000;
public final static int FLAG_DISABLE_KEY_REPEAT = 0x08000000;
- public final static int FLAG_WOKE_HERE = 0x10000000;
- public final static int FLAG_BRIGHT_HERE = 0x20000000;
+ public final static int FLAG_INTERACTIVE = 0x20000000;
public final static int FLAG_PASS_TO_USER = 0x40000000;
// Flags used for indicating whether the internal and/or external input devices
@@ -744,11 +743,10 @@
* because it's the most fragile.
* @param event The key event.
* @param policyFlags The policy flags associated with the key.
- * @param isScreenOn True if the screen is already on
*
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
*/
- public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
/**
* Called from the input reader thread before a motion is enqueued when the screen is off.
@@ -761,7 +759,7 @@
*
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
*/
- public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
+ public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
/**
* Called from the input dispatcher thread before a key is dispatched to a window.
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index fe3e5c6..b6570cc 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -57,4 +57,6 @@
void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service,
boolean touchExplorationEnabled);
+
+ IBinder getWindowToken(int windowId);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 81d36a4..85168fd 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1691,6 +1691,9 @@
* thread of this WebView. Care is therefore required to maintain thread
* safety.</li>
* <li> The Java object's fields are not accessible.</li>
+ * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#L}
+ * and above, methods of injected Java objects are enumerable from
+ * JavaScript.</li>
* </ul>
*
* @param object the Java object to inject into this WebView's JavaScript
diff --git a/core/java/com/android/internal/notification/PeopleNotificationScorer.java b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
new file mode 100644
index 0000000..efb5f63
--- /dev/null
+++ b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
@@ -0,0 +1,227 @@
+/*
+* 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.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.LruCache;
+import android.util.Slog;
+
+/**
+ * This {@link NotificationScorer} attempts to validate people references.
+ * Also elevates the priority of real people.
+ */
+public class PeopleNotificationScorer implements NotificationScorer {
+ private static final String TAG = "PeopleNotificationScorer";
+ private static final boolean DBG = false;
+
+ private static final boolean ENABLE_PEOPLE_SCORER = true;
+ private static final String SETTING_ENABLE_PEOPLE_SCORER = "people_scorer_enabled";
+ private static final String[] LOOKUP_PROJECTION = { Contacts._ID };
+ private static final int MAX_PEOPLE = 10;
+ private static final int PEOPLE_CACHE_SIZE = 200;
+ // see NotificationManagerService
+ private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
+
+ protected boolean mEnabled;
+ private Context mContext;
+
+ // maps raw person handle to resolved person object
+ private LruCache<String, LookupResult> mPeopleCache;
+
+ private float findMaxContactScore(Bundle extras) {
+ if (extras == null) {
+ return 0f;
+ }
+
+ final String[] people = extras.getStringArray(Notification.EXTRA_PEOPLE);
+ if (people == null || people.length == 0) {
+ return 0f;
+ }
+
+ float rank = 0f;
+ for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
+ final String handle = people[personIdx];
+ if (TextUtils.isEmpty(handle)) continue;
+
+ LookupResult lookupResult = mPeopleCache.get(handle);
+ if (lookupResult == null || lookupResult.isExpired()) {
+ final Uri uri = Uri.parse(handle);
+ if ("tel".equals(uri.getScheme())) {
+ if (DBG) Slog.w(TAG, "checking telephone URI: " + handle);
+ lookupResult = lookupPhoneContact(handle, uri.getSchemeSpecificPart());
+ } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+ if (DBG) Slog.w(TAG, "checking lookup URI: " + handle);
+ lookupResult = resolveContactsUri(handle, uri);
+ } else {
+ if (DBG) Slog.w(TAG, "unsupported URI " + handle);
+ }
+ } else {
+ if (DBG) Slog.w(TAG, "using cached lookupResult: " + lookupResult.mId);
+ }
+ if (lookupResult != null) {
+ rank = Math.max(rank, lookupResult.getRank());
+ }
+ }
+ return rank;
+ }
+
+ private LookupResult lookupPhoneContact(final String handle, final String number) {
+ LookupResult lookupResult = null;
+ Cursor c = null;
+ try {
+ Uri numberUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
+ Uri.encode(number));
+ c = mContext.getContentResolver().query(numberUri, LOOKUP_PROJECTION, null, null, null);
+ if (c != null && c.getCount() > 0) {
+ c.moveToFirst();
+ final int idIdx = c.getColumnIndex(Contacts._ID);
+ final int id = c.getInt(idIdx);
+ if (DBG) Slog.w(TAG, "is valid: " + id);
+ lookupResult = new LookupResult(id);
+ }
+ } catch(Throwable t) {
+ Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ if (lookupResult == null) {
+ lookupResult = new LookupResult(LookupResult.INVALID_ID);
+ }
+ mPeopleCache.put(handle, lookupResult);
+ return lookupResult;
+ }
+
+ private LookupResult resolveContactsUri(String handle, final Uri personUri) {
+ LookupResult lookupResult = null;
+ Cursor c = null;
+ try {
+ c = mContext.getContentResolver().query(personUri, LOOKUP_PROJECTION, null, null, null);
+ if (c != null && c.getCount() > 0) {
+ c.moveToFirst();
+ final int idIdx = c.getColumnIndex(Contacts._ID);
+ final int id = c.getInt(idIdx);
+ if (DBG) Slog.w(TAG, "is valid: " + id);
+ lookupResult = new LookupResult(id);
+ }
+ } catch(Throwable t) {
+ Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ if (lookupResult == null) {
+ lookupResult = new LookupResult(LookupResult.INVALID_ID);
+ }
+ mPeopleCache.put(handle, lookupResult);
+ return lookupResult;
+ }
+
+ private final static int clamp(int x, int low, int high) {
+ return (x < low) ? low : ((x > high) ? high : x);
+ }
+
+ // TODO: rework this function before shipping
+ private static int priorityBumpMap(int incomingScore) {
+ //assumption is that scale runs from [-2*pm, 2*pm]
+ int pm = NOTIFICATION_PRIORITY_MULTIPLIER;
+ int theScore = incomingScore;
+ // enforce input in range
+ theScore = clamp(theScore, -2 * pm, 2 * pm);
+ if (theScore != incomingScore) return incomingScore;
+ // map -20 -> -20 and -10 -> 5 (when pm = 10)
+ if (theScore <= -pm) {
+ theScore += 1.5 * (theScore + 2 * pm);
+ } else {
+ // map 0 -> 10, 10 -> 15, 20 -> 20;
+ theScore += 0.5 * (2 * pm - theScore);
+ }
+ if (DBG) Slog.v(TAG, "priorityBumpMap: score before: " + incomingScore
+ + ", score after " + theScore + ".");
+ return theScore;
+ }
+
+ @Override
+ public void initialize(Context context) {
+ if (DBG) Slog.v(TAG, "Initializing " + getClass().getSimpleName() + ".");
+ mContext = context;
+ mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
+ mEnabled = ENABLE_PEOPLE_SCORER && 1 == Settings.Global.getInt(
+ mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_SCORER, 0);
+ }
+
+ @Override
+ public int getScore(Notification notification, int score) {
+ if (notification == null || !mEnabled) {
+ if (DBG) Slog.w(TAG, "empty notification? scorer disabled?");
+ return score;
+ }
+ float contactScore = findMaxContactScore(notification.extras);
+ if (contactScore > 0f) {
+ if (DBG) Slog.v(TAG, "Notification references a real contact. Promoted!");
+ score = priorityBumpMap(score);
+ } else {
+ if (DBG) Slog.v(TAG, "Notification lacks any valid contact reference. Not promoted!");
+ }
+ return score;
+ }
+
+ private static class LookupResult {
+ private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
+ public static final int INVALID_ID = -1;
+
+ private final long mExpireMillis;
+ private int mId;
+
+ public LookupResult(int id) {
+ mId = id;
+ mExpireMillis = System.currentTimeMillis() + CONTACT_REFRESH_MILLIS;
+ }
+
+ public boolean isExpired() {
+ return mExpireMillis < System.currentTimeMillis();
+ }
+
+ public boolean isInvalid() {
+ return mId == INVALID_ID || isExpired();
+ }
+
+ public float getRank() {
+ if (isInvalid()) {
+ return 0f;
+ } else {
+ return 1f; // TODO: finer grained score
+ }
+ }
+
+ public LookupResult setId(int id) {
+ mId = id;
+ return this;
+ }
+ }
+}
+
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 159ffb2..8141a00 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -34,6 +34,7 @@
#include <gui/SurfaceComposerClient.h>
#include <ui/DisplayInfo.h>
+#include <ui/FrameStats.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -64,6 +65,16 @@
delete ((ScreenshotClient*) context);
}
+static struct {
+ nsecs_t UNDEFINED_TIME_NANO;
+ jmethodID init;
+} gWindowContentFrameStatsClassInfo;
+
+static struct {
+ nsecs_t UNDEFINED_TIME_NANO;
+ jmethodID init;
+} gWindowAnimationFrameStatsClassInfo;
+
// ----------------------------------------------------------------------------
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
@@ -371,6 +382,151 @@
SurfaceComposerClient::unblankDisplay(token);
}
+static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->clearLayerFrameStats();
+
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, just report we failed.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject outStats) {
+ FrameStats stats;
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t err = ctrl->getLayerFrameStats(&stats);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, fine just return empty stats.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+ size_t frameCount = stats.desiredPresentTimesNano.size();
+
+ jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
+ if (postedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+ if (presentedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
+ if (readyTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ nsecs_t postedTimesNanoSrc[frameCount];
+ nsecs_t presentedTimesNanoSrc[frameCount];
+ nsecs_t readyTimesNanoSrc[frameCount];
+
+ for (size_t i = 0; i < frameCount; i++) {
+ nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
+ if (postedTimeNano == INT64_MAX) {
+ postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ postedTimesNanoSrc[i] = postedTimeNano;
+
+ nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
+ if (presentedTimeNano == INT64_MAX) {
+ presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ presentedTimesNanoSrc[i] = presentedTimeNano;
+
+ nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
+ if (readyTimeNano == INT64_MAX) {
+ readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ readyTimesNanoSrc[i] = readyTimeNano;
+ }
+
+ env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
+ env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+ env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
+
+ env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
+ postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
+
+ if (env->ExceptionCheck()) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
+ status_t err = SurfaceComposerClient::clearAnimationFrameStats();
+
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, just report we failed.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
+ FrameStats stats;
+
+ status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+
+ // The other end is not ready, fine just return empty stats.
+ if (err == NO_INIT) {
+ return JNI_FALSE;
+ }
+
+ jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+ size_t frameCount = stats.desiredPresentTimesNano.size();
+
+ jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+ if (presentedTimesNanoDst == NULL) {
+ return JNI_FALSE;
+ }
+
+ nsecs_t presentedTimesNanoSrc[frameCount];
+
+ for (size_t i = 0; i < frameCount; i++) {
+ nsecs_t presentedTimeNano = stats.desiredPresentTimesNano[i];
+ if (presentedTimeNano == INT64_MAX) {
+ presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+ }
+ presentedTimesNanoSrc[i] = presentedTimeNano;
+ }
+
+ env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+
+ env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
+ presentedTimesNanoDst);
+
+ if (env->ExceptionCheck()) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod sSurfaceControlMethods[] = {
@@ -426,6 +582,14 @@
(void*)nativeBlankDisplay },
{"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
(void*)nativeUnblankDisplay },
+ {"nativeClearContentFrameStats", "(J)Z",
+ (void*)nativeClearContentFrameStats },
+ {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
+ (void*)nativeGetContentFrameStats },
+ {"nativeClearAnimationFrameStats", "()Z",
+ (void*)nativeClearAnimationFrameStats },
+ {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
+ (void*)nativeGetAnimationFrameStats },
};
int register_android_view_SurfaceControl(JNIEnv* env)
@@ -441,6 +605,19 @@
gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+
+ jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
+ jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
+ nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
+
+ jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats");
+ gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V");
+ gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
+ jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats");
+ gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V");
+ gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
return err;
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 36c8357..30d3e0c 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -127,20 +127,6 @@
proxy->destroyCanvas();
}
-static void android_view_ThreadedRenderer_attachFunctor(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong functorPtr) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- proxy->attachFunctor(functor);
-}
-
-static void android_view_ThreadedRenderer_detachFunctor(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong functorPtr) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- proxy->detachFunctor(functor);
-}
-
static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -209,8 +195,6 @@
{ "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
{ "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
{ "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
- { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
- { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor },
{ "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0f772f1..a83942f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1921,6 +1921,18 @@
android:description="@string/permdesc_filter_events"
android:protectionLevel="signature" />
+ <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
+ <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
+ android:label="@string/permlab_retrieveWindowToken"
+ android:description="@string/permdesc_retrieveWindowToken"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to collect frame statistics -->
+ <permission android:name="android.permission.FRAME_STATS"
+ android:label="@string/permlab_frameStats"
+ android:description="@string/permdesc_frameStats"
+ android:protectionLevel="signature" />
+
<!-- @hide Allows an application to temporary enable accessibility on the device. -->
<permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
android:label="@string/permlab_temporary_enable_accessibility"
diff --git a/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..32ddf7a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..db9e172
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..805cb29
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..c3791fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum.xml b/core/res/res/drawable/scrubber_control_selector_quantum.xml
index e31c2c1..e34f64a 100644
--- a/core/res/res/drawable/scrubber_control_selector_quantum.xml
+++ b/core/res/res/drawable/scrubber_control_selector_quantum.xml
@@ -15,12 +15,16 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="true" android:state_pressed="true">
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/scrubber_control_off_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_pressed="true">
<bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ android:tint="?attr/colorControlActivated" />
</item>
</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
index 7b124ac..d172b05 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
@@ -15,12 +15,24 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
</item>
<item>
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ <layer-list>
+ <item android:id="@id/background">
+ <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:id="@id/secondaryProgress">
+ <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:id="@id/progress">
+ <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ </layer-list>
</item>
</selector>
diff --git a/core/res/res/layout/volume_adjust.xml b/core/res/res/layout/volume_adjust.xml
index c16a12c..1cf7ca9 100644
--- a/core/res/res/layout/volume_adjust.xml
+++ b/core/res/res/layout/volume_adjust.xml
@@ -15,23 +15,20 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="480dp"
+ android:layout_width="448dp"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/visible_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@android:drawable/dialog_full_holo_dark"
- android:orientation="horizontal"
- >
+ android:orientation="horizontal">
<LinearLayout
android:id="@+id/slider_group"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
- >
+ android:orientation="vertical">
<!-- Sliders go here -->
</LinearLayout>
@@ -43,8 +40,7 @@
android:scaleType="fitXY"
android:layout_gravity="top"
android:layout_marginTop="16dip"
- android:layout_marginBottom="16dip"
- />
+ android:layout_marginBottom="16dip" />
<ImageView
android:id="@+id/expand_button"
@@ -53,8 +49,7 @@
android:layout_gravity="top"
android:padding="16dip"
android:background="?attr/selectableItemBackground"
- android:src="@drawable/ic_sysbar_quicksettings"
- />
+ android:src="@drawable/ic_sysbar_quicksettings" />
</LinearLayout>
</FrameLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml
index 4a0fbaf..746cf91 100644
--- a/core/res/res/layout/volume_adjust_item.xml
+++ b/core/res/res/layout/volume_adjust_item.xml
@@ -26,16 +26,15 @@
android:id="@+id/stream_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="16dip"
+ android:paddingLeft="16dip"
android:background="?attr/selectableItemBackground"
- />
+ android:contentDescription="@null" />
<SeekBar
style="?android:attr/seekBarStyle"
android:id="@+id/seekbar"
- android:layout_width="300dp"
+ android:layout_width="252dp"
android:layout_height="wrap_content"
- android:layout_weight="1"
android:padding="16dip"
android:layout_marginEnd="16dip" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fbe066a..d5e78a5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1370,7 +1370,7 @@
</string-array>
<string-array name="config_notificationScorers">
- <item>com.android.internal.notification.DemoContactNotificationScorer</item>
+ <item>com.android.internal.notification.PeopleNotificationScorer</item>
</string-array>
<!-- Flag indicating that this device does not rotate and will always remain in its default
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 94123a2..6b2c788 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -201,7 +201,7 @@
<dimen name="textview_error_popup_default_width">240dip</dimen>
<!-- Volume panel y offset -->
- <dimen name="volume_panel_top">80dp</dimen>
+ <dimen name="volume_panel_top">16dp</dimen>
<!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
<dimen name="default_app_widget_padding_left">8dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4a121d1..6266393 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -830,6 +830,20 @@
user consent.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_retrieveWindowToken">retrieve window token</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_retrieveWindowToken">Allows an application to retrieve
+ the window token. Malicious apps may perfrom unauthorized interaction with
+ the application window impersonating the system.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_frameStats">retrieve frame statistics</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_frameStats">Allows an application to collect
+ frame statistics. Malicious apps may observe the frame statistics
+ of windows from other apps.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_filter_events">filter events</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_filter_events">Allows an application to register an input filter
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 2810c43..3773a49 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -44,9 +44,6 @@
* Documentation pending.
*/
public class TouchFeedbackDrawable extends LayerDrawable {
- private static final PorterDuffXfermode DST_ATOP = new PorterDuffXfermode(Mode.DST_ATOP);
- private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
-
/** The maximum number of ripples supported. */
private static final int MAX_RIPPLES = 10;
@@ -153,10 +150,8 @@
* @param tintMode A Porter-Duff blending mode
*/
public void setTintMode(Mode tintMode) {
- if (mState.mTintMode != tintMode) {
- mState.mTintMode = tintMode;
- invalidateSelf();
- }
+ mState.setTintMode(tintMode);
+ invalidateSelf();
}
@Override
@@ -187,8 +182,8 @@
}
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tintMode] == 0) {
- mState.mTintMode = Drawable.parseTintMode(
- a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP);
+ mState.setTintMode(Drawable.parseTintMode(
+ a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP));
}
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_pinned] == 0) {
@@ -238,8 +233,8 @@
}
if (a.hasValue(R.styleable.TouchFeedbackDrawable_tintMode)) {
- mState.mTintMode = Drawable.parseTintMode(
- a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP);
+ mState.setTintMode(Drawable.parseTintMode(
+ a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP));
}
if (a.hasValue(R.styleable.TouchFeedbackDrawable_pinned)) {
@@ -382,8 +377,9 @@
// If we have ripples and content, we need a masking layer. This will
// merge DST_ATOP onto (effectively under) the ripple layer.
if (drewRipples && !projected && rippleRestoreCount >= 0) {
+ final PorterDuffXfermode xfermode = mState.getTintXfermode();
canvas.saveLayer(bounds.left, bounds.top,
- bounds.right, bounds.bottom, getMaskingPaint(DST_ATOP), 0);
+ bounds.right, bounds.bottom, getMaskingPaint(xfermode), 0);
}
Drawable mask = null;
@@ -401,7 +397,7 @@
if (mask != null && drewRipples) {
// TODO: This will also mask the lower layer, which is bad.
canvas.saveLayer(bounds.left, bounds.top, bounds.right,
- bounds.bottom, getMaskingPaint(DST_IN), 0);
+ bounds.bottom, getMaskingPaint(mState.mTintXfermode), 0);
mask.draw(canvas);
}
@@ -459,7 +455,7 @@
static class TouchFeedbackState extends LayerState {
int[] mTouchThemeAttrs;
ColorStateList mTint;
- Mode mTintMode;
+ PorterDuffXfermode mTintXfermode;
boolean mPinned;
public TouchFeedbackState(
@@ -469,10 +465,19 @@
if (orig != null) {
mTouchThemeAttrs = orig.mTouchThemeAttrs;
mTint = orig.mTint;
- mTintMode = orig.mTintMode;
+ mTintXfermode = orig.mTintXfermode;
mPinned = orig.mPinned;
}
}
+
+ public void setTintMode(Mode mode) {
+ final Mode invertedMode = TouchFeedbackState.invertPorterDuffMode(mode);
+ mTintXfermode = new PorterDuffXfermode(invertedMode);
+ }
+
+ public PorterDuffXfermode getTintXfermode() {
+ return mTintXfermode;
+ }
@Override
public boolean canApplyTheme() {
@@ -493,6 +498,33 @@
public Drawable newDrawable(Resources res, Theme theme) {
return new TouchFeedbackDrawable(this, res, theme);
}
+
+ /**
+ * Inverts SRC and DST in PorterDuff blending modes.
+ */
+ private static Mode invertPorterDuffMode(Mode src) {
+ switch (src) {
+ case SRC_ATOP:
+ return Mode.DST_ATOP;
+ case SRC_IN:
+ return Mode.DST_IN;
+ case SRC_OUT:
+ return Mode.DST_OUT;
+ case SRC_OVER:
+ return Mode.DST_OVER;
+ case DST_ATOP:
+ return Mode.SRC_ATOP;
+ case DST_IN:
+ return Mode.SRC_IN;
+ case DST_OUT:
+ return Mode.SRC_OUT;
+ case DST_OVER:
+ return Mode.SRC_OVER;
+ default:
+ // Everything else is agnostic to SRC versus DST.
+ return src;
+ }
+ }
}
private TouchFeedbackDrawable(TouchFeedbackState state, Resources res, Theme theme) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6c0b722..3e68574 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -17,8 +17,8 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
@@ -47,6 +47,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+
/**
* This lets you create a drawable based on an XML vector graphic
* It can be defined in an XML file with the <code><vector></code> element.
@@ -172,7 +173,8 @@
private static final int DEFAULT_DURATION = 1000;
private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
- private VectorDrawableState mVectorState;
+ private final VectorDrawableState mVectorState;
+
private int mAlpha = 0xFF;
public VectorDrawable() {
@@ -282,14 +284,17 @@
@Override
protected boolean onStateChange(int[] state) {
+ super.onStateChange(state);
+
mVectorState.mVAnimatedPath.setState(state);
- int direction = mVectorState.mVAnimatedPath.getTrigger(state);
- if (direction>0) {
+
+ final int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+ if (direction > 0) {
animateForward();
- } else if (direction<0) {
+ } else if (direction < 0) {
animateBackward();
}
- super.onStateChange(state);
+
invalidateSelf();
return true;
}
@@ -310,7 +315,11 @@
@Override
public void draw(Canvas canvas) {
- mVectorState.mVAnimatedPath.draw(canvas);
+ final int saveCount = canvas.save();
+ final Rect bounds = getBounds();
+ canvas.translate(bounds.left, bounds.top);
+ mVectorState.mVAnimatedPath.draw(canvas, bounds.width(), bounds.height());
+ canvas.restoreToCount(saveCount);
}
@Override
@@ -327,10 +336,6 @@
// TODO: support color filter
}
- /**
- * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
- * value of TRANSLUCENT.
- */
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
@@ -364,38 +369,14 @@
invalidateSelf();
}
- /**
- * Sets the intrinsic (default) width for this shape.
- *
- * @param width the intrinsic width (in pixels)
- */
- public void setIntrinsicWidth(int width) {
- if (mVectorState.mIntrinsicWidth != width) {
- mVectorState.mIntrinsicWidth = width;
- invalidateSelf();
- }
- }
-
- /**
- * Sets the intrinsic (default) height for this shape.
- *
- * @param height the intrinsic height (in pixels)
- */
- public void setIntrinsicHeight(int height) {
- if (mVectorState.mIntrinsicHeight != height) {
- mVectorState.mIntrinsicHeight = height;
- invalidateSelf();
- }
- }
-
@Override
public int getIntrinsicWidth() {
- return mVectorState.mIntrinsicWidth;
+ return (int) mVectorState.mVAnimatedPath.mBaseWidth;
}
@Override
public int getIntrinsicHeight() {
- return mVectorState.mIntrinsicHeight;
+ return (int) mVectorState.mVAnimatedPath.mBaseHeight;
}
@Override
@@ -408,25 +389,6 @@
}
}
- /** @hide */
- public static VectorDrawable create(Resources resources, int rid) {
- try {
- VectorDrawable drawable = new VectorDrawable();
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
- XmlPullParser xpp = resources.getXml(rid);
- AttributeSet attrs = Xml.asAttributeSet(xpp);
- drawable.inflate(resources, xpp, attrs);
- drawable.setAnimationFraction(0);
- return drawable;
- } catch (XmlPullParserException e) {
- Log.e(LOGTAG, "parser error", e);
- } catch (IOException e) {
- Log.e(LOGTAG, "parser error", e);
- }
- return null;
- }
-
@Override
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
@@ -450,6 +412,27 @@
}
}
+ /** @hide */
+ public static VectorDrawable create(Resources resources, int rid) {
+ try {
+ final XmlPullParser xpp = resources.getXml(rid);
+ final AttributeSet attrs = Xml.asAttributeSet(xpp);
+ final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+
+ final VectorDrawable drawable = new VectorDrawable();
+ drawable.inflate(resources, xpp, attrs);
+ drawable.setAnimationFraction(0);
+
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
final VAnimatedPath animatedPath = new VAnimatedPath();
@@ -543,9 +526,6 @@
private void setAnimatedPath(VAnimatedPath animatedPath) {
mVectorState.mVAnimatedPath = animatedPath;
- setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
- setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
-
long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
if (duration == -1) { // if it set to infinite set to 1 hour
duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
@@ -575,18 +555,12 @@
ValueAnimator mBasicAnimator;
VAnimatedPath mVAnimatedPath;
Rect mPadding;
- int mIntrinsicHeight;
- int mIntrinsicWidth;
public VectorDrawableState(VectorDrawableState copy) {
if (copy != null) {
mChangingConfigurations = copy.mChangingConfigurations;
mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
mPadding = new Rect(copy.mPadding);
- mIntrinsicHeight = copy.mIntrinsicHeight;
- mIntrinsicWidth = copy.mIntrinsicWidth;
- } else {
- mVAnimatedPath = new VAnimatedPath();
}
}
@@ -612,17 +586,31 @@
}
private static class VAnimatedPath {
- private ArrayList<VAnimation> mCurrentAnimList = null;
+ private static final int [] TRIGGER_MAP = {
+ 0,
+ R.attr.state_pressed,
+ R.attr.state_focused,
+ R.attr.state_hovered,
+ R.attr.state_selected,
+ R.attr.state_checkable,
+ R.attr.state_checked,
+ R.attr.state_activated,
+ R.attr.state_focused
+ };
+
+ private final Path mPath = new Path();
+ private final Path mRenderPath = new Path();
+ private final Matrix mMatrix = new Matrix();
+
+ private ArrayList<VAnimation> mCurrentAnimList;
private VPath[] mCurrentPaths;
- private float mAnimationValue = 0; // value goes from 0 to 1
- private Paint mStrokePaint = null;
- private Paint mFillPaint = null;
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
private PathMeasure mPathMeasure;
- private Path mPath = new Path();
- private Path mRenderPath = new Path();
- private Matrix mMatrix = new Matrix();
- private long mTotalDuration;
+
private int[] mCurrentState = new int[0];
+ private float mAnimationValue;
+ private long mTotalDuration;
private int mTrigger;
private boolean mTriggerState;
@@ -634,11 +622,9 @@
float mViewportHeight;
public VAnimatedPath() {
- setup();
}
public VAnimatedPath(VAnimatedPath copy) {
- setup();
mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
mGroupList.addAll(copy.mGroupList);
if (copy.mCurrentPaths != null) {
@@ -703,28 +689,7 @@
}
public void setTrigger(int trigger){
- final int [] lut = {
- 0,
- R.attr.state_pressed,
- R.attr.state_focused,
- R.attr.state_hovered,
- R.attr.state_selected,
- R.attr.state_checkable,
- R.attr.state_checked,
- R.attr.state_activated,
- R.attr.state_focused
- };
-
- mTrigger = lut[trigger];
- }
-
- private void setup(){
- mStrokePaint = new Paint();
- mStrokePaint.setStyle(Paint.Style.STROKE);
- mStrokePaint.setAntiAlias(true);
- mFillPaint = new Paint();
- mFillPaint.setStyle(Paint.Style.FILL);
- mFillPaint.setAntiAlias(true);
+ mTrigger = VAnimatedPath.getStateForTrigger(trigger);
}
public long getTotalAnimationDuration() {
@@ -780,16 +745,12 @@
}
}
- public void draw(Canvas canvas) {
+ public void draw(Canvas canvas, int w, int h) {
if (mCurrentPaths == null) {
Log.e(LOGTAG,"mCurrentPaths == null");
return;
}
- // TODO: This should probably use getBounds().
- final int w = canvas.getWidth();
- final int h = canvas.getHeight();
-
for (int i = 0; i < mCurrentPaths.length; i++) {
if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
drawPath(mCurrentPaths[i], canvas, w, h);
@@ -801,7 +762,7 @@
final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
vPath.toPath(mPath);
- Path path = mPath;
+ final Path path = mPath;
if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
@@ -839,24 +800,36 @@
}
if (vPath.mFillColor != 0) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
mFillPaint.setColor(vPath.mFillColor);
- int alpha = 0xFF & (vPath.mFillColor >> 24);
- mFillPaint.setAlpha(alpha);
canvas.drawPath(mRenderPath, mFillPaint);
}
if (vPath.mStrokeColor != 0) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
if (vPath.mStrokeLineJoin != null) {
- mStrokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
+ strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
}
+
if (vPath.mStrokeLineCap != null) {
- mStrokePaint.setStrokeCap(vPath.mStrokeLineCap);
+ strokePaint.setStrokeCap(vPath.mStrokeLineCap);
}
- mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
- mStrokePaint.setColor(vPath.mStrokeColor);
- mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
- mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
- canvas.drawPath(mRenderPath, mStrokePaint);
+
+ strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+ strokePaint.setColor(vPath.mStrokeColor);
+ strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, strokePaint);
}
}
@@ -926,7 +899,7 @@
private void parseViewport(Resources r, AttributeSet attrs)
throws XmlPullParserException {
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+ final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
if (mViewportWidth == 0 || mViewportHeight == 0) {
@@ -938,7 +911,7 @@
private void parseSize(Resources r, AttributeSet attrs)
throws XmlPullParserException {
- TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+ final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
if (mBaseWidth == 0 || mBaseHeight == 0) {
@@ -947,6 +920,10 @@
}
a.recycle();
}
+
+ private static final int getStateForTrigger(int trigger) {
+ return TRIGGER_MAP[trigger];
+ }
}
private static class VAnimation {
@@ -1324,8 +1301,8 @@
boolean mAnimated = false;
boolean mClip = false;
- Paint.Cap mStrokeLineCap = null;
- Paint.Join mStrokeLineJoin = null;
+ Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
+ Paint.Join mStrokeLineJoin = Paint.Join.MITER;
float mStrokeMiterlimit = 4;
private VNode[] mNode = null;
@@ -1775,32 +1752,29 @@
return returnPath;
}
- private static int rgbInterpolate(float t, int color1, int color2) {
- int ret;
- if (color1 == color2) {
- return color2;
- }
- if (color1 == 0) {
- return color2;
- }
- if (color2 == 0) {
- return color1;
+ private static int rgbInterpolate(float fraction, int startColor, int endColor) {
+ if (startColor == endColor) {
+ return startColor;
+ } else if (startColor == 0) {
+ return endColor;
+ } else if (endColor == 0) {
+ return startColor;
}
- float t1 = 1 - t;
- ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
- color1 >>= 8;
- color2 >>= 8;
+ final int startA = (startColor >> 24) & 0xff;
+ final int startR = (startColor >> 16) & 0xff;
+ final int startG = (startColor >> 8) & 0xff;
+ final int startB = startColor & 0xff;
- ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
- color1 >>= 8;
- color2 >>= 8;
- ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
- color1 >>= 8;
- color2 >>= 8;
- ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+ final int endA = (endColor >> 24) & 0xff;
+ final int endR = (endColor >> 16) & 0xff;
+ final int endG = (endColor >> 8) & 0xff;
+ final int endB = endColor & 0xff;
- return ret;
+ return ((startA + (int)(fraction * (endA - startA))) << 24) |
+ ((startR + (int)(fraction * (endR - startR))) << 16) |
+ ((startG + (int)(fraction * (endG - startG))) << 8) |
+ ((startB + (int)(fraction * (endB - startB))));
}
public boolean isVisible(int[] state) {
@@ -1852,27 +1826,25 @@
}
}
- private void nodeListToPath(VNode[] node, Path path) {
- float[] current = new float[4];
- for (int i = 0; i < node.length; i++) {
- addCommand(path, current, node[i].mType, node[i].mParams);
- }
- }
-
public static void createPath(VNode[] node, Path path) {
float[] current = new float[4];
+ char previousCommand = 'm';
for (int i = 0; i < node.length; i++) {
- addCommand(path, current, node[i].mType, node[i].mParams);
+ addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
+ previousCommand = node[i].mType;
}
}
- private static void addCommand(Path path, float[] current, char cmd, float[] val) {
+ private static void addCommand(Path path, float[] current,
+ char previousCmd, char cmd, float[] val) {
int incr = 2;
float currentX = current[0];
float currentY = current[1];
float ctrlPointX = current[2];
float ctrlPointY = current[3];
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
switch (cmd) {
case 'z':
@@ -1952,12 +1924,8 @@
currentY = val[k + 0];
break;
case 'c': // curveto - Draws a cubic Bézier curve (relative)
- path.rCubicTo(val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3],
- val[k + 4],
- val[k + 5]);
+ path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
ctrlPointX = currentX + val[k + 2];
ctrlPointY = currentY + val[k + 3];
@@ -1966,20 +1934,22 @@
break;
case 'C': // curveto - Draws a cubic Bézier curve
- path.cubicTo(val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3],
- val[k + 4],
- val[k + 5]);
+ path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
currentX = val[k + 4];
currentY = val[k + 5];
ctrlPointX = val[k + 2];
ctrlPointY = val[k + 3];
-
break;
case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
- path.rCubicTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
val[k + 0], val[k + 1],
val[k + 2], val[k + 3]);
@@ -1989,47 +1959,63 @@
currentY += val[k + 3];
break;
case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
- path.cubicTo(2 * currentX - ctrlPointX,
- 2 * currentY - ctrlPointY,
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3]);
- currentX = val[k + 2];
- currentY = val[k + 3];
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
ctrlPointX = val[k + 0];
ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
break;
case 'q': // Draws a quadratic Bézier (relative)
path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
currentX += val[k + 2];
currentY += val[k + 3];
- ctrlPointX = val[k + 0];
- ctrlPointY = val[k + 1];
break;
case 'Q': // Draws a quadratic Bézier
path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- currentX = val[k + 2];
- currentY = val[k + 3];
ctrlPointX = val[k + 0];
ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
break;
case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
- path.rQuadTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
val[k + 0], val[k + 1]);
- ctrlPointX = ctrlPointX + currentX;
- ctrlPointY = ctrlPointY + currentY;
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
currentX += val[k + 0];
currentY += val[k + 1];
-
break;
case 'T': // Draws a quadratic Bézier curve (reflective control point)
- path.quadTo(currentX * 2 - ctrlPointX, currentY * 2 - ctrlPointY,
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
val[k + 0], val[k + 1]);
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
currentX = val[k + 0];
- currentY = val[k + 1]; // TODO: Check this logic
- ctrlPointX = -(val[k + 0] - currentX);
- ctrlPointY = -(val[k + 1] - currentY);
+ currentY = val[k + 1];
break;
case 'a': // Draws an elliptical arc
// (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
@@ -2047,7 +2033,6 @@
currentY += val[k + 6];
ctrlPointX = currentX;
ctrlPointY = currentY;
-
break;
case 'A': // Draws an elliptical arc
drawArc(path,
@@ -2066,6 +2051,7 @@
ctrlPointY = currentY;
break;
}
+ previousCmd = cmd;
}
current[0] = currentX;
current[1] = currentY;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index c64c169..8b23955 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -41,6 +41,7 @@
DeferredLayerUpdater::~DeferredLayerUpdater() {
SkSafeUnref(mColorFilter);
+ setTransform(0);
if (mLayer) {
mCaches.resourceCache.decrementRefcount(mLayer);
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c5122e2..3638184 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -313,14 +313,11 @@
, mDirtyRegionsEnabled(false)
, mOpaque(!translucent)
, mCanvas(0)
- , mHaveNewSurface(false)
- , mInvokeFunctorsPending(false)
- , mInvokeFunctorsTask(this) {
+ , mHaveNewSurface(false) {
mGlobalContext = GlobalContext::get();
}
CanvasContext::~CanvasContext() {
- removeFunctorsTask();
destroyCanvas();
}
@@ -387,6 +384,7 @@
void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
bool* hasFunctors) {
+ LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
mGlobalContext->makeCurrent(mEglSurface);
for (size_t i = 0; i < layerUpdaters->size(); i++) {
DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
@@ -431,55 +429,17 @@
}
}
-void InvokeFunctorsTask::run() {
- mContext->invokeFunctors();
-}
-
-void CanvasContext::attachFunctor(Functor* functor) {
- if (!mCanvas) return;
-
- mCanvas->attachFunctor(functor);
- removeFunctorsTask();
- queueFunctorsTask(0);
-}
-
-void CanvasContext::detachFunctor(Functor* functor) {
- if (!mCanvas) return;
-
- mCanvas->detachFunctor(functor);
-}
-
void CanvasContext::invokeFunctor(Functor* functor) {
+ ATRACE_CALL();
DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
if (mGlobalContext->hasContext()) {
requireGlContext();
mode = DrawGlInfo::kModeProcess;
}
- (*functor)(mode, NULL);
-}
-
-void CanvasContext::invokeFunctors() {
- mInvokeFunctorsPending = false;
-
- if (!mCanvas) return;
-
- requireSurface();
- Rect dirty;
- mCanvas->invokeFunctors(dirty);
-}
-
-void CanvasContext::removeFunctorsTask() {
- if (!mInvokeFunctorsPending) return;
-
- mInvokeFunctorsPending = false;
- mRenderThread.remove(&mInvokeFunctorsTask);
-}
-
-void CanvasContext::queueFunctorsTask(int delayMs) {
- if (mInvokeFunctorsPending) return;
-
- mInvokeFunctorsPending = true;
- mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
+ // TODO: Remove the dummy info in the future
+ DrawGlInfo dummyInfo;
+ memset(&dummyInfo, 0, sizeof(DrawGlInfo));
+ (*functor)(mode, &dummyInfo);
}
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index a24162e..dcb5957 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -43,17 +43,6 @@
class CanvasContext;
class RenderThread;
-class InvokeFunctorsTask : public RenderTask {
-public:
- InvokeFunctorsTask(CanvasContext* context)
- : mContext(context) {}
-
- virtual void run();
-
-private:
- CanvasContext* mContext;
-};
-
// This per-renderer class manages the bridge between the global EGL context
// and the render surface.
class CanvasContext {
@@ -71,8 +60,6 @@
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
- void attachFunctor(Functor* functor);
- void detachFunctor(Functor* functor);
void invokeFunctor(Functor* functor);
void runWithGlContext(RenderTask* task);
@@ -85,11 +72,6 @@
void swapBuffers();
void requireSurface();
- friend class InvokeFunctorsTask;
- void invokeFunctors();
- void removeFunctorsTask();
- void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
-
void requireGlContext();
GlobalContext* mGlobalContext;
@@ -100,10 +82,6 @@
bool mOpaque;
OpenGLRenderer* mCanvas;
bool mHaveNewSurface;
-
- bool mInvokeFunctorsPending;
- InvokeFunctorsTask mInvokeFunctorsTask;
-
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 372d0d0..cf6c8db 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,7 +30,7 @@
namespace uirenderer {
namespace renderthread {
-DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
+DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
}
DrawFrameTask::~DrawFrameTask() {
@@ -69,23 +69,14 @@
LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
- postAndWait(renderThread, MODE_FULL);
+ postAndWait(renderThread);
// Reset the single-frame data
mDirty.setEmpty();
mRenderNode = 0;
}
-void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
- LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
-
- postAndWait(renderThread, MODE_STATE_ONLY);
-}
-
-void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
- LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
-
- mTaskMode = mode;
+void DrawFrameTask::postAndWait(RenderThread* renderThread) {
AutoMutex _lock(mLock);
renderThread->queue(this);
mSignal.wait(mLock);
@@ -97,11 +88,6 @@
// canUnblockUiThread is temporary until WebView has a solution for syncing frame state
bool canUnblockUiThread = syncFrameState();
- if (mTaskMode == MODE_STATE_ONLY) {
- unblockUiThread();
- return;
- }
-
// Grab a copy of everything we need
Rect dirtyCopy(mDirty);
sp<RenderNode> renderNode = mRenderNode;
@@ -125,12 +111,9 @@
bool hasFunctors = false;
mContext->processLayerUpdates(&mLayers, &hasFunctors);
- // If we don't have an mRenderNode this is a state flush only
- if (mRenderNode.get()) {
- TreeInfo info = {0};
- mRenderNode->prepareTree(info);
- hasFunctors |= info.hasFunctors;
- }
+ TreeInfo info = {0};
+ mRenderNode->prepareTree(info);
+ hasFunctors |= info.hasFunctors;
return !hasFunctors;
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index a512408..055d4cf 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -56,18 +56,11 @@
void setRenderNode(RenderNode* renderNode);
void setDirty(int left, int top, int right, int bottom);
void drawFrame(RenderThread* renderThread);
- void flushStateChanges(RenderThread* renderThread);
virtual void run();
private:
- enum TaskMode {
- MODE_INVALID,
- MODE_FULL,
- MODE_STATE_ONLY,
- };
-
- void postAndWait(RenderThread* renderThread, TaskMode mode);
+ void postAndWait(RenderThread* renderThread);
bool syncFrameState();
void unblockUiThread();
static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
@@ -80,7 +73,6 @@
/*********************************************
* Single frame data
*********************************************/
- TaskMode mTaskMode;
sp<RenderNode> mRenderNode;
Rect mDirty;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 49b9aca..b233ae9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -75,9 +75,6 @@
void RenderProxy::destroyContext() {
if (mContext) {
- // Flush any pending changes to ensure all garbage is destroyed
- mDrawFrameTask.flushStateChanges(&mRenderThread);
-
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
@@ -149,45 +146,18 @@
}
void RenderProxy::destroyCanvas() {
- // If the canvas is being destroyed we won't be drawing again anytime soon
- // So flush any pending state changes to allow for resource cleanup.
- mDrawFrameTask.flushStateChanges(&mRenderThread);
-
SETUP_TASK(destroyCanvas);
args->context = mContext;
post(task);
}
-CREATE_BRIDGE2(attachFunctor, CanvasContext* context, Functor* functor) {
- args->context->attachFunctor(args->functor);
- return NULL;
-}
-
-void RenderProxy::attachFunctor(Functor* functor) {
- SETUP_TASK(attachFunctor);
- args->context = mContext;
- args->functor = functor;
- post(task);
-}
-
-CREATE_BRIDGE2(detachFunctor, CanvasContext* context, Functor* functor) {
- args->context->detachFunctor(args->functor);
- return NULL;
-}
-
-void RenderProxy::detachFunctor(Functor* functor) {
- SETUP_TASK(detachFunctor);
- args->context = mContext;
- args->functor = functor;
- post(task);
-}
-
CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
args->context->invokeFunctor(args->functor);
return NULL;
}
void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
+ ATRACE_CALL();
SETUP_TASK(invokeFunctor);
args->context = mContext;
args->functor = functor;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 1ad3c85..3eb8ed8 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -67,8 +67,6 @@
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
ANDROID_API void destroyCanvas();
- ANDROID_API void attachFunctor(Functor* functor);
- ANDROID_API void detachFunctor(Functor* functor);
ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task);
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 664c707..214306c 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -1064,10 +1064,8 @@
private boolean mHasRemotePlayback;
/**
- * The stack of remote control event receivers.
- * Code sections and methods that modify the remote control event receiver stack are
- * synchronized on mPRStack, but also BEFORE on mFocusLock as any change in either
- * stack, audio focus or RC, can lead to a change in the remote control display
+ * The stack of remote control event receivers.
+ * All read and write operations on mPRStack are synchronized.
*/
private final Stack<PlayerRecord> mPRStack = new Stack<PlayerRecord>();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index d157478..89886ef 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -23,6 +23,7 @@
import android.hardware.IProCameraCallbacks;
import android.hardware.IProCameraUser;
import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
@@ -151,21 +152,50 @@
static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
- @Override
- public void onCameraError(int errorCode) {
- }
-
- @Override
- public void onCameraIdle() {
- }
-
- @Override
- public void onCaptureStarted(int requestId, long timestamp) {
- }
-
- @Override
- public void onResultReceived(int frameId, CameraMetadataNative result)
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
+ * android.hardware.camera2.CaptureResultExtras)
+ */
+ public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
+ * android.hardware.camera2.CaptureResultExtras, long)
+ */
+ public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
+ * android.hardware.camera2.impl.CameraMetadataNative,
+ * android.hardware.camera2.CaptureResultExtras)
+ */
+ public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
+ */
+ public void onCameraIdle() throws RemoteException {
+ // TODO Auto-generated method stub
+
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 5f3ba74..74ce997 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -21,6 +21,7 @@
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
@@ -84,20 +85,50 @@
public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
- @Override
- public void onCameraError(int errorCode) {
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
+ * android.hardware.camera2.CaptureResultExtras)
+ */
+ public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
}
- @Override
- public void onCameraIdle() {
+ /*
+ * (non-Javadoc)
+ * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
+ */
+ public void onCameraIdle() throws RemoteException {
+ // TODO Auto-generated method stub
+
}
- @Override
- public void onCaptureStarted(int requestId, long timestamp) {
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
+ * android.hardware.camera2.CaptureResultExtras, long)
+ */
+ public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
}
- @Override
- public void onResultReceived(int frameId, CameraMetadataNative result) {
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
+ * android.hardware.camera2.impl.CameraMetadataNative,
+ * android.hardware.camera2.CaptureResultExtras)
+ */
+ public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
}
}
@@ -139,7 +170,7 @@
}
private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
- int requestId = mCameraUser.submitRequest(request, streaming);
+ int requestId = mCameraUser.submitRequest(request, streaming, null);
assertTrue(
"Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
requestId >= 0);
@@ -252,13 +283,13 @@
CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
CaptureRequest request1 = builder.build();
- int status = mCameraUser.submitRequest(request1, /* streaming */false);
+ int status = mCameraUser.submitRequest(request1, /* streaming */false, null);
assertEquals("Expected submitRequest to return BAD_VALUE " +
"since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
builder.addTarget(mSurface);
CaptureRequest request2 = builder.build();
- status = mCameraUser.submitRequest(request2, /* streaming */false);
+ status = mCameraUser.submitRequest(request2, /* streaming */false, null);
assertEquals("Expected submitRequest to return BAD_VALUE since " +
"the target surface wasn't registered with createStream.",
CameraBinderTestUtils.BAD_VALUE, status);
@@ -292,15 +323,15 @@
assertNotSame("Request IDs should be unique for multiple requests", requestId1,
requestIdStreaming);
- int status = mCameraUser.cancelRequest(-1);
+ int status = mCameraUser.cancelRequest(-1, null);
assertEquals("Invalid request IDs should not be cancellable",
CameraBinderTestUtils.BAD_VALUE, status);
- status = mCameraUser.cancelRequest(requestId1);
+ status = mCameraUser.cancelRequest(requestId1, null);
assertEquals("Non-streaming request IDs should not be cancellable",
CameraBinderTestUtils.BAD_VALUE, status);
- status = mCameraUser.cancelRequest(requestIdStreaming);
+ status = mCameraUser.cancelRequest(requestIdStreaming, null);
assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
status);
@@ -339,7 +370,7 @@
CameraBinderTestUtils.INVALID_OPERATION, status);
// Test good case, waitUntilIdle when there is no active repeating request
- status = mCameraUser.cancelRequest(requestIdStreaming);
+ status = mCameraUser.cancelRequest(requestIdStreaming, null);
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
status = mCameraUser.waitUntilIdle();
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
@@ -351,16 +382,14 @@
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Test both single request and streaming request.
- int requestId1 = submitCameraRequest(request, /* streaming */false);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived(
- eq(requestId1),
- argThat(matcher));
+ argThat(matcher),
+ any(CaptureResultExtras.class));
- int streamingId = submitCameraRequest(request, /* streaming */true);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
.onResultReceived(
- eq(streamingId),
- argThat(matcher));
+ argThat(matcher),
+ any(CaptureResultExtras.class));
}
@SmallTest
@@ -372,13 +401,13 @@
// Test both single request and streaming request.
int requestId1 = submitCameraRequest(request, /* streaming */false);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
- eq(requestId1),
+ any(CaptureResultExtras.class),
anyLong());
int streamingId = submitCameraRequest(request, /* streaming */true);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
.onCaptureStarted(
- eq(streamingId),
+ any(CaptureResultExtras.class),
timestamps.capture());
long timestamp = 0; // All timestamps should be larger than 0.
@@ -401,7 +430,7 @@
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Cancel and make sure we eventually quiesce
- status = mCameraUser.cancelRequest(streamingId);
+ status = mCameraUser.cancelRequest(streamingId, null);
verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onCameraIdle();
@@ -422,14 +451,14 @@
int status;
// Initial flush should work
- status = mCameraUser.flush();
+ status = mCameraUser.flush(null);
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
// Then set up a stream
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Flush should still be a no-op, really
- status = mCameraUser.flush();
+ status = mCameraUser.flush(null);
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
// Submit a few capture requests
@@ -440,7 +469,7 @@
int requestId5 = submitCameraRequest(request, /* streaming */false);
// Then flush and wait for idle
- status = mCameraUser.flush();
+ status = mCameraUser.flush(null);
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onCameraIdle();
@@ -452,7 +481,7 @@
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Then flush and wait for the idle callback
- status = mCameraUser.flush();
+ status = mCameraUser.flush(null);
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onCameraIdle();
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 19286c8..e1c17cb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -87,6 +87,8 @@
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.BLUETOOTH_STACK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
+ <uses-permission android:name="android.permission.RENDER_STATS" />
<application android:label="@string/app_label">
<provider
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index 46d2a16..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
deleted file mode 100644
index 704b4ec..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index d56efb5..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
new file mode 100644
index 0000000..b7fe5ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_qs_brightness_auto_off_alpha"
+ android:tint="?android:attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml
new file mode 100644
index 0000000..e17b533
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_qs_brightness_auto_on_alpha"
+ android:tint="?android:attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index a6f4e9b..46fbaff 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -13,27 +13,26 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
style="@style/BrightnessDialogContainer">
<ImageView
android:id="@+id/brightness_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingEnd="10dp"
android:src="@drawable/ic_qs_brightness_auto_off"
- />
+ android:contentDescription="@null" />
+
<com.android.systemui.settings.ToggleSlider
android:id="@+id/brightness_slider"
android:layout_width="0dp"
android:layout_height="40dp"
- android:layout_weight="1"
- android:layout_marginEnd="2dp"
android:layout_gravity="center_vertical"
- systemui:text="@string/status_bar_settings_auto_brightness_label"
- />
+ android:layout_marginEnd="2dp"
+ android:layout_weight="1"
+ systemui:text="@string/status_bar_settings_auto_brightness_label" />
+
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index eb09335..aa4e69a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -17,10 +17,12 @@
package com.android.systemui.recent;
import android.app.ActivityManager;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -30,7 +32,9 @@
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -162,9 +166,14 @@
intent.setComponent(origActivity);
}
final PackageManager pm = mContext.getPackageManager();
+ final IPackageManager ipm = AppGlobals.getPackageManager();
intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
| Intent.FLAG_ACTIVITY_NEW_TASK);
- final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
+ ResolveInfo resolveInfo = null;
+ try {
+ resolveInfo = ipm.resolveIntent(intent, null, 0, userId);
+ } catch (RemoteException re) {
+ }
if (resolveInfo != null) {
final ActivityInfo info = resolveInfo.activityInfo;
final String title = info.loadLabel(pm).toString();
@@ -192,7 +201,11 @@
final PackageManager pm = mContext.getPackageManager();
Bitmap thumbnail = am.getTaskTopThumbnail(td.persistentTaskId);
Drawable icon = getFullResIcon(td.resolveInfo, pm);
-
+ if (td.userId != UserHandle.myUserId()) {
+ // Need to badge the icon
+ final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ icon = um.getBadgedDrawableForUser(icon, new UserHandle(td.userId));
+ }
if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
+ td + ": " + thumbnail);
synchronized (td) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 3c34e90..fd0f6d1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -192,8 +192,9 @@
" forceLoad: " + forceLoadTask);
// Load the application icon
if (loadIcon == null || forceLoadTask) {
- ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
- Drawable icon = ssp.getActivityIcon(info);
+ ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
+ t.userId);
+ Drawable icon = ssp.getActivityIcon(info, t.userId);
if (!mCancelled) {
if (icon != null) {
Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -411,7 +412,7 @@
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
+ ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
t.activityLabel.toString());
Bitmap activityIcon = t.activityIcon;
@@ -437,7 +438,7 @@
}
}
if (task.applicationIcon == null) {
- task.applicationIcon = ssp.getActivityIcon(info);
+ task.applicationIcon = ssp.getActivityIcon(info, task.userId);
if (task.applicationIcon != null) {
mApplicationIconCache.put(task.key, task.applicationIcon);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 505238d..7f0d9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -18,14 +18,19 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +43,8 @@
public class SystemServicesProxy {
ActivityManager mAm;
PackageManager mPm;
+ IPackageManager mIpm;
+ UserManager mUm;
String mPackage;
Bitmap mDummyIcon;
@@ -46,6 +53,8 @@
public SystemServicesProxy(Context context) {
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mPm = context.getPackageManager();
+ mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mIpm = AppGlobals.getPackageManager();
mPackage = context.getPackageName();
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
@@ -142,14 +151,19 @@
mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
}
- /** Returns the activity info for a given component name */
- public ActivityInfo getActivityInfo(ComponentName cn) {
- if (mPm == null) return null;
+ /**
+ * Returns the activity info for a given component name.
+ *
+ * @param ComponentName The component name of the activity.
+ * @param userId The userId of the user that this is for.
+ */
+ public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
+ if (mIpm == null) return null;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
try {
- return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
+ return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
+ } catch (RemoteException e) {
e.printStackTrace();
return null;
}
@@ -167,15 +181,22 @@
return info.loadLabel(mPm).toString();
}
- /** Returns the activity icon */
- public Drawable getActivityIcon(ActivityInfo info) {
- if (mPm == null) return null;
+ /**
+ * Returns the activity icon for the ActivityInfo for a user, badging if
+ * necessary.
+ */
+ public Drawable getActivityIcon(ActivityInfo info, int userId) {
+ if (mPm == null || mUm == null) return null;
// If we are mocking, then return a mock label
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
return new ColorDrawable(0xFF666666);
}
- return info.loadIcon(mPm);
+ Drawable icon = info.loadIcon(mPm);
+ if (userId != UserHandle.myUserId()) {
+ icon = mUm.getBadgedDrawableForUser(icon, new UserHandle(userId));
+ }
+ return icon;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 189f358..ff062f6c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -37,25 +37,33 @@
public static class TaskKey {
public final int id;
public final Intent baseIntent;
+ public final int userId;
- public TaskKey(int id, Intent intent) {
+ public TaskKey(int id, Intent intent, int userId) {
this.id = id;
this.baseIntent = intent;
+ this.userId = userId;
}
@Override
public boolean equals(Object o) {
- return hashCode() == o.hashCode();
+ if (!(o instanceof TaskKey)) {
+ return false;
+ }
+ return id == ((TaskKey) o).id
+ && userId == ((TaskKey) o).userId;
}
@Override
public int hashCode() {
- return id;
+ return (id << 5) + userId;
}
@Override
public String toString() {
- return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
+ return "Task.Key: " + id + ", "
+ + "u" + userId + ", "
+ + baseIntent.getComponent().getPackageName();
}
}
@@ -75,7 +83,7 @@
public Task(int id, boolean isActive, Intent intent, String activityTitle,
Bitmap activityIcon, int userId) {
- this.key = new TaskKey(id, intent);
+ this.key = new TaskKey(id, intent, userId);
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
this.isActive = isActive;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f1299fe..2f135ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -138,7 +138,8 @@
protected IDreamManager mDreamManager;
PowerManager mPowerManager;
- protected int mRowHeight;
+ protected int mRowMinHeight;
+ protected int mRowMaxHeight;
// public mode, private notifications, etc
private boolean mLockscreenPublicMode = false;
@@ -880,7 +881,7 @@
}
}
entry.row = row;
- entry.row.setRowHeight(mRowHeight);
+ entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
entry.content = content;
entry.expanded = contentViewLocal;
entry.expandedPublic = publicViewLocal;
@@ -1055,17 +1056,19 @@
}
protected void updateExpansionStates() {
+
+ // TODO: Handle user expansion better
int N = mNotificationData.size();
for (int i = 0; i < N; i++) {
NotificationData.Entry entry = mNotificationData.get(i);
if (!entry.row.isUserLocked()) {
if (i == (N-1)) {
if (DEBUG) Log.d(TAG, "expanding top notification at " + i);
- entry.row.setExpanded(true);
+ entry.row.setSystemExpanded(true);
} else {
if (!entry.row.isUserExpanded()) {
if (DEBUG) Log.d(TAG, "collapsing notification at " + i);
- entry.row.setExpanded(false);
+ entry.row.setSystemExpanded(false);
} else {
if (DEBUG) Log.d(TAG, "ignoring user-modified notification at " + i);
}
@@ -1218,13 +1221,14 @@
if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
- final boolean wasExpanded = oldEntry.row.isUserExpanded();
removeNotificationViews(key);
addNotificationViews(key, notification); // will also replace the heads up
- if (wasExpanded) {
- final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
- newEntry.row.setExpanded(true);
- newEntry.row.setUserExpanded(true);
+ final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
+ final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
+ if (userChangedExpansion) {
+ boolean userExpanded = oldEntry.row.isUserExpanded();
+ newEntry.row.applyExpansionToLayout(userExpanded);
+ newEntry.row.setUserExpanded(userExpanded);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b3d8688..2daf619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -22,30 +22,49 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import com.android.internal.widget.SizeAdaptiveLayout;
import com.android.systemui.R;
public class ExpandableNotificationRow extends FrameLayout {
- private int mRowHeight;
+ private int mRowMinHeight;
+ private int mRowMaxHeight;
- /** does this row contain layouts that can adapt to row expansion */
+ /** Does this row contain layouts that can adapt to row expansion */
private boolean mExpandable;
- /** has the user manually expanded this row */
+ /** Has the user actively changed the expansion state of this row */
+ private boolean mHasUserChangedExpansion;
+ /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
private boolean mUserExpanded;
- /** is the user touching this row */
+ /** Is the user touching this row */
private boolean mUserLocked;
- /** are we showing the "public" version */
+ /** Are we showing the "public" version */
private boolean mShowingPublic;
+ /**
+ * Is this notification expanded by the system. The expansion state can be overridden by the
+ * user expansion.
+ */
+ private boolean mIsSystemExpanded;
+ private SizeAdaptiveLayout mPublicLayout;
+ private SizeAdaptiveLayout mPrivateLayout;
+ private int mMaxExpandHeight;
+ private boolean mMaxHeightNeedsUpdate;
+
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public int getRowHeight() {
- return mRowHeight;
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic);
+ mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded);
}
- public void setRowHeight(int rowHeight) {
- this.mRowHeight = rowHeight;
+ public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
+ mRowMinHeight = rowMinHeight;
+ mRowMaxHeight = rowMaxHeight;
+ mMaxHeightNeedsUpdate = true;
}
public boolean isExpandable() {
@@ -56,11 +75,24 @@
mExpandable = expandable;
}
+ /**
+ * @return whether the user has changed the expansion state
+ */
+ public boolean hasUserChangedExpansion() {
+ return mHasUserChangedExpansion;
+ }
+
public boolean isUserExpanded() {
return mUserExpanded;
}
+ /**
+ * Set this notification to be expanded by the user
+ *
+ * @param userExpanded whether the user wants this notification to be expanded
+ */
public void setUserExpanded(boolean userExpanded) {
+ mHasUserChangedExpansion = true;
mUserExpanded = userExpanded;
}
@@ -72,25 +104,102 @@
mUserLocked = userLocked;
}
- public void setExpanded(boolean expand) {
+ /**
+ * @return has the system set this notification to be expanded
+ */
+ public boolean isSystemExpanded() {
+ return mIsSystemExpanded;
+ }
+
+ /**
+ * Set this notification to be expanded by the system.
+ *
+ * @param expand whether the system wants this notification to be expanded.
+ */
+ public void setSystemExpanded(boolean expand) {
+ mIsSystemExpanded = expand;
+ applyExpansionToLayout(expand);
+ }
+
+ /**
+ * Apply an expansion state to the layout.
+ *
+ * @param expand should the layout be in the expanded state
+ */
+ public void applyExpansionToLayout(boolean expand) {
ViewGroup.LayoutParams lp = getLayoutParams();
if (expand && mExpandable) {
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
- lp.height = mRowHeight;
+ lp.height = mRowMinHeight;
}
setLayoutParams(lp);
}
+ /**
+ * If {@link #isExpanded()} then this is the greatest possible height this view can
+ * get and otherwise it is {@link #mRowMinHeight}.
+ *
+ * @return the maximum allowed expansion height of this view.
+ */
+ public int getMaximumAllowedExpandHeight() {
+ boolean inExpansionState = isExpanded();
+ if (!inExpansionState) {
+ // not expanded, so we return the collapsed size
+ return mRowMinHeight;
+ }
+
+ return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
+ }
+
+
+
+ private void updateMaxExpandHeight() {
+ ViewGroup.LayoutParams lp = getLayoutParams();
+ int oldHeight = lp.height;
+ lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ setLayoutParams(lp);
+ measure(View.MeasureSpec.makeMeasureSpec(getMeasuredWidth(), View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(mRowMaxHeight, View.MeasureSpec.AT_MOST));
+ lp.height = oldHeight;
+ setLayoutParams(lp);
+ mMaxExpandHeight = getMeasuredHeight();
+ }
+
+ /**
+ * Check whether the view state is currently expanded. This is given by the system in {@link
+ * #setSystemExpanded(boolean)} and can be overridden by user expansion or
+ * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
+ * view can differ from this state, if layout params are modified from outside.
+ *
+ * @return whether the view state is currently expanded.
+ */
+ private boolean isExpanded() {
+ return !hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mMaxHeightNeedsUpdate = true;
+ }
+
public void setShowingPublic(boolean show) {
mShowingPublic = show;
- final ViewGroup publicLayout = (ViewGroup) findViewById(R.id.expandedPublic);
// bail out if no public version
- if (publicLayout.getChildCount() == 0) return;
+ if (mPublicLayout.getChildCount() == 0) return;
// TODO: animation?
- publicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
- findViewById(R.id.expanded).setVisibility(show ? View.GONE : View.VISIBLE);
+ mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
+ mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+
+ public int getMaxExpandHeight() {
+ if (mMaxHeightNeedsUpdate) {
+ updateMaxExpandHeight();
+ mMaxHeightNeedsUpdate = false;
+ }
+ return mMaxExpandHeight;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 2d2f2f1..6f93bed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -139,6 +139,7 @@
* @param expandedHeight the new expanded height
*/
private void updateNotificationStackHeight(float expandedHeight) {
+ mNotificationStackScroller.setIsExpanded(expandedHeight > 0.0f);
float childOffset = getRelativeTop(mNotificationStackScroller)
- mNotificationParent.getTranslationY();
int newStackHeight = (int) (expandedHeight - childOffset);
@@ -168,4 +169,16 @@
protected int getDesiredMeasureHeight() {
return mMaxPanelHeight;
}
+
+ @Override
+ protected void onExpandingStarted() {
+ super.onExpandingStarted();
+ mNotificationStackScroller.onExpansionStarted();
+ }
+
+ @Override
+ protected void onExpandingFinished() {
+ super.onExpandingFinished();
+ mNotificationStackScroller.onExpansionStopped();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 20fb225..6922ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -216,6 +216,7 @@
mTimeAnimator.end();
mRubberbanding = false;
mClosing = false;
+ onExpandingFinished();
}
}
};
@@ -230,6 +231,12 @@
mRubberbandingEnabled = enable;
}
+ protected void onExpandingFinished() {
+ }
+
+ protected void onExpandingStarted() {
+ }
+
private void runPeekAnimation() {
if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
if (mTimeAnimator.isStarted()) {
@@ -398,7 +405,7 @@
initVelocityTracker();
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
- mBar.onTrackingStarted(PanelView.this);
+ onTrackingStarted();
mInitialOffsetOnTouch = mExpandedHeight;
if (mExpandedHeight == 0) {
mJustPeeked = true;
@@ -443,7 +450,7 @@
mHandleView.setPressed(false);
postInvalidate(); // catch the press state change
}
- mBar.onTrackingStopped(PanelView.this);
+ onTrackingStopped();
trackMovement(event);
float vel = getCurrentVelocity();
@@ -458,6 +465,15 @@
return true;
}
+ protected void onTrackingStopped() {
+ mBar.onTrackingStopped(PanelView.this);
+ }
+
+ protected void onTrackingStarted() {
+ mBar.onTrackingStarted(PanelView.this);
+ onExpandingStarted();
+ }
+
private float getCurrentVelocity() {
float vel = 0;
float yVel = 0, xVel = 0;
@@ -561,6 +577,7 @@
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = y;
mTracking = true;
+ onTrackingStarted();
return true;
}
}
@@ -598,6 +615,8 @@
if (always||mVel != 0) {
animationTick(0); // begin the animation
+ } else {
+ onExpandingFinished();
}
}
@@ -770,6 +789,7 @@
if (!isFullyCollapsed()) {
mTimeAnimator.cancel();
mClosing = true;
+ onExpandingStarted();
// collapse() should never be a rubberband, even if an animation is already running
mRubberbanding = false;
fling(-mSelfCollapseVelocityPx, /*always=*/ true);
@@ -780,6 +800,7 @@
if (DEBUG) logf("expand: " + this);
if (isFullyCollapsed()) {
mBar.startOpeningPanel(this);
+ onExpandingStarted();
fling(mSelfExpandVelocityPx, /*always=*/ true);
} else if (DEBUG) {
if (DEBUG) logf("skipping expansion: is expanded");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f3dd7e3..841f3ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2641,7 +2641,8 @@
}
mHeadsUpNotificationDecay = res.getInteger(R.integer.heads_up_notification_decay);
- mRowHeight = res.getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mRowMinHeight = res.getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mRowMaxHeight = res.getDimensionPixelSize(R.dimen.notification_row_max_height);
if (false) Log.v(TAG, "updateResources");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 79932a7..2dba669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -78,7 +78,7 @@
}
if (mHeadsUp != null) {
- mHeadsUp.row.setExpanded(true);
+ mHeadsUp.row.setSystemExpanded(true);
mHeadsUp.row.setShowingPublic(false);
if (mContentHolder == null) {
// too soon!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index e2d6c5b..f31896a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -89,7 +89,7 @@
* The current State this Layout is in
*/
private final StackScrollState mCurrentStackScrollState = new StackScrollState(this);
-
+
private OnChildLocationsChangedListener mListener;
public NotificationStackScrollLayout(Context context) {
@@ -336,7 +336,7 @@
continue;
}
float top = slidingChild.getTranslationY();
- float bottom = top + slidingChild.getMeasuredHeight();
+ float bottom = top + slidingChild.getHeight();
int left = slidingChild.getLeft();
int right = slidingChild.getRight();
@@ -713,6 +713,13 @@
protected void onViewRemoved(View child) {
super.onViewRemoved(child);
mCurrentStackScrollState.removeViewStateForView(child);
+ mStackScrollAlgorithm.notifyChildrenChanged(this);
+ }
+
+ @Override
+ protected void onViewAdded(View child) {
+ super.onViewAdded(child);
+ mStackScrollAlgorithm.notifyChildrenChanged(this);
}
private boolean onInterceptTouchEventScroll(MotionEvent ev) {
@@ -858,6 +865,21 @@
return Math.max(getHeight() - mContentHeight, 0);
}
+ public void onExpansionStarted() {
+ mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
+ }
+
+ public void onExpansionStopped() {
+ mStackScrollAlgorithm.onExpansionStopped();
+ }
+
+ public void setIsExpanded(boolean isExpanded) {
+ mStackScrollAlgorithm.setIsExpanded(isExpanded);
+ if (!isExpanded) {
+ mOwnScrollY = 0;
+ }
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 4745f3b..5506a55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -21,6 +21,7 @@
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
/**
* The Algorithm of the {@link com.android.systemui.statusbar.stack
@@ -46,6 +47,11 @@
private float mLayoutHeight;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
+ private boolean mIsExpansionChanging;
+ private int mFirstChildMaxHeight;
+ private boolean mIsExpanded;
+ private View mFirstChildWhileExpanding;
+ private boolean mExpandedOnStart;
public StackScrollAlgorithm(Context context) {
initConstants(context);
@@ -117,8 +123,11 @@
StackScrollAlgorithmState algorithmState) {
float stackHeight = getLayoutHeight();
+ // The starting position of the bottom stack peek
+ float bottomPeekStart = stackHeight - mBottomStackPeekSize;
+
// The position where the bottom stack starts.
- float transitioningPositionStart = stackHeight - mCollapsedSize - mBottomStackPeekSize;
+ float transitioningPositionStart = bottomPeekStart - mCollapsedSize;
// The y coordinate of the current child.
float currentYPosition = 0.0f;
@@ -151,8 +160,8 @@
// Case 2:
// First element of regular scrollview comes next, so the position is just the
// scrolling position
- nextYPosition = Math.min(scrollOffset, transitioningPositionStart);
- childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+ nextYPosition = updateStateForFirstScrollingChild(transitioningPositionStart,
+ childViewState, scrollOffset);
} else if (nextYPosition >= transitioningPositionStart) {
if (currentYPosition >= transitioningPositionStart) {
// Case 3:
@@ -186,6 +195,32 @@
}
}
+ /**
+ * Update the state for the first child which is in the regular scrolling area.
+ *
+ * @param transitioningPositionStart the transition starting position of the bottom stack
+ * @param childViewState the view state of the child
+ * @param scrollOffset the position in the regular scroll view after this child
+ * @return the next child position
+ */
+ private float updateStateForFirstScrollingChild(float transitioningPositionStart,
+ StackScrollState.ViewState childViewState, float scrollOffset) {
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+ if (scrollOffset < transitioningPositionStart) {
+ return scrollOffset;
+ } else {
+ return transitioningPositionStart;
+ }
+ }
+
+ private int getMaxAllowedChildHeight(View child) {
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ return row.getMaximumAllowedExpandHeight();
+ }
+ return child.getHeight();
+ }
+
private float updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
float stackHeight, float transitioningPositionStart, float currentYPosition,
StackScrollState.ViewState childViewState, int childHeight, float nextYPosition) {
@@ -335,7 +370,17 @@
}
} else {
algorithmState.lastTopStackIndex = i;
+ if (i == 0) {
+ // The starting position of the bottom stack peek
+ float bottomPeekStart = getLayoutHeight() - mBottomStackPeekSize;
+ // Collapse and expand the first child while the shade is being expanded
+ float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
+ ? mFirstChildMaxHeight
+ : childHeight;
+ childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+ mCollapsedSize);
+ }
// We are already past the stack so we can end the loop
break;
}
@@ -381,6 +426,47 @@
this.mLayoutHeight = layoutHeight;
}
+ public void onExpansionStarted(StackScrollState currentState) {
+ mIsExpansionChanging = true;
+ mExpandedOnStart = mIsExpanded;
+ ViewGroup hostView = currentState.getHostView();
+ updateFirstChildHeightWhileExpanding(hostView);
+ }
+
+ private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
+ if (hostView.getChildCount() > 0) {
+ mFirstChildWhileExpanding = hostView.getChildAt(0);
+ if (mExpandedOnStart) {
+
+ // We are collapsing the shade, so the first child can get as most as high as the
+ // current height.
+ mFirstChildMaxHeight = mFirstChildWhileExpanding.getHeight();
+ } else {
+
+ // We are expanding the shade, expand it to its full height.
+ mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
+ }
+ } else {
+ mFirstChildWhileExpanding = null;
+ mFirstChildMaxHeight = 0;
+ }
+ }
+
+ public void onExpansionStopped() {
+ mIsExpansionChanging = false;
+ mFirstChildWhileExpanding = null;
+ }
+
+ public void setIsExpanded(boolean isExpanded) {
+ this.mIsExpanded = isExpanded;
+ }
+
+ public void notifyChildrenChanged(ViewGroup hostView) {
+ if (mIsExpansionChanging) {
+ updateFirstChildHeightWhileExpanding(hostView);
+ }
+ }
+
class StackScrollAlgorithmState {
/**
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ccdacea..216f6a4 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -986,7 +986,7 @@
initializeHdmiState();
// Match current screen state.
- if (mPowerManager.isScreenOn()) {
+ if (mPowerManager.isInteractive()) {
screenTurningOn(null);
} else {
screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
@@ -2357,7 +2357,7 @@
}
private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
- int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
+ int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
if ((actions & ACTION_PASS_TO_USER) != 0) {
long delayMillis = interceptKeyBeforeDispatching(
win, fallbackEvent, policyFlags);
@@ -3801,12 +3801,13 @@
/** {@inheritDoc} */
@Override
- public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
return 0;
}
+ final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
@@ -3818,7 +3819,7 @@
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
- (isScreenOn ?
+ (interactive ?
mKeyguardDelegate.isShowingAndNotHidden() :
mKeyguardDelegate.isShowing()));
@@ -3830,7 +3831,7 @@
if (DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
- + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
+ + " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags));
}
@@ -3839,18 +3840,11 @@
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
- // Basic policy based on screen state and keyguard.
- // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
- // is on or off, really. We should care about whether the device is in an
- // interactive state or is in suspend pretending to be "off".
- // The primary screen might be turned off due to proximity sensor or
- // because we are presenting media on an auxiliary screen or remotely controlling
- // the device some other way (which is why we have an exemption here for injected
- // events).
+ // Basic policy based on interactive state.
int result;
boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
| WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
- if (isScreenOn || (isInjected && !isWakeKey)) {
+ if (interactive || (isInjected && !isWakeKey)) {
// When the screen is on or if the key is injected pass the key to the application.
result = ACTION_PASS_TO_USER;
} else {
@@ -3875,7 +3869,7 @@
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
- if (isScreenOn && !mVolumeDownKeyTriggered
+ if (interactive && !mVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mVolumeDownKeyTriggered = true;
mVolumeDownKeyTime = event.getDownTime();
@@ -3889,7 +3883,7 @@
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (down) {
- if (isScreenOn && !mVolumeUpKeyTriggered
+ if (interactive && !mVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
@@ -3957,7 +3951,7 @@
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
- interceptPowerKeyDown(!isScreenOn || hungUp);
+ interceptPowerKeyDown(!interactive || hungUp);
} else {
if (interceptPowerKeyUp(canceled)) {
if ((mEndcallBehavior
@@ -3979,12 +3973,12 @@
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
- boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
+ boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
if (panic) {
mHandler.post(mRequestTransientNav);
}
- if (isScreenOn && !mPowerKeyTriggered
+ if (interactive && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mPowerKeyTriggered = true;
mPowerKeyTime = event.getDownTime();
@@ -4001,7 +3995,7 @@
telephonyService.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
- && telephonyService.isOffhook() && isScreenOn) {
+ && telephonyService.isOffhook() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telephonyService.endCall();
@@ -4010,7 +4004,7 @@
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
- interceptPowerKeyDown(!isScreenOn || hungUp
+ interceptPowerKeyDown(!interactive || hungUp
|| mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
} else {
mPowerKeyTriggered = false;
@@ -4143,15 +4137,12 @@
/** {@inheritDoc} */
@Override
- public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
- int result = 0;
-
- final boolean isWakeMotion = (policyFlags
- & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
- if (isWakeMotion) {
- mPowerManager.wakeUp(whenNanos / 1000000);
- }
- return result;
+ public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+ // We already know this is a wake motion so just wake up.
+ // Note that we would observe policyFlags containing
+ // FLAG_WAKE and FLAG_INTERACTIVE here.
+ mPowerManager.wakeUp(whenNanos / 1000000);
+ return 0;
}
void dispatchMediaKeyWithWakeLock(KeyEvent event) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index c3db55e..53ac063 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -132,6 +132,8 @@
private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
"temporaryEnableAccessibilityStateUntilKeyguardRemoved";
+ private static final String GET_WINDOW_TOKEN = "getWindowToken";
+
private static final ComponentName sFakeAccessibilityServiceComponentName =
new ComponentName("foo.bar", "FakeService");
@@ -360,6 +362,7 @@
}, UserHandle.ALL, intentFilter, null, null);
}
+ @Override
public int addClient(IAccessibilityManagerClient client, int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -388,6 +391,7 @@
}
}
+ @Override
public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -412,6 +416,7 @@
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
+ @Override
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
@@ -430,6 +435,7 @@
}
}
+ @Override
public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
int userId) {
List<AccessibilityServiceInfo> result = null;
@@ -463,6 +469,7 @@
return result;
}
+ @Override
public void interrupt(int userId) {
CopyOnWriteArrayList<Service> services;
synchronized (mLock) {
@@ -485,6 +492,7 @@
}
}
+ @Override
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
synchronized (mLock) {
@@ -521,6 +529,7 @@
}
}
+ @Override
public void removeAccessibilityInteractionConnection(IWindow window) {
synchronized (mLock) {
mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
@@ -570,6 +579,7 @@
return -1;
}
+ @Override
public void registerUiTestAutomationService(IBinder owner,
IAccessibilityServiceClient serviceClient,
AccessibilityServiceInfo accessibilityServiceInfo) {
@@ -612,6 +622,7 @@
}
}
+ @Override
public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
synchronized (mLock) {
UserState userState = getCurrentUserStateLocked();
@@ -630,6 +641,7 @@
}
}
+ @Override
public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
ComponentName service, boolean touchExplorationEnabled) {
mSecurityPolicy.enforceCallingPermission(
@@ -662,6 +674,29 @@
}
}
+ @Override
+ public IBinder getWindowToken(int windowId) {
+ mSecurityPolicy.enforceCallingPermission(
+ Manifest.permission.RETRIEVE_WINDOW_TOKEN,
+ GET_WINDOW_TOKEN);
+ synchronized (mLock) {
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return null;
+ }
+ if (mSecurityPolicy.findWindowById(windowId) == null) {
+ return null;
+ }
+ IBinder token = mGlobalWindowTokens.get(windowId);
+ if (token != null) {
+ return token;
+ }
+ return getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ }
+ }
+
boolean onGesture(int gestureId) {
synchronized (mLock) {
boolean handled = notifyGestureLocked(gestureId, false);
@@ -689,7 +724,7 @@
* @param outBounds The output to which to write the focus bounds.
* @return Whether accessibility focus was found and the bounds are populated.
*/
- // TODO: (multi-display) Make sure this works for multiple displays.
+ // TODO: (multi-display) Make sure this works for multiple displays.
boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
// Instead of keeping track of accessibility focus events per
// window to be able to find the focus in the active window,
diff --git a/services/core/java/com/android/server/display/DisplayBlanker.java b/services/core/java/com/android/server/display/DisplayBlanker.java
new file mode 100644
index 0000000..eb0ae6a
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 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.server.display;
+
+/**
+ * Interface used to update the actual display state.
+ */
+public interface DisplayBlanker {
+ void requestDisplayState(int state);
+}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 9ec1122..a5f9822 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -107,15 +107,9 @@
}
/**
- * Blanks the display, if supported.
+ * Sets the display state, if supported.
*/
- public void blankLocked() {
- }
-
- /**
- * Unblanks the display, if supported.
- */
- public void unblankLocked() {
+ public void requestDisplayStateLocked(int state) {
}
/**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 75f1f53..a77443d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -176,6 +176,11 @@
public String address;
/**
+ * Display state.
+ */
+ public int state = Display.STATE_ON;
+
+ /**
* The UID of the application that owns this display, or zero if it is owned by the system.
* <p>
* If the display is private, then only the owner can use it.
@@ -219,6 +224,7 @@
&& rotation == other.rotation
&& type == other.type
&& Objects.equal(address, other.address)
+ && state == other.state
&& ownerUid == other.ownerUid
&& Objects.equal(ownerPackageName, other.ownerPackageName);
}
@@ -241,6 +247,7 @@
rotation = other.rotation;
type = other.type;
address = other.address;
+ state = other.state;
ownerUid = other.ownerUid;
ownerPackageName = other.ownerPackageName;
}
@@ -260,6 +267,7 @@
if (address != null) {
sb.append(", address ").append(address);
}
+ sb.append(", state ").append(Display.stateToString(state));
if (ownerUid != 0 || ownerPackageName != null) {
sb.append(", owner ").append(ownerPackageName);
sb.append(" (uid ").append(ownerUid).append(")");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 693f7d8..071417b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -121,10 +121,6 @@
private static final int MSG_REQUEST_TRAVERSAL = 4;
private static final int MSG_UPDATE_VIEWPORT = 5;
- private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
- private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
- private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
-
private final Context mContext;
private final DisplayManagerHandler mHandler;
private final Handler mUiHandler;
@@ -176,8 +172,9 @@
// Display power controller.
private DisplayPowerController mDisplayPowerController;
- // Set to true if all displays have been blanked by the power manager.
- private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
+ // The overall display state, independent of changes that might influence one
+ // display or another in particular.
+ private int mGlobalDisplayState = Display.STATE_UNKNOWN;
// Set to true when there are pending display changes that have yet to be applied
// to the surface flinger state.
@@ -315,21 +312,11 @@
}
}
- private void blankAllDisplaysFromPowerManagerInternal() {
+ private void requestGlobalDisplayStateInternal(int state) {
synchronized (mSyncRoot) {
- if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
- mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
- updateAllDisplayBlankingLocked();
- scheduleTraversalLocked(false);
- }
- }
- }
-
- private void unblankAllDisplaysFromPowerManagerInternal() {
- synchronized (mSyncRoot) {
- if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
- mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
- updateAllDisplayBlankingLocked();
+ if (mGlobalDisplayState != state) {
+ mGlobalDisplayState = state;
+ updateGlobalDisplayStateLocked();
scheduleTraversalLocked(false);
}
}
@@ -616,7 +603,7 @@
mDisplayDevices.add(device);
addLogicalDisplayLocked(device);
- updateDisplayBlankingLocked(device);
+ updateDisplayStateLocked(device);
scheduleTraversalLocked(false);
}
@@ -655,27 +642,20 @@
scheduleTraversalLocked(false);
}
- private void updateAllDisplayBlankingLocked() {
+ private void updateGlobalDisplayStateLocked() {
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
- updateDisplayBlankingLocked(device);
+ updateDisplayStateLocked(device);
}
}
- private void updateDisplayBlankingLocked(DisplayDevice device) {
+ private void updateDisplayStateLocked(DisplayDevice device) {
// Blank or unblank the display immediately to match the state requested
- // by the power manager (if known).
+ // by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
- switch (mAllDisplayBlankStateFromPowerManager) {
- case DISPLAY_BLANK_STATE_BLANKED:
- device.blankLocked();
- break;
- case DISPLAY_BLANK_STATE_UNBLANKED:
- device.unblankLocked();
- break;
- }
+ device.requestDisplayStateLocked(mGlobalDisplayState);
}
}
@@ -816,9 +796,7 @@
+ device.getDisplayDeviceInfoLocked());
return;
}
- boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
- && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
- display.configureDisplayInTransactionLocked(device, isBlanked);
+ display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
// Update the viewports if needed.
if (!mDefaultViewport.valid
@@ -897,8 +875,7 @@
pw.println(" mOnlyCode=" + mOnlyCore);
pw.println(" mSafeMode=" + mSafeMode);
pw.println(" mPendingTraversal=" + mPendingTraversal);
- pw.println(" mAllDisplayBlankStateFromPowerManager="
- + mAllDisplayBlankStateFromPowerManager);
+ pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
pw.println(" mDefaultViewport=" + mDefaultViewport);
pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
@@ -1322,11 +1299,26 @@
private final class LocalService extends DisplayManagerInternal {
@Override
- public void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler,
+ public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
+ DisplayBlanker blanker = new DisplayBlanker() {
+ @Override
+ public void requestDisplayState(int state) {
+ // The order of operations is important for legacy reasons.
+ if (state == Display.STATE_OFF) {
+ requestGlobalDisplayStateInternal(state);
+ }
+
+ callbacks.onDisplayStateChange(state);
+
+ if (state != Display.STATE_OFF) {
+ requestGlobalDisplayStateInternal(state);
+ }
+ }
+ };
mDisplayPowerController = new DisplayPowerController(
- mContext, callbacks, handler, sensorManager);
+ mContext, callbacks, handler, sensorManager, blanker);
}
}
@@ -1343,16 +1335,6 @@
}
@Override
- public void blankAllDisplaysFromPowerManager() {
- blankAllDisplaysFromPowerManagerInternal();
- }
-
- @Override
- public void unblankAllDisplaysFromPowerManager() {
- unblankAllDisplaysFromPowerManagerInternal();
- }
-
- @Override
public DisplayInfo getDisplayInfo(int displayId) {
return getDisplayInfoInternal(displayId, Process.myUid());
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 62fb02a..1f38eb6 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -42,6 +42,7 @@
import android.util.Slog;
import android.util.Spline;
import android.util.TimeUtils;
+import android.view.Display;
import java.io.PrintWriter;
@@ -122,6 +123,9 @@
// The sensor manager.
private final SensorManager mSensorManager;
+ // The display blanker.
+ private final DisplayBlanker mBlanker;
+
// The proximity sensor, or null if not available or needed.
private Sensor mProximitySensor;
@@ -225,13 +229,15 @@
* Creates the display power controller.
*/
public DisplayPowerController(Context context,
- DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) {
+ DisplayPowerCallbacks callbacks, Handler handler,
+ SensorManager sensorManager, DisplayBlanker blanker) {
mHandler = new DisplayControllerHandler(handler.getLooper());
mCallbacks = callbacks;
mBatteryStats = BatteryStatsService.getService();
mLights = LocalServices.getService(LightsManager.class);
mSensorManager = sensorManager;
+ mBlanker = blanker;
final Resources resources = context.getResources();
@@ -366,8 +372,11 @@
}
private void initialize() {
- mPowerState = new DisplayPowerState(new ElectronBeam(), mCallbacks,
- mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
+ // Initialize the power state object for the default display.
+ // In the future, we might manage multiple displays independently.
+ mPowerState = new DisplayPowerState(mBlanker,
+ mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
+ new ElectronBeam(Display.DEFAULT_DISPLAY));
mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -384,7 +393,7 @@
// Initialize screen state for battery stats.
try {
- if (mPowerState.isScreenOn()) {
+ if (mPowerState.getScreenState() != Display.STATE_OFF) {
mBatteryStats.noteScreenOn();
} else {
mBatteryStats.noteScreenOff();
@@ -523,7 +532,7 @@
// Animate the screen on or off unless blocked.
if (mScreenOffBecauseOfProximity) {
// Screen off due to proximity.
- setScreenOn(false);
+ setScreenState(Display.STATE_OFF);
unblockScreenOn();
} else if (mPowerRequest.wantScreenOnAny()) {
// Want screen on.
@@ -534,7 +543,8 @@
// Turn the screen on. The contents of the screen may not yet
// be visible if the electron beam has not been dismissed because
// its last frame of animation is solid black.
- setScreenOn(true);
+ setScreenState(mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE
+ ? Display.STATE_DOZING : Display.STATE_ON);
if (mPowerRequest.blockScreenOn
&& mPowerState.getElectronBeamLevel() == 0.0f) {
@@ -567,12 +577,12 @@
if (!mElectronBeamOnAnimator.isStarted()) {
if (!mElectronBeamOffAnimator.isStarted()) {
if (mPowerState.getElectronBeamLevel() == 0.0f) {
- setScreenOn(false);
+ setScreenState(Display.STATE_OFF);
} else if (mPowerState.prepareElectronBeam(
mElectronBeamFadesConfig ?
ElectronBeam.MODE_FADE :
ElectronBeam.MODE_COOL_DOWN)
- && mPowerState.isScreenOn()) {
+ && mPowerState.getScreenState() != Display.STATE_OFF) {
mElectronBeamOffAnimator.start();
} else {
mElectronBeamOffAnimator.end();
@@ -610,9 +620,9 @@
private void blockScreenOn() {
if (!mScreenOnWasBlocked) {
mScreenOnWasBlocked = true;
+ mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
if (DEBUG) {
Slog.d(TAG, "Blocked screen on.");
- mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
}
}
}
@@ -627,11 +637,11 @@
}
}
- private void setScreenOn(boolean on) {
- if (mPowerState.isScreenOn() != on) {
- mPowerState.setScreenOn(on);
+ private void setScreenState(int state) {
+ if (mPowerState.getScreenState() != state) {
+ mPowerState.setScreenState(state);
try {
- if (on) {
+ if (state != Display.STATE_OFF) {
mBatteryStats.noteScreenOn();
} else {
mBatteryStats.noteScreenOff();
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index e1416d7..a5f8849 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -18,7 +18,6 @@
import com.android.server.lights.Light;
-import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
@@ -27,6 +26,7 @@
import android.util.IntProperty;
import android.util.Slog;
import android.view.Choreographer;
+import android.view.Display;
import java.io.PrintWriter;
@@ -54,12 +54,12 @@
private final Handler mHandler;
private final Choreographer mChoreographer;
- private final ElectronBeam mElectronBeam;
- private final DisplayPowerCallbacks mCallbacks;
+ private final DisplayBlanker mBlanker;
private final Light mBacklight;
+ private final ElectronBeam mElectronBeam;
private final PhotonicModulator mPhotonicModulator;
- private boolean mScreenOn;
+ private int mScreenState;
private int mScreenBrightness;
private boolean mScreenReady;
private boolean mScreenUpdatePending;
@@ -71,13 +71,12 @@
private Runnable mCleanListener;
- public DisplayPowerState(ElectronBeam electronBean,
- DisplayPowerCallbacks callbacks, Light backlight) {
+ public DisplayPowerState(DisplayBlanker blanker, Light backlight, ElectronBeam electronBeam) {
mHandler = new Handler(true /*async*/);
mChoreographer = Choreographer.getInstance();
- mElectronBeam = electronBean;
- mCallbacks = callbacks;
+ mBlanker = blanker;
mBacklight = backlight;
+ mElectronBeam = electronBeam;
mPhotonicModulator = new PhotonicModulator();
// At boot time, we know that the screen is on and the electron beam
@@ -86,7 +85,7 @@
// Although we set the brightness to full on here, the display power controller
// will reset the brightness to a new level immediately before the changes
// actually have a chance to be applied.
- mScreenOn = true;
+ mScreenState = Display.STATE_ON;
mScreenBrightness = PowerManager.BRIGHTNESS_ON;
scheduleScreenUpdate();
@@ -122,25 +121,25 @@
};
/**
- * Sets whether the screen is on or off.
+ * Sets whether the screen is on, off, or dozing.
*/
- public void setScreenOn(boolean on) {
- if (mScreenOn != on) {
+ public void setScreenState(int state) {
+ if (mScreenState != state) {
if (DEBUG) {
- Slog.d(TAG, "setScreenOn: on=" + on);
+ Slog.d(TAG, "setScreenState: state=" + state);
}
- mScreenOn = on;
+ mScreenState = state;
mScreenReady = false;
scheduleScreenUpdate();
}
}
/**
- * Returns true if the screen is on.
+ * Gets the desired screen state.
*/
- public boolean isScreenOn() {
- return mScreenOn;
+ public int getScreenState() {
+ return mScreenState;
}
/**
@@ -155,7 +154,7 @@
}
mScreenBrightness = brightness;
- if (mScreenOn) {
+ if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate();
}
@@ -219,7 +218,7 @@
}
mElectronBeamLevel = level;
- if (mScreenOn) {
+ if (mScreenState != Display.STATE_OFF) {
mScreenReady = false;
scheduleScreenUpdate(); // update backlight brightness
}
@@ -256,7 +255,7 @@
public void dump(PrintWriter pw) {
pw.println();
pw.println("Display Power State:");
- pw.println(" mScreenOn=" + mScreenOn);
+ pw.println(" mScreenState=" + Display.stateToString(mScreenState));
pw.println(" mScreenBrightness=" + mScreenBrightness);
pw.println(" mScreenReady=" + mScreenReady);
pw.println(" mScreenUpdatePending=" + mScreenUpdatePending);
@@ -302,8 +301,9 @@
public void run() {
mScreenUpdatePending = false;
- int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
- if (mPhotonicModulator.setState(mScreenOn, brightness)) {
+ int brightness = mScreenState != Display.STATE_OFF
+ && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
+ if (mPhotonicModulator.setState(mScreenState, brightness)) {
if (DEBUG) {
Slog.d(TAG, "Screen ready");
}
@@ -335,26 +335,26 @@
* Updates the state of the screen and backlight asynchronously on a separate thread.
*/
private final class PhotonicModulator {
- private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
+ private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
private static final int INITIAL_BACKLIGHT = -1; // unknown
private final Object mLock = new Object();
- private boolean mPendingOn = INITIAL_SCREEN_ON;
+ private int mPendingState = INITIAL_SCREEN_STATE;
private int mPendingBacklight = INITIAL_BACKLIGHT;
- private boolean mActualOn = INITIAL_SCREEN_ON;
+ private int mActualState = INITIAL_SCREEN_STATE;
private int mActualBacklight = INITIAL_BACKLIGHT;
private boolean mChangeInProgress;
- public boolean setState(boolean on, int backlight) {
+ public boolean setState(int state, int backlight) {
synchronized (mLock) {
- if (on != mPendingOn || backlight != mPendingBacklight) {
+ if (state != mPendingState || backlight != mPendingBacklight) {
if (DEBUG) {
- Slog.d(TAG, "Requesting new screen state: on=" + on
- + ", backlight=" + backlight);
+ Slog.d(TAG, "Requesting new screen state: state="
+ + Display.stateToString(state) + ", backlight=" + backlight);
}
- mPendingOn = on;
+ mPendingState = state;
mPendingBacklight = backlight;
if (!mChangeInProgress) {
@@ -369,9 +369,9 @@
public void dump(PrintWriter pw) {
pw.println();
pw.println("Photonic Modulator State:");
- pw.println(" mPendingOn=" + mPendingOn);
+ pw.println(" mPendingState=" + Display.stateToString(mPendingState));
pw.println(" mPendingBacklight=" + mPendingBacklight);
- pw.println(" mActualOn=" + mActualOn);
+ pw.println(" mActualState=" + Display.stateToString(mActualState));
pw.println(" mActualBacklight=" + mActualBacklight);
pw.println(" mChangeInProgress=" + mChangeInProgress);
}
@@ -381,35 +381,35 @@
public void run() {
// Apply pending changes until done.
for (;;) {
- final boolean on;
- final boolean onChanged;
+ final int state;
+ final boolean stateChanged;
final int backlight;
final boolean backlightChanged;
synchronized (mLock) {
- on = mPendingOn;
- onChanged = (on != mActualOn);
+ state = mPendingState;
+ stateChanged = (state != mActualState);
backlight = mPendingBacklight;
backlightChanged = (backlight != mActualBacklight);
- if (!onChanged && !backlightChanged) {
+ if (!stateChanged && !backlightChanged) {
mChangeInProgress = false;
break;
}
- mActualOn = on;
+ mActualState = state;
mActualBacklight = backlight;
}
if (DEBUG) {
- Slog.d(TAG, "Updating screen state: on=" + on
- + ", backlight=" + backlight);
+ Slog.d(TAG, "Updating screen state: state="
+ + Display.stateToString(state) + ", backlight=" + backlight);
}
- if (onChanged && on) {
- mCallbacks.unblankAllDisplays();
+ if (stateChanged && state != Display.STATE_OFF) {
+ mBlanker.requestDisplayState(state);
}
if (backlightChanged) {
mBacklight.setBrightness(backlight);
}
- if (onChanged && !on) {
- mCallbacks.blankAllDisplays();
+ if (stateChanged && state == Display.STATE_OFF) {
+ mBlanker.requestDisplayState(state);
}
}
diff --git a/services/core/java/com/android/server/display/ElectronBeam.java b/services/core/java/com/android/server/display/ElectronBeam.java
index 13816bb..18e4049 100644
--- a/services/core/java/com/android/server/display/ElectronBeam.java
+++ b/services/core/java/com/android/server/display/ElectronBeam.java
@@ -35,7 +35,6 @@
import android.os.Looper;
import android.util.FloatMath;
import android.util.Slog;
-import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
@@ -74,6 +73,8 @@
// See code for details.
private static final int DEJANK_FRAMES = 3;
+ private final int mDisplayId;
+
// Set to true when the animation context has been fully prepared.
private boolean mPrepared;
private int mMode;
@@ -118,8 +119,8 @@
*/
public static final int MODE_FADE = 2;
-
- public ElectronBeam() {
+ public ElectronBeam(int displayId) {
+ mDisplayId = displayId;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
}
@@ -139,7 +140,7 @@
// Get the display size and layer stack.
// This is not expected to change while the electron beam surface is showing.
- DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+ DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
mDisplayLayerStack = displayInfo.layerStack;
mDisplayWidth = displayInfo.getNaturalWidth();
mDisplayHeight = displayInfo.getNaturalHeight();
@@ -528,7 +529,8 @@
mSurface = new Surface();
mSurface.copyFrom(mSurfaceControl);
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl);
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+ mDisplayId, mSurfaceControl);
mSurfaceLayout.onDisplayTransaction();
} finally {
SurfaceControl.closeTransaction();
@@ -687,11 +689,13 @@
*/
private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
private final DisplayManagerInternal mDisplayManagerInternal;
+ private final int mDisplayId;
private SurfaceControl mSurfaceControl;
public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal,
- SurfaceControl surfaceControl) {
+ int displayId, SurfaceControl surfaceControl) {
mDisplayManagerInternal = displayManagerInternal;
+ mDisplayId = displayId;
mSurfaceControl = surfaceControl;
mDisplayManagerInternal.registerDisplayTransactionListener(this);
}
@@ -710,8 +714,7 @@
return;
}
- DisplayInfo displayInfo =
- mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+ DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
switch (displayInfo.rotation) {
case Surface.ROTATION_0:
mSurfaceControl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 02be477..2c8f1b4 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -101,7 +101,7 @@
private DisplayDeviceInfo mInfo;
private boolean mHavePendingChanges;
- private boolean mBlanked;
+ private int mState = Display.STATE_UNKNOWN;
public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
SurfaceControl.PhysicalDisplayInfo phys) {
@@ -134,6 +134,7 @@
mInfo.width = mPhys.width;
mInfo.height = mPhys.height;
mInfo.refreshRate = mPhys.refreshRate;
+ mInfo.state = mState;
// Assume that all built-in displays that have secure output (eg. HDCP) also
// support compositing from gralloc protected buffers.
@@ -177,15 +178,16 @@
}
@Override
- public void blankLocked() {
- mBlanked = true;
- SurfaceControl.blankDisplay(getDisplayTokenLocked());
- }
-
- @Override
- public void unblankLocked() {
- mBlanked = false;
- SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+ public void requestDisplayStateLocked(int state) {
+ if (mState != state) {
+ if (state == Display.STATE_OFF && mState != Display.STATE_OFF) {
+ SurfaceControl.blankDisplay(getDisplayTokenLocked());
+ } else if (state != Display.STATE_OFF && mState == Display.STATE_OFF) {
+ SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+ }
+ mState = state;
+ updateDeviceInfoLocked();
+ }
}
@Override
@@ -193,7 +195,12 @@
super.dumpLocked(pw);
pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
pw.println("mPhys=" + mPhys);
- pw.println("mBlanked=" + mBlanked);
+ pw.println("mState=" + Display.stateToString(mState));
+ }
+
+ private void updateDeviceInfoLocked() {
+ mInfo = null;
+ sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
}
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index c26c438..d61a35b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -114,6 +114,7 @@
mInfo.copyFrom(mOverrideDisplayInfo);
mInfo.layerStack = mBaseDisplayInfo.layerStack;
mInfo.name = mBaseDisplayInfo.name;
+ mInfo.state = mBaseDisplayInfo.state;
} else {
mInfo.copyFrom(mBaseDisplayInfo);
}
@@ -212,6 +213,7 @@
mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
+ mBaseDisplayInfo.state = deviceInfo.state;
mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 007acf7..bfd8372c 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -194,12 +194,14 @@
private final int mDensityDpi;
private final boolean mSecure;
- private Surface mSurface;
+ private int mState;
private SurfaceTexture mSurfaceTexture;
+ private Surface mSurface;
private DisplayDeviceInfo mInfo;
public OverlayDisplayDevice(IBinder displayToken, String name,
- int width, int height, float refreshRate, int densityDpi, boolean secure,
+ int width, int height, float refreshRate,
+ int densityDpi, boolean secure, int state,
SurfaceTexture surfaceTexture) {
super(OverlayDisplayAdapter.this, displayToken);
mName = name;
@@ -208,6 +210,7 @@
mRefreshRate = refreshRate;
mDensityDpi = densityDpi;
mSecure = secure;
+ mState = state;
mSurfaceTexture = surfaceTexture;
}
@@ -230,6 +233,11 @@
}
}
+ public void setStateLocked(int state) {
+ mState = state;
+ mInfo = null;
+ }
+
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
if (mInfo == null) {
@@ -247,6 +255,7 @@
}
mInfo.type = Display.TYPE_OVERLAY;
mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+ mInfo.state = mState;
}
return mInfo;
}
@@ -288,11 +297,12 @@
// Called on the UI thread.
@Override
- public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
+ public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, int state) {
synchronized (getSyncRoot()) {
IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure);
mDevice = new OverlayDisplayDevice(displayToken, mName,
- mWidth, mHeight, refreshRate, mDensityDpi, mSecure, surfaceTexture);
+ mWidth, mHeight, refreshRate, mDensityDpi, mSecure,
+ state, surfaceTexture);
sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
}
@@ -309,6 +319,17 @@
}
}
+ // Called on the UI thread.
+ @Override
+ public void onStateChanged(int state) {
+ synchronized (getSyncRoot()) {
+ if (mDevice != null) {
+ mDevice.setStateLocked(state);
+ sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+ }
+ }
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println(" " + mName + ":");
pw.println(" mWidth=" + mWidth);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index f1dd60a..06891f3 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -282,6 +282,7 @@
if (displayId == mDefaultDisplay.getDisplayId()) {
if (updateDefaultDisplayInfo()) {
relayout();
+ mListener.onStateChanged(mDefaultDisplayInfo.state);
} else {
dismiss();
}
@@ -301,7 +302,8 @@
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
int width, int height) {
- mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
+ mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate,
+ mDefaultDisplayInfo.state);
}
@Override
@@ -370,7 +372,9 @@
* Watches for significant changes in the overlay display window lifecycle.
*/
public interface Listener {
- public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
+ public void onWindowCreated(SurfaceTexture surfaceTexture,
+ float refreshRate, int state);
public void onWindowDestroyed();
+ public void onStateChanged(int state);
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
index 64b51c9..baae1d99 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
@@ -182,11 +182,49 @@
}
/**
+ * Send <Active Source> command. The default implementation does nothing. Should be
+ * overriden by subclass.
+ */
+ public void sendActiveSource(int physicalAddress) {
+ logWarning("<Active Source> not valid for the device type: " + mType
+ + " address:" + physicalAddress);
+ }
+
+ /**
+ * Send <Inactive Source> command. The default implementation does nothing. Should be
+ * overriden by subclass.
+ */
+ public void sendInactiveSource(int physicalAddress) {
+ logWarning("<Inactive Source> not valid for the device type: " + mType
+ + " address:" + physicalAddress);
+ }
+
+ /**
+ * Send <Image View On> command. The default implementation does nothing. Should be
+ * overriden by subclass.
+ */
+ public void sendImageViewOn() {
+ logWarning("<Image View On> not valid for the device type: " + mType);
+ }
+
+ /**
+ * Send <Text View On> command. The default implementation does nothing. Should be
+ * overriden by subclass.
+ */
+ public void sendTextViewOn() {
+ logWarning("<Text View On> not valid for the device type: " + mType);
+ }
+
+ /**
* Check if the connected sink device is in powered-on state. The default implementation
* simply returns false. Should be overriden by subclass to report the correct state.
*/
public boolean isSinkDeviceOn() {
- Log.w(TAG, "Not valid for the device type: " + mType);
+ logWarning("isSinkDeviceOn() not valid for the device type: " + mType);
return false;
}
+
+ private void logWarning(String msg) {
+ Log.w(TAG, msg);
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
index 0310264..f8cf11d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
@@ -66,14 +66,11 @@
// 1) Response for the queried power status request arrives. Update the status.
// 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going
// into standby mode too.
- // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up.
if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) {
mSinkDevicePowerStatus = params[0];
} else if (srcAddress == HdmiCec.ADDR_TV) {
if (opcode == HdmiCec.MESSAGE_STANDBY) {
mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY;
- } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) {
- mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON;
}
}
super.handleMessage(srcAddress, dstAddress, opcode, params);
@@ -95,4 +92,38 @@
public boolean isSinkDeviceOn() {
return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON;
}
+
+ @Override
+ public void sendActiveSource(int physicalAddress) {
+ setIsActiveSource(true);
+ byte[] param = new byte[] {
+ (byte) ((physicalAddress >> 8) & 0xff),
+ (byte) (physicalAddress & 0xff)
+ };
+ getService().sendMessage(getType(), HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE,
+ param);
+ }
+
+ @Override
+ public void sendInactiveSource(int physicalAddress) {
+ setIsActiveSource(false);
+ byte[] param = new byte[] {
+ (byte) ((physicalAddress >> 8) & 0xff),
+ (byte) (physicalAddress & 0xff)
+ };
+ getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_INACTIVE_SOURCE,
+ param);
+ }
+
+ @Override
+ public void sendImageViewOn() {
+ getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_IMAGE_VIEW_ON,
+ HdmiCecService.EMPTY_PARAM);
+ }
+
+ @Override
+ public void sendTextViewOn() {
+ getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_TEXT_VIEW_ON,
+ HdmiCecService.EMPTY_PARAM);
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java
index aa496c5..0a4c719 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java
@@ -277,14 +277,7 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- device.setIsActiveSource(true);
- int physicalAddress = nativeGetPhysicalAddress(mNativePtr);
- byte[] param = new byte[] {
- (byte) ((physicalAddress >> 8) & 0xff),
- (byte) (physicalAddress & 0xff)
- };
- nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
- HdmiCec.MESSAGE_ACTIVE_SOURCE, param);
+ device.sendActiveSource(nativeGetPhysicalAddress(mNativePtr));
}
}
@@ -293,9 +286,7 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- device.setIsActiveSource(false);
- nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
- HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM);
+ device.sendInactiveSource(nativeGetPhysicalAddress(mNativePtr));
}
}
@@ -304,8 +295,7 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
- HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM);
+ device.sendImageViewOn();
}
}
@@ -314,8 +304,16 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
- HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM);
+ device.sendTextViewOn();
+ }
+ }
+
+ public void sendGiveDevicePowerStatus(IBinder b, int address) {
+ enforceAccessPermission();
+ synchronized (mLock) {
+ HdmiCecDevice device = getLogicalDeviceLocked(b);
+ nativeSendMessage(mNativePtr, device.getType(), address,
+ HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM);
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 316bd57..54cb035 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -185,6 +185,7 @@
InputChannel fromChannel, InputChannel toChannel);
private static native void nativeSetPointerSpeed(long ptr, int speed);
private static native void nativeSetShowTouches(long ptr, boolean enabled);
+ private static native void nativeSetInteractive(long ptr, boolean interactive);
private static native void nativeReloadCalibration(long ptr);
private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
int repeat, int token);
@@ -1404,14 +1405,13 @@
}
// Native callback.
- private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
- return mWindowManagerCallbacks.interceptKeyBeforeQueueing(
- event, policyFlags, isScreenOn);
+ private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+ return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}
// Native callback.
- private int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
- return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(
+ private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+ return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
whenNanos, policyFlags);
}
@@ -1570,9 +1570,9 @@
public long notifyANR(InputApplicationHandle inputApplicationHandle,
InputWindowHandle inputWindowHandle, String reason);
- public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
- public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
+ public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags);
@@ -1740,5 +1740,10 @@
public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
return injectInputEventInternal(event, displayId, mode);
}
+
+ @Override
+ public void setInteractive(boolean interactive) {
+ nativeSetInteractive(mPtr, interactive);
+ }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index eb7cc4c..855ae23 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1730,7 +1730,7 @@
private void updateScreenOn() {
synchronized (mRulesLock) {
try {
- mScreenOn = mPowerManager.isScreenOn();
+ mScreenOn = mPowerManager.isInteractive();
} catch (RemoteException e) {
// ignored; service lives in system_server
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index f72efff..d84e8e1 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -28,6 +28,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.hardware.input.InputManagerInternal;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -86,6 +87,7 @@
private final ScreenOnBlocker mScreenOnBlocker;
private final WindowManagerPolicy mPolicy;
private final ActivityManagerInternal mActivityManagerInternal;
+ private final InputManagerInternal mInputManagerInternal;
private final NotifierHandler mHandler;
private final Intent mScreenOnIntent;
@@ -121,6 +123,7 @@
mScreenOnBlocker = screenOnBlocker;
mPolicy = policy;
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mHandler = new NotifierHandler(looper);
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
@@ -232,73 +235,58 @@
}
/**
- * Called when the device is waking up from sleep and the
- * display is about to be turned on.
+ * Notifies that the device is changing interactive state.
*/
- public void onWakeUpStarted() {
+ public void onInteractiveStateChangeStarted(boolean interactive, int reason) {
if (DEBUG) {
- Slog.d(TAG, "onWakeUpStarted");
+ Slog.d(TAG, "onInteractiveChangeStarted: interactive=" + interactive
+ + ", reason=" + reason);
}
synchronized (mLock) {
- if (mActualPowerState != POWER_STATE_AWAKE) {
- mActualPowerState = POWER_STATE_AWAKE;
- mPendingWakeUpBroadcast = true;
- if (!mScreenOnBlockerAcquired) {
- mScreenOnBlockerAcquired = true;
- mScreenOnBlocker.acquire();
+ if (interactive) {
+ // Waking up...
+ if (mActualPowerState != POWER_STATE_AWAKE) {
+ mActualPowerState = POWER_STATE_AWAKE;
+ mPendingWakeUpBroadcast = true;
+ if (!mScreenOnBlockerAcquired) {
+ mScreenOnBlockerAcquired = true;
+ mScreenOnBlocker.acquire();
+ }
+ updatePendingBroadcastLocked();
}
- updatePendingBroadcastLocked();
+ } else {
+ // Going to sleep...
+ mLastGoToSleepReason = reason;
}
+ mInputManagerInternal.setInteractive(interactive);
}
}
/**
- * Called when the device has finished waking up from sleep
- * and the display has been turned on.
+ * Notifies that the device has finished changing interactive state.
*/
- public void onWakeUpFinished() {
+ public void onInteractiveStateChangeFinished(boolean interactive) {
if (DEBUG) {
- Slog.d(TAG, "onWakeUpFinished");
- }
- }
-
- /**
- * Called when the device is going to sleep.
- */
- public void onGoToSleepStarted(int reason) {
- if (DEBUG) {
- Slog.d(TAG, "onGoToSleepStarted");
+ Slog.d(TAG, "onInteractiveChangeFinished");
}
synchronized (mLock) {
- mLastGoToSleepReason = reason;
- }
- }
-
- /**
- * Called when the device has finished going to sleep and the
- * display has been turned off.
- *
- * This is a good time to make transitions that we don't want the user to see,
- * such as bringing the key guard to focus. There's no guarantee for this,
- * however because the user could turn the device on again at any time.
- * Some things may need to be protected by other mechanisms that defer screen on.
- */
- public void onGoToSleepFinished() {
- if (DEBUG) {
- Slog.d(TAG, "onGoToSleepFinished");
- }
-
- synchronized (mLock) {
- if (mActualPowerState != POWER_STATE_ASLEEP) {
- mActualPowerState = POWER_STATE_ASLEEP;
- mPendingGoToSleepBroadcast = true;
- if (mUserActivityPending) {
- mUserActivityPending = false;
- mHandler.removeMessages(MSG_USER_ACTIVITY);
+ if (!interactive) {
+ // Finished going to sleep...
+ // This is a good time to make transitions that we don't want the user to see,
+ // such as bringing the key guard to focus. There's no guarantee for this,
+ // however because the user could turn the device on again at any time.
+ // Some things may need to be protected by other mechanisms that defer screen on.
+ if (mActualPowerState != POWER_STATE_ASLEEP) {
+ mActualPowerState = POWER_STATE_ASLEEP;
+ mPendingGoToSleepBroadcast = true;
+ if (mUserActivityPending) {
+ mUserActivityPending = false;
+ mHandler.removeMessages(MSG_USER_ACTIVITY);
+ }
+ updatePendingBroadcastLocked();
}
- updatePendingBroadcastLocked();
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 90363d7..82cef7f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -62,6 +62,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.TimeUtils;
+import android.view.Display;
import android.view.WindowManagerPolicy;
import java.io.FileDescriptor;
@@ -209,6 +210,10 @@
// A bitfield that summarizes the state of all active wakelocks.
private int mWakeLockSummary;
+ // True if the device is in an interactive state.
+ private boolean mInteractive;
+ private boolean mInteractiveChanging;
+
// If true, instructs the display controller to wait for the proximity sensor to
// go negative before turning the screen on.
private boolean mRequestWaitForNegativeProximity;
@@ -217,11 +222,6 @@
private long mLastWakeTime;
private long mLastSleepTime;
- // True if we need to send a wake up or go to sleep finished notification
- // when the display is ready.
- private boolean mSendWakeUpFinishedNotificationWhenReady;
- private boolean mSendGoToSleepFinishedNotificationWhenReady;
-
// Timestamp of the last call to user activity.
private long mLastUserActivityTime;
private long mLastUserActivityTimeNoChangeLights;
@@ -265,11 +265,11 @@
// True if auto-suspend mode is enabled.
// Refer to autosuspend.h.
- private boolean mAutoSuspendModeEnabled;
+ private boolean mHalAutoSuspendModeEnabled;
// True if interactive mode is enabled.
// Refer to power.h.
- private boolean mInteractiveModeEnabled;
+ private boolean mHalInteractiveModeEnabled;
// True if the device is plugged into a power source.
private boolean mIsPowered;
@@ -289,10 +289,10 @@
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
// True to decouple auto-suspend mode from the display state.
- private boolean mDecoupleAutoSuspendModeFromDisplayConfig;
+ private boolean mDecoupleHalAutoSuspendModeFromDisplayConfig;
// True to decouple interactive mode from the display state.
- private boolean mDecoupleInteractiveModeFromDisplayConfig;
+ private boolean mDecoupleHalInteractiveModeFromDisplayConfig;
// True if the device should wake up when plugged or unplugged.
private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
@@ -397,7 +397,6 @@
private native void nativeInit();
- private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
private static native void nativeAcquireSuspendBlocker(String name);
private static native void nativeReleaseSuspendBlocker(String name);
private static native void nativeSetInteractive(boolean enable);
@@ -412,13 +411,17 @@
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
+ mHalAutoSuspendModeEnabled = false;
+ mHalInteractiveModeEnabled = true;
mScreenOnBlocker = new ScreenOnBlockerImpl();
mWakefulness = WAKEFULNESS_AWAKE;
- }
+ mInteractive = true;
- nativeInit();
- nativeSetPowerState(true, true);
+ nativeInit();
+ nativeSetAutoSuspend(false);
+ nativeSetInteractive(true);
+ }
}
@Override
@@ -446,14 +449,6 @@
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
-
- // Forcibly turn the screen on at boot so that it is in a known power state.
- // We do this in init() rather than in the constructor because setting the
- // screen state requires a call into surface flinger which then needs to call back
- // into the activity manager to check permissions. Unfortunately the
- // activity manager is not running when the constructor is called, so we
- // have to defer setting the screen state until this point.
- mDisplayPowerCallbacks.unblankAllDisplays();
}
void setPolicy(WindowManagerPolicy policy) {
@@ -547,9 +542,9 @@
private void readConfigurationLocked() {
final Resources resources = mContext.getResources();
- mDecoupleAutoSuspendModeFromDisplayConfig = resources.getBoolean(
+ mDecoupleHalAutoSuspendModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay);
- mDecoupleInteractiveModeFromDisplayConfig = resources.getBoolean(
+ mDecoupleHalInteractiveModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
com.android.internal.R.bool.config_unplugTurnsOnScreen);
@@ -867,11 +862,6 @@
return false;
}
- // Called from native code.
- private void wakeUpFromNative(long eventTime) {
- wakeUpInternal(eventTime);
- }
-
private void wakeUpInternal(long eventTime) {
synchronized (mLock) {
if (wakeUpNoUpdateLocked(eventTime)) {
@@ -902,26 +892,16 @@
break;
}
- if (mWakefulness != WAKEFULNESS_DREAMING) {
- sendPendingNotificationsLocked();
- mNotifier.onWakeUpStarted();
- mSendWakeUpFinishedNotificationWhenReady = true;
- }
-
mLastWakeTime = eventTime;
- mWakefulness = WAKEFULNESS_AWAKE;
mDirty |= DIRTY_WAKEFULNESS;
+ mWakefulness = WAKEFULNESS_AWAKE;
+ setInteractiveStateLocked(true, 0);
userActivityNoUpdateLocked(
eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
return true;
}
- // Called from native code.
- private void goToSleepFromNative(long eventTime, int reason) {
- goToSleepInternal(eventTime, reason);
- }
-
private void goToSleepInternal(long eventTime, int reason) {
synchronized (mLock) {
if (goToSleepNoUpdateLocked(eventTime, reason)) {
@@ -958,14 +938,11 @@
break;
}
- sendPendingNotificationsLocked();
- mNotifier.onGoToSleepStarted(reason);
- mSendGoToSleepFinishedNotificationWhenReady = true;
-
mLastSleepTime = eventTime;
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_DOZING;
mSandmanSummoned = true;
+ setInteractiveStateLocked(false, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
@@ -1007,6 +984,7 @@
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_DREAMING;
mSandmanSummoned = true;
+ setInteractiveStateLocked(true, 0);
return true;
}
@@ -1025,9 +1003,27 @@
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
+ setInteractiveStateLocked(false, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
return true;
}
+ private void setInteractiveStateLocked(boolean interactive, int reason) {
+ if (mInteractive != interactive) {
+ finishInteractiveStateChangeLocked();
+
+ mInteractive = interactive;
+ mInteractiveChanging = true;
+ mNotifier.onInteractiveStateChangeStarted(interactive, reason);
+ }
+ }
+
+ private void finishInteractiveStateChangeLocked() {
+ if (mInteractiveChanging) {
+ mNotifier.onInteractiveStateChangeFinished(mInteractive);
+ mInteractiveChanging = false;
+ }
+ }
+
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
@@ -1071,7 +1067,7 @@
// Phase 3: Send notifications, if needed.
if (mDisplayReady) {
- sendPendingNotificationsLocked();
+ finishInteractiveStateChangeLocked();
}
// Phase 4: Update suspend blocker.
@@ -1080,17 +1076,6 @@
updateSuspendBlockerLocked();
}
- private void sendPendingNotificationsLocked() {
- if (mSendWakeUpFinishedNotificationWhenReady) {
- mSendWakeUpFinishedNotificationWhenReady = false;
- mNotifier.onWakeUpFinished();
- }
- if (mSendGoToSleepFinishedNotificationWhenReady) {
- mSendGoToSleepFinishedNotificationWhenReady = false;
- mNotifier.onGoToSleepFinished();
- }
- }
-
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
@@ -1210,48 +1195,45 @@
mWakeLockSummary |= WAKE_LOCK_CPU;
break;
case PowerManager.FULL_WAKE_LOCK:
- if (mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING) {
- mWakeLockSummary |= WAKE_LOCK_CPU
- | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
- }
- if (mWakefulness == WAKEFULNESS_AWAKE) {
- mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
- }
+ mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
- if (mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING) {
- mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
- }
- if (mWakefulness == WAKEFULNESS_AWAKE) {
- mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
- }
+ mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
- if (mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING) {
- mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
- }
- if (mWakefulness == WAKEFULNESS_AWAKE) {
- mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
- }
+ mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- if (mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING
- || mWakefulness == WAKEFULNESS_DOZING) {
- mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
- }
+ mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
break;
case PowerManager.DOZE_WAKE_LOCK:
- if (mWakefulness == WAKEFULNESS_DOZING) {
- mWakeLockSummary |= WAKE_LOCK_DOZE;
- }
+ mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
}
}
+ // Cancel wake locks that make no sense based on the current state.
+ if (mWakefulness != WAKEFULNESS_DOZING) {
+ mWakeLockSummary &= ~WAKE_LOCK_DOZE;
+ }
+ if (mWakefulness == WAKEFULNESS_ASLEEP
+ || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+ mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
+ | WAKE_LOCK_BUTTON_BRIGHT);
+ if (mWakefulness == WAKEFULNESS_ASLEEP) {
+ mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
+ }
+ }
+
+ // Infer implied wake locks where necessary based on the current state.
+ if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
+ } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+ mWakeLockSummary |= WAKE_LOCK_CPU;
+ }
+ }
+
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ wakefulnessToString(mWakefulness)
@@ -1269,12 +1251,14 @@
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
- if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
+ if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
+ | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
if (mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING) {
+ || mWakefulness == WAKEFULNESS_DREAMING
+ || mWakefulness == WAKEFULNESS_DOZING) {
final int screenOffTimeout = getScreenOffTimeoutLocked();
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
@@ -1598,8 +1582,6 @@
| DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
final int newScreenState = getDesiredScreenPowerStateLocked();
mDisplayPowerRequest.screenState = newScreenState;
- nativeSetPowerState(isScreenOnLocked(),
- newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
@@ -1681,7 +1663,7 @@
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
new DisplayManagerInternal.DisplayPowerCallbacks() {
- private boolean mBlanked;
+ private int mDisplayState = Display.STATE_UNKNOWN;
@Override
public void onStateChanged() {
@@ -1712,6 +1694,33 @@
}
@Override
+ public void onDisplayStateChange(int state) {
+ // This method is only needed to support legacy display blanking behavior
+ // where the display's power state is coupled to suspend or to the power HAL.
+ // The order of operations matters here.
+ synchronized (mLock) {
+ if (mDisplayState != state) {
+ mDisplayState = state;
+ if (state == Display.STATE_OFF) {
+ if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+ setHalInteractiveModeLocked(false);
+ }
+ if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(true);
+ }
+ } else {
+ if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(false);
+ }
+ if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+ setHalInteractiveModeLocked(true);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
public void acquireSuspendBlocker() {
mDisplaySuspendBlocker.acquire();
}
@@ -1722,37 +1731,9 @@
}
@Override
- public void blankAllDisplays() {
- synchronized (this) {
- mBlanked = true;
- mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
- if (!mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(false);
- }
- if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(true);
- }
- }
- }
-
- @Override
- public void unblankAllDisplays() {
- synchronized (this) {
- if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(false);
- }
- if (!mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(true);
- }
- mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
- mBlanked = false;
- }
- }
-
- @Override
public String toString() {
synchronized (this) {
- return "blanked=" + mBlanked;
+ return "state=" + Display.stateToString(mDisplayState);
}
}
};
@@ -1773,11 +1754,11 @@
// Disable auto-suspend if needed.
if (!autoSuspend) {
- if (mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(false);
+ if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(false);
}
- if (mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(true);
+ if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+ setHalInteractiveModeLocked(true);
}
}
@@ -1803,11 +1784,11 @@
// Enable auto-suspend if needed.
if (autoSuspend) {
- if (mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(false);
+ if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+ setHalInteractiveModeLocked(false);
}
- if (mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(true);
+ if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(true);
}
}
}
@@ -1834,42 +1815,32 @@
return false;
}
- private void setAutoSuspendModeLocked(boolean enable) {
- if (enable != mAutoSuspendModeEnabled) {
+ private void setHalAutoSuspendModeLocked(boolean enable) {
+ if (enable != mHalAutoSuspendModeEnabled) {
if (DEBUG) {
- Slog.d(TAG, "Setting auto-suspend mode to " + enable);
+ Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
}
- mAutoSuspendModeEnabled = enable;
+ mHalAutoSuspendModeEnabled = enable;
nativeSetAutoSuspend(enable);
}
}
- private void setInteractiveModeLocked(boolean enable) {
- if (enable != mInteractiveModeEnabled) {
+ private void setHalInteractiveModeLocked(boolean enable) {
+ if (enable != mHalInteractiveModeEnabled) {
if (DEBUG) {
- Slog.d(TAG, "Setting interactive mode to " + enable);
+ Slog.d(TAG, "Setting HAL interactive mode to " + enable);
}
- mInteractiveModeEnabled = enable;
+ mHalInteractiveModeEnabled = enable;
nativeSetInteractive(enable);
}
}
- private boolean isScreenOnInternal() {
+ private boolean isInteractiveInternal() {
synchronized (mLock) {
- // XXX This is a temporary hack to let certain parts of the system pretend the
- // screen is still on even when dozing and we would normally want to report
- // screen off. Will be removed when the window manager is modified to use
- // the true blanking state of the display.
- return isScreenOnLocked()
- || mWakefulness == WAKEFULNESS_DOZING;
+ return mInteractive;
}
}
- private boolean isScreenOnLocked() {
- return mWakefulness == WAKEFULNESS_AWAKE
- || mWakefulness == WAKEFULNESS_DREAMING;
- }
-
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
@@ -2090,6 +2061,7 @@
pw.println("Power Manager State:");
pw.println(" mDirty=0x" + Integer.toHexString(mDirty));
pw.println(" mWakefulness=" + wakefulnessToString(mWakefulness));
+ pw.println(" mInteractive=" + mInteractive);
pw.println(" mIsPowered=" + mIsPowered);
pw.println(" mPlugType=" + mPlugType);
pw.println(" mBatteryLevel=" + mBatteryLevel);
@@ -2099,8 +2071,8 @@
pw.println(" mProximityPositive=" + mProximityPositive);
pw.println(" mBootCompleted=" + mBootCompleted);
pw.println(" mSystemReady=" + mSystemReady);
- pw.println(" mAutoSuspendModeEnabled=" + mAutoSuspendModeEnabled);
- pw.println(" mInteactiveModeEnabled=" + mInteractiveModeEnabled);
+ pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
+ pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
@@ -2108,10 +2080,6 @@
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
- pw.println(" mSendWakeUpFinishedNotificationWhenReady="
- + mSendWakeUpFinishedNotificationWhenReady);
- pw.println(" mSendGoToSleepFinishedNotificationWhenReady="
- + mSendGoToSleepFinishedNotificationWhenReady);
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
pw.println(" mLastUserActivityTimeNoChangeLights="
+ TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
@@ -2121,10 +2089,10 @@
pw.println();
pw.println("Settings and Configuration:");
- pw.println(" mDecoupleAutoSuspendModeFromDisplayConfig="
- + mDecoupleAutoSuspendModeFromDisplayConfig);
- pw.println(" mDecoupleInteractiveModeFromDisplayConfig="
- + mDecoupleInteractiveModeFromDisplayConfig);
+ pw.println(" mDecoupleHalAutoSuspendModeFromDisplayConfig="
+ + mDecoupleHalAutoSuspendModeFromDisplayConfig);
+ pw.println(" mDecoupleHalInteractiveModeFromDisplayConfig="
+ + mDecoupleHalInteractiveModeFromDisplayConfig);
pw.println(" mWakeUpWhenPluggedOrUnpluggedConfig="
+ mWakeUpWhenPluggedOrUnpluggedConfig);
pw.println(" mSuspendWhenScreenOffDueToProximityConfig="
@@ -2725,10 +2693,10 @@
}
@Override // Binder call
- public boolean isScreenOn() {
+ public boolean isInteractive() {
final long ident = Binder.clearCallingIdentity();
try {
- return isScreenOnInternal();
+ return isInteractiveInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4aae5c1..b27c8d6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -355,17 +355,16 @@
/* Provides an opportunity for the window manager policy to intercept early key
* processing as soon as the key has been read from the device. */
@Override
- public int interceptKeyBeforeQueueing(
- KeyEvent event, int policyFlags, boolean isScreenOn) {
- return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+ return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
/* Provides an opportunity for the window manager policy to intercept early
* motion event processing when the screen is off since these events are normally
* dropped. */
@Override
- public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
- return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(whenNanos, policyFlags);
+ public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+ return mService.mPolicy.interceptWakeMotionBeforeQueueing(whenNanos, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key before
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b12ae4f..c24f53f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -24,6 +24,7 @@
import android.util.TimeUtils;
import android.view.IWindowId;
+import android.view.WindowContentFrameStats;
import com.android.internal.app.IBatteryStats;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
@@ -626,6 +627,8 @@
private final PointerEventDispatcher mPointerEventDispatcher;
+ private WindowContentFrameStats mTempWindowRenderStats;
+
final class DragInputEventReceiver extends InputEventReceiver {
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
@@ -10264,6 +10267,51 @@
return mSafeMode;
}
+ @Override
+ public boolean clearWindowContentFrameStats(IBinder token) {
+ if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+ "clearWindowContentFrameStats()")) {
+ throw new SecurityException("Requires FRAME_STATS permission");
+ }
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(token);
+ if (windowState == null) {
+ return false;
+ }
+ SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+ if (surfaceControl == null) {
+ return false;
+ }
+ return surfaceControl.clearContentFrameStats();
+ }
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+ if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+ "getWindowContentFrameStats()")) {
+ throw new SecurityException("Requires FRAME_STATS permission");
+ }
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(token);
+ if (windowState == null) {
+ return null;
+ }
+ SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+ if (surfaceControl == null) {
+ return null;
+ }
+ if (mTempWindowRenderStats == null) {
+ mTempWindowRenderStats = new WindowContentFrameStats();
+ }
+ WindowContentFrameStats stats = mTempWindowRenderStats;
+ if (!surfaceControl.getContentFrameStats(stats)) {
+ return null;
+ }
+ return stats;
+ }
+ }
+
void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
mPolicy.dump(" ", pw, args);
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
index a00aaa8..54c9755 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
@@ -204,6 +204,11 @@
} else {
ALOGV("Logical Address Allocation success: %d", addr);
mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));
+
+ // Broadcast <Report Physical Address> when a new logical address was allocated to let
+ // other devices discover the new logical device and its logical - physical address
+ // association.
+ sendReportPhysicalAddress();
}
return addr;
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b3247ff..4085991 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -71,7 +71,7 @@
jmethodID notifyANR;
jmethodID filterInputEvent;
jmethodID interceptKeyBeforeQueueing;
- jmethodID interceptMotionBeforeQueueingWhenScreenOff;
+ jmethodID interceptWakeMotionBeforeQueueing;
jmethodID interceptKeyBeforeDispatching;
jmethodID dispatchUnhandledKey;
jmethodID checkInjectEventsPermission;
@@ -189,6 +189,7 @@
void setSystemUiVisibility(int32_t visibility);
void setPointerSpeed(int32_t speed);
void setShowTouches(bool enabled);
+ void setInteractive(bool interactive);
void reloadCalibration();
/* --- InputReaderPolicyInterface implementation --- */
@@ -214,7 +215,6 @@
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
- virtual bool isKeyRepeatEnabled();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual nsecs_t interceptKeyBeforeDispatching(
@@ -262,14 +262,12 @@
wp<PointerController> pointerController;
} mLocked;
+ volatile bool mInteractive;
+
void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
void ensureSpriteControllerLocked();
- // Power manager interactions.
- bool isScreenOn();
- bool isScreenBright();
-
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
static inline JNIEnv* jniEnv() {
@@ -281,7 +279,7 @@
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
- mLooper(looper) {
+ mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
@@ -637,11 +635,6 @@
}
}
-bool NativeInputManager::isKeyRepeatEnabled() {
- // Only enable automatic key repeating when the screen is on.
- return isScreenOn();
-}
-
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
Vector<sp<InputWindowHandle> > windowHandles;
@@ -753,19 +746,15 @@
InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
}
+void NativeInputManager::setInteractive(bool interactive) {
+ mInteractive = interactive;
+}
+
void NativeInputManager::reloadCalibration() {
mInputManager->getReader()->requestRefreshConfiguration(
InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION);
}
-bool NativeInputManager::isScreenOn() {
- return android_server_PowerManagerService_isScreenOn();
-}
-
-bool NativeInputManager::isScreenBright() {
- return android_server_PowerManagerService_isScreenBright();
-}
-
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
JNIEnv *env, jfloatArray matrixArr) {
ScopedFloatArrayRO matrix(env, matrixArr);
@@ -841,18 +830,18 @@
// - Ignore untrusted events and pass them along.
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
+ if (mInteractive) {
+ policyFlags |= POLICY_FLAG_INTERACTIVE;
+ }
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
- bool isScreenOn = this->isScreenOn();
- bool isScreenBright = this->isScreenBright();
-
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
jint wmActions;
if (keyEventObj) {
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
- keyEventObj, policyFlags, isScreenOn);
+ keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
wmActions = 0;
}
@@ -863,16 +852,6 @@
wmActions = 0;
}
- if (!(policyFlags & POLICY_FLAG_INJECTED)) {
- if (!isScreenOn) {
- policyFlags |= POLICY_FLAG_WOKE_HERE;
- }
-
- if (!isScreenBright) {
- policyFlags |= POLICY_FLAG_BRIGHT_HERE;
- }
- }
-
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
@@ -885,24 +864,22 @@
// - No special filtering for injected events required at this time.
// - Filter normal events based on screen state.
// - For normal events brighten (but do not wake) the screen if currently dim.
+ if (mInteractive) {
+ policyFlags |= POLICY_FLAG_INTERACTIVE;
+ }
if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
- if (isScreenOn()) {
+ if (policyFlags & POLICY_FLAG_INTERACTIVE) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
-
- if (!isScreenBright()) {
- policyFlags |= POLICY_FLAG_BRIGHT_HERE;
- }
- } else {
+ } else if (policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED)) {
JNIEnv* env = jniEnv();
jint wmActions = env->CallIntMethod(mServiceObj,
- gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+ gServiceClassInfo.interceptWakeMotionBeforeQueueing,
when, policyFlags);
if (checkAndClearExceptionFromCallback(env,
- "interceptMotionBeforeQueueingWhenScreenOff")) {
+ "interceptWakeMotionBeforeQueueing")) {
wmActions = 0;
}
- policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
@@ -1285,6 +1262,13 @@
im->setShowTouches(enabled);
}
+static void nativeSetInteractive(JNIEnv* env,
+ jclass clazz, jlong ptr, jboolean interactive) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->setInteractive(interactive);
+}
+
static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->reloadCalibration();
@@ -1395,6 +1379,8 @@
(void*) nativeSetPointerSpeed },
{ "nativeSetShowTouches", "(JZ)V",
(void*) nativeSetShowTouches },
+ { "nativeSetInteractive", "(JZ)V",
+ (void*) nativeSetInteractive },
{ "nativeReloadCalibration", "(J)V",
(void*) nativeReloadCalibration },
{ "nativeVibrate", "(JI[JII)V",
@@ -1453,11 +1439,10 @@
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
- "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
+ "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
- GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
- clazz,
- "interceptMotionBeforeQueueingWhenScreenOff", "(JI)I");
+ GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz,
+ "interceptWakeMotionBeforeQueueing", "(JI)I");
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
"interceptKeyBeforeDispatching",
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index dbf5439..33e0bd7 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -42,8 +42,6 @@
// ----------------------------------------------------------------------------
static struct {
- jmethodID wakeUpFromNative;
- jmethodID goToSleepFromNative;
jmethodID userActivityFromNative;
} gPowerManagerServiceClassInfo;
@@ -52,10 +50,6 @@
static jobject gPowerManagerServiceObj;
static struct power_module* gPowerModule;
-static Mutex gPowerManagerLock;
-static bool gScreenOn;
-static bool gScreenBright;
-
static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
// Throttling interval for user activity calls.
@@ -73,16 +67,6 @@
return false;
}
-bool android_server_PowerManagerService_isScreenOn() {
- AutoMutex _l(gPowerManagerLock);
- return gScreenOn;
-}
-
-bool android_server_PowerManagerService_isScreenBright() {
- AutoMutex _l(gPowerManagerLock);
- return gScreenBright;
-}
-
void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
// Tell the power HAL when user activity occurs.
if (gPowerModule && gPowerModule->powerHint) {
@@ -114,28 +98,6 @@
}
}
-void android_server_PowerManagerService_wakeUp(nsecs_t eventTime) {
- if (gPowerManagerServiceObj) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
-
- env->CallVoidMethod(gPowerManagerServiceObj,
- gPowerManagerServiceClassInfo.wakeUpFromNative,
- nanoseconds_to_milliseconds(eventTime));
- checkAndClearExceptionFromCallback(env, "wakeUpFromNative");
- }
-}
-
-void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
- if (gPowerManagerServiceObj) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
-
- env->CallVoidMethod(gPowerManagerServiceObj,
- gPowerManagerServiceClassInfo.goToSleepFromNative,
- nanoseconds_to_milliseconds(eventTime), 0);
- checkAndClearExceptionFromCallback(env, "goToSleepFromNative");
- }
-}
-
// ----------------------------------------------------------------------------
static void nativeInit(JNIEnv* env, jobject obj) {
@@ -150,13 +112,6 @@
}
}
-static void nativeSetPowerState(JNIEnv* env,
- jclass clazz, jboolean screenOn, jboolean screenBright) {
- AutoMutex _l(gPowerManagerLock);
- gScreenOn = screenOn;
- gScreenBright = screenBright;
-}
-
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
@@ -207,8 +162,6 @@
/* name, signature, funcPtr */
{ "nativeInit", "()V",
(void*) nativeInit },
- { "nativeSetPowerState", "(ZZ)V",
- (void*) nativeSetPowerState },
{ "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
(void*) nativeAcquireSuspendBlocker },
{ "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
@@ -243,12 +196,6 @@
jclass clazz;
FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
- GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
- "wakeUpFromNative", "(J)V");
-
- GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz,
- "goToSleepFromNative", "(JI)V");
-
GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
"userActivityFromNative", "(JII)V");
@@ -256,8 +203,6 @@
for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
gLastEventTime[i] = LLONG_MIN;
}
- gScreenOn = true;
- gScreenBright = true;
gPowerManagerServiceObj = NULL;
gPowerModule = NULL;
return 0;
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index b48e546..f5fd3d6 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -24,11 +24,7 @@
namespace android {
-extern bool android_server_PowerManagerService_isScreenOn();
-extern bool android_server_PowerManagerService_isScreenBright();
extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
-extern void android_server_PowerManagerService_wakeUp(nsecs_t eventTime);
-extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
} // namespace android
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 8b9f718..8392672 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -216,7 +216,7 @@
expectLastCall().atLeastOnce();
// expect to answer screen status during systemReady()
- expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+ expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
expectCurrentTime();
@@ -331,7 +331,7 @@
verifyAndReset();
// now turn screen off and verify REJECT rule
- expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
+ expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
expectSetUidNetworkRules(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
@@ -341,7 +341,7 @@
verifyAndReset();
// and turn screen back on, verify ALLOW rule restored
- expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+ expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
expectSetUidNetworkRules(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
diff --git a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
index bf35db4..a0b2d1a 100644
--- a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
+++ b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
@@ -97,6 +97,7 @@
setLowProfile(true);
setFullscreen(true);
setContentView(R.layout.dream);
+ setScreenBright(false);
mAlarmClock = (TextView)findViewById(R.id.alarm_clock);
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 6ca1aa7..bb2bebf 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -46,8 +46,8 @@
android:rotation="46.757"
android:pivotX="162"
android:pivotY="173.5"
- android:fill="?attr/android:colorControlNormal"
- android:stroke="?attr/android:colorControlNormal"
+ android:fill="?android:attr/colorControlNormal"
+ android:stroke="?android:attr/colorControlNormal"
android:strokeWidth="3"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
@@ -56,7 +56,7 @@
<path
android:name="box3"
android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
- android:stroke="?attr/android:colorControlNormal"
+ android:stroke="?android:attr/colorControlNormal"
android:strokeWidth="10"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
@@ -65,7 +65,7 @@
<path
android:name="box4"
android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
- android:stroke="?attr/android:colorControlNormal"
+ android:stroke="?android:attr/colorControlNormal"
android:strokeWidth="30"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 743a26c..4dd1446 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -23,22 +23,11 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.IApplicationToken;
-import android.view.IInputFilter;
-import android.view.IOnKeyguardExitResult;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.IWindowSession;
-
-import java.util.List;
/**
* Basic implementation of {@link IWindowManager} so that {@link Display} (and
@@ -462,4 +451,16 @@
// TODO Auto-generated method stub
return false;
}
+
+ @Override
+ public boolean clearWindowContentFrameStats(IBinder token) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index b9f2ed9..4eb70aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -28,7 +28,7 @@
public class BridgePowerManager implements IPowerManager {
@Override
- public boolean isScreenOn() throws RemoteException {
+ public boolean isInteractive() throws RemoteException {
return true;
}