From 4a7ef23efecec9754918fb150f50bde2464d21e5 Mon Sep 17 00:00:00 2001
From: Mingguang Xu
Date: Thu, 3 Oct 2019 17:36:42 +0000
Subject: [PATCH 1/9] Revert "Wifi usability: Change the unit of the threshold
for tx/rx throughput from Mbps to Kbps"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 078fe45552425c18aa8052da0ae3c9205fa5c309.
Reason for revert: This change introduced a bug and it completely changed the functionality of WiFi data stall detection, e.g., high Tx link speed can easily trigger data stall. We would like to roll back them to restore the normal functionality of Wifi data stall detection.
Bug: 141995185
Change-Id: I024808b580955545b084112c4b14921f038b595f
Merged-In: I078d28ed81a84e32aaece839a51590364a974481
(cherry picked from commit 038345da61cb9d560486386a1c46c18c870e597c)
---
proto/src/wifi.proto | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index fbf6ca52f11c6..353a18756ca2b 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1798,12 +1798,12 @@ message ExperimentValues {
optional int32 data_stall_duration_ms = 5;
// Threshold of Tx throughput below which to trigger a data stall
- // measured in Kbps
- optional int32 data_stall_tx_tput_thr_kbps = 6;
+ // measured in Mbps
+ optional int32 data_stall_tx_tput_thr_mbps = 6;
// Threshold of Rx throughput below which to trigger a data stall
- // measured in Kbps
- optional int32 data_stall_rx_tput_thr_kbps = 7;
+ // measured in Mbps
+ optional int32 data_stall_rx_tput_thr_mbps = 7;
// Threshold of Tx packet error rate above which to trigger a data stall
// in percentage
From dedeee88f4c5f2f8c646a73f0dd09e277bdb1dcd Mon Sep 17 00:00:00 2001
From: Todd Kennedy
Date: Fri, 20 Sep 2019 13:45:15 -0700
Subject: [PATCH 2/9] Only allow INSTALL_ALLOW_TEST from shell or root
Bug: 141169173
Test: Manual. App can't be installed as test-only
Change-Id: Ib6dcca7901aa549d620448c0165c22270a3042be
(cherry picked from commit b5afc874838857bac783555bd665ac3bdd7966f9)
---
.../core/java/com/android/server/pm/PackageInstallerService.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index e75f545eafaa5..0329e2c5ed45b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -491,6 +491,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;
+ params.installFlags &= ~PackageManager.INSTALL_ALLOW_TEST;
params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0
&& !mPm.isCallerVerifier(callingUid)) {
From 1ba03516d7a64bf1e2394de2ffe4db9c086f81de Mon Sep 17 00:00:00 2001
From: Svet Ganov
Date: Mon, 23 Sep 2019 21:32:08 -0700
Subject: [PATCH 3/9] Update PermissionChecker usages to avoid unnecessary
attribution.
We had accidental usages of the PermissionChecker for cases where no
private data was provided to the app but the checkPermission API on
the latter also did blame data access on the app. The PermissionChecker
was designed to handle IPC calls and not for generic API checks.
To avoid future accidental incorrect PermissionChecker usages this
change renames the existing APIs of the latter to clearly indicate
that they should be used for data delivery and also adds sibling
methods for doing the same permission checks for preflight purposes.
Also the documentation is improved to furhter assist developers.
In addition, this change fixes accidental permission checker usages
that blame when they should not by using the new preflight flavor
of the permission check APIs.
Test:
atest com.android.settingslib.location.RecentLocationAppsTest
atest CtsPermissionTestCases
added: LocationAccessCheckTest#notificationOnlyForAccessesSinceFeatureWasEnabled
added: LocationAccessCheckTest#noNotificationIfFeatureDisabled
added: LocationAccessCheckTest#noNotificationIfBlamerNotSystemOrLocationProvider
added: LocationAccessCheckTest#testOpeningLocationSettingsDoesNotTriggerAccess
bug:141028068
Merged-In: I65c71569d0dd8a40bc6fecabb22c5373dd6e806e
Change-Id: I65c71569d0dd8a40bc6fecabb22c5373dd6e806e
(cherry picked from commit 7fe065eb660cfe8ae54f8cd1e1e615f47d7b311c)
---
.../android/content/PermissionChecker.java | 360 +++++++++++++++---
.../android/speech/RecognitionService.java | 24 +-
.../location/RecentLocationAccesses.java | 5 +-
.../location/RecentLocationApps.java | 6 +-
.../server/role/RoleManagerService.java | 3 +-
.../DevicePolicyManagerService.java | 11 +-
6 files changed, 329 insertions(+), 80 deletions(-)
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 6fe6e991fb1e7..95286e4bc1dbf 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -50,6 +50,19 @@ import java.lang.annotation.RetentionPolicy;
* permission model for which the user had disabled the "permission"
* which is achieved by disallowing the corresponding app op.
*
+ *
+ * This class has two types of methods and you should be careful which
+ * type to call based on whether permission protected data is being
+ * passed to the app or you are just checking whether the app holds a
+ * permission. The reason is that a permission check requires checking
+ * the runtime permission and if it is granted checking the corresponding
+ * app op as for apps not supporting the runtime mode we never revoke
+ * permissions but disable app ops. Since there are two types of app op
+ * checks, one that does not leave a record an action was performed and
+ * another the does, one needs to call the preflight flavor of the checks
+ * named xxxForPreflight only if no private data is being delivered but
+ * a permission check is what is needed and the xxxForDataDelivery where
+ * the permission check is right before private data delivery.
*
* @hide
*/
@@ -63,6 +76,9 @@ public final class PermissionChecker {
/** Permission result: The permission is denied because the app op is not allowed. */
public static final int PERMISSION_DENIED_APP_OP = PackageManager.PERMISSION_DENIED - 1;
+ /** Constant when the PID for which we check permissions is unknown. */
+ public static final int PID_UNKNOWN = -1;
+
/** @hide */
@IntDef({PERMISSION_GRANTED,
PERMISSION_DENIED,
@@ -78,6 +94,57 @@ public final class PermissionChecker {
* Checks whether a given package in a UID and PID has a given permission
* and whether the app op that corresponds to this permission is allowed.
*
+ * NOTE: Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
+ * is not known.
+ * @param uid The uid for which to check.
+ * @param packageName The package name for which to check. If null the
+ * the first package for the calling UID will be used.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkPermissionForPreflight(Context, String, int, int, String)
+ */
+ @PermissionResult
+ public static int checkPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission, int pid, int uid, @Nullable String packageName) {
+ return checkPermissionCommon(context, permission, pid, uid, packageName,
+ true /*forDataDelivery*/);
+ }
+
+ /**
+ * Checks whether a given package in a UID and PID has a given permission
+ * and whether the app op that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * preflight point where you will not deliver the permission protected data
+ * to clients but schedule permission data delivery, apps register listeners,
+ * etc.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have location
+ * permission (if app has only foreground location the grant state depends on the app's
+ * fg/gb state) and this check will not leave a trace that permission protected data
+ * was delivered. When you are about to deliver the location data to a registered
+ * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
+ * int, int, String)} which will evaluate the permission access based on the current
+ * fg/bg state of the app and leave a record that the data was accessed.
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
* @param pid The process id for which to check.
@@ -86,10 +153,229 @@ public final class PermissionChecker {
* the first package for the calling UID will be used.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkPermissionForDataDelivery(Context, String, int, int, String)
*/
@PermissionResult
- public static int checkPermission(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName) {
+ public static int checkPermissionForPreflight(@NonNull Context context,
+ @NonNull String permission, int pid, int uid, @Nullable String packageName) {
+ return checkPermissionCommon(context, permission, pid, uid, packageName,
+ false /*forDataDelivery*/);
+ }
+
+ /**
+ * Checks whether your app has a given permission and whether the app op
+ * that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkSelfPermissionForPreflight(Context, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method
+ * which will evaluate the permission access based on the current fg/bg state of the
+ * app and leave a record that the data was accessed.
+ *
+ *
This API assumes the the {@link Binder#getCallingUid()} is the same as
+ * {@link Process#myUid()}.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkSelfPermissionForPreflight(Context, String)
+ */
+ @PermissionResult
+ public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission) {
+ return checkPermissionForDataDelivery(context, permission, Process.myPid(),
+ Process.myUid(), context.getPackageName());
+ }
+
+ /**
+ * Checks whether your app has a given permission and whether the app op
+ * that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * preflight point where you will not deliver the permission protected data
+ * to clients but schedule permission data delivery, apps register listeners,
+ * etc.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have location
+ * permission (if app has only foreground location the grant state depends on the
+ * app's fg/gb state) and this check will not leave a trace that permission protected
+ * data was delivered. When you are about to deliver the location data to a registered
+ * listener you should use this method which will evaluate the permission access based
+ * on the current fg/bg state of the app and leave a record that the data was accessed.
+ *
+ *
This API assumes the the {@link Binder#getCallingUid()} is the same as
+ * {@link Process#myUid()}.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkSelfPermissionForDataDelivery(Context, String)
+ */
+ @PermissionResult
+ public static int checkSelfPermissionForPreflight(@NonNull Context context,
+ @NonNull String permission) {
+ return checkPermissionForPreflight(context, permission, Process.myPid(),
+ Process.myUid(), context.getPackageName());
+ }
+
+ /**
+ * Checks whether the IPC you are handling has a given permission and whether
+ * the app op that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @param packageName The package name making the IPC. If null the
+ * the first package for the calling UID will be used.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkCallingPermissionForPreflight(Context, String, String)
+ */
+ @PermissionResult
+ public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission, @Nullable String packageName) {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return PERMISSION_DENIED;
+ }
+ return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+ Binder.getCallingUid(), packageName);
+ }
+
+ /**
+ * Checks whether the IPC you are handling has a given permission and whether
+ * the app op that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * preflight point where you will not deliver the permission protected data
+ * to clients but schedule permission data delivery, apps register listeners,
+ * etc.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have location
+ * permission (if app has only foreground location the grant state depends on the app's
+ * fg/gb state) and this check will not leave a trace that permission protected data
+ * was delivered. When you are about to deliver the location data to a registered
+ * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+ * String)} which will evaluate the permission access based on the current fg/bg state
+ * of the app and leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @param packageName The package name making the IPC. If null the
+ * the first package for the calling UID will be used.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkCallingPermissionForDataDelivery(Context, String, String)
+ */
+ @PermissionResult
+ public static int checkCallingPermissionForPreflight(@NonNull Context context,
+ @NonNull String permission, @Nullable String packageName) {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return PERMISSION_DENIED;
+ }
+ return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+ Binder.getCallingUid(), packageName);
+ }
+
+ /**
+ * Checks whether the IPC you are handling or your app has a given permission
+ * and whether the app op that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * point where you will deliver the permission protected data to clients.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)}
+ * to determine if the app has or may have location permission (if app has only foreground
+ * location the grant state depends on the app's fg/gb state) and this check will not
+ * leave a trace that permission protected data was delivered. When you are about to
+ * deliver the location data to a registered listener you should use this method which
+ * will evaluate the permission access based on the current fg/bg state of the app and
+ * leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkCallingOrSelfPermissionForPreflight(Context, String)
+ */
+ @PermissionResult
+ public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
+ @NonNull String permission) {
+ String packageName = (Binder.getCallingPid() == Process.myPid())
+ ? context.getPackageName() : null;
+ return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
+ Binder.getCallingUid(), packageName);
+ }
+
+ /**
+ * Checks whether the IPC you are handling or your app has a given permission
+ * and whether the app op that corresponds to this permission is allowed.
+ *
+ * NOTE: Use this method only for permission checks at the
+ * preflight point where you will not deliver the permission protected data
+ * to clients but schedule permission data delivery, apps register listeners,
+ * etc.
+ *
+ *
For example, if an app registers a location listener it should have the location
+ * permission but no data is actually sent to the app at the moment of registration
+ * and you should use this method to determine if the app has or may have location
+ * permission (if app has only foreground location the grant state depends on the
+ * app's fg/gb state) and this check will not leave a trace that permission protected
+ * data was delivered. When you are about to deliver the location data to a registered
+ * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
+ * String)} which will evaluate the permission access based on the current fg/bg state
+ * of the app and leave a record that the data was accessed.
+ *
+ * @param context Context for accessing resources.
+ * @param permission The permission to check.
+ * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+ * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ *
+ * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String)
+ */
+ @PermissionResult
+ public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
+ @NonNull String permission) {
+ String packageName = (Binder.getCallingPid() == Process.myPid())
+ ? context.getPackageName() : null;
+ return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
+ Binder.getCallingUid(), packageName);
+ }
+
+ private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
+ int pid, int uid, @Nullable String packageName, boolean forDataDelivery) {
if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
return PERMISSION_DENIED;
}
@@ -108,68 +394,18 @@ public final class PermissionChecker {
packageName = packageNames[0];
}
- if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) {
- return PERMISSION_DENIED_APP_OP;
+ if (forDataDelivery) {
+ if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid)
+ != AppOpsManager.MODE_ALLOWED) {
+ return PERMISSION_DENIED_APP_OP;
+ }
+ } else {
+ final int mode = appOpsManager.unsafeCheckOpRawNoThrow(op, uid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED && mode != AppOpsManager.MODE_FOREGROUND) {
+ return PERMISSION_DENIED_APP_OP;
+ }
}
return PERMISSION_GRANTED;
}
-
- /**
- * Checks whether your app has a given permission and whether the app op
- * that corresponds to this permission is allowed.
- *
- *
This API assumes the the {@link Binder#getCallingUid()} is the same as
- * {@link Process#myUid()}.
- *
- * @param context Context for accessing resources.
- * @param permission The permission to check.
- * @return The permission check result which is either {@link #PERMISSION_GRANTED}
- * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
- */
- @PermissionResult
- public static int checkSelfPermission(@NonNull Context context,
- @NonNull String permission) {
- return checkPermission(context, permission, Process.myPid(),
- Process.myUid(), context.getPackageName());
- }
-
- /**
- * Checks whether the IPC you are handling has a given permission and whether
- * the app op that corresponds to this permission is allowed.
- *
- * @param context Context for accessing resources.
- * @param permission The permission to check.
- * @param packageName The package name making the IPC. If null the
- * the first package for the calling UID will be used.
- * @return The permission check result which is either {@link #PERMISSION_GRANTED}
- * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
- */
- @PermissionResult
- public static int checkCallingPermission(@NonNull Context context,
- @NonNull String permission, @Nullable String packageName) {
- if (Binder.getCallingPid() == Process.myPid()) {
- return PERMISSION_DENIED;
- }
- return checkPermission(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName);
- }
-
- /**
- * Checks whether the IPC you are handling or your app has a given permission
- * and whether the app op that corresponds to this permission is allowed.
- *
- * @param context Context for accessing resources.
- * @param permission The permission to check.
- * @return The permission check result which is either {@link #PERMISSION_GRANTED}
- * or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
- */
- @PermissionResult
- public static int checkCallingOrSelfPermission(@NonNull Context context,
- @NonNull String permission) {
- String packageName = (Binder.getCallingPid() == Process.myPid())
- ? context.getPackageName() : null;
- return checkPermission(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName);
- }
}
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 70dfef574ca53..fb13c1f5dde3b 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -170,13 +170,23 @@ public abstract class RecognitionService extends Service {
* Checks whether the caller has sufficient permissions
*
* @param listener to send the error message to in case of error
+ * @param forDataDelivery If the permission check is for delivering the sensitive data.
* @return {@code true} if the caller has enough permissions, {@code false} otherwise
*/
- private boolean checkPermissions(IRecognitionListener listener) {
+ private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) {
if (DBG) Log.d(TAG, "checkPermissions");
- if (PermissionChecker.checkCallingOrSelfPermission(this,
- android.Manifest.permission.RECORD_AUDIO) == PermissionChecker.PERMISSION_GRANTED) {
- return true;
+ if (forDataDelivery) {
+ if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this,
+ android.Manifest.permission.RECORD_AUDIO)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ return true;
+ }
+ } else {
+ if (PermissionChecker.checkCallingOrSelfPermissionForPreflight(this,
+ android.Manifest.permission.RECORD_AUDIO)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ return true;
+ }
}
try {
Log.e(TAG, "call for recognition service without RECORD_AUDIO permissions");
@@ -342,7 +352,7 @@ public abstract class RecognitionService extends Service {
public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener)) {
+ if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_START_LISTENING, service.new StartListeningArgs(
recognizerIntent, listener, Binder.getCallingUid())));
@@ -353,7 +363,7 @@ public abstract class RecognitionService extends Service {
public void stopListening(IRecognitionListener listener) {
if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener)) {
+ if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_STOP_LISTENING, listener));
}
@@ -363,7 +373,7 @@ public abstract class RecognitionService extends Service {
public void cancel(IRecognitionListener listener) {
if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener)) {
+ if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_CANCEL, listener));
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index ea39317fb045b..81ca9eaf8e36b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -111,8 +111,9 @@ public class RecentLocationAccesses {
for (int op : LOCATION_OPS) {
final String permission = AppOpsManager.opToPermission(op);
final int permissionFlags = pm.getPermissionFlags(permission, packageName, user);
- if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName)
- == PermissionChecker.PERMISSION_GRANTED) {
+ if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+ PermissionChecker.PID_UNKNOWN, uid, packageName)
+ == PermissionChecker.PERMISSION_GRANTED) {
if ((permissionFlags
& PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) {
showApp = false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 60c9984e5ed4c..104cc8f9841c2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -110,9 +110,9 @@ public class RecentLocationApps {
final String permission = AppOpsManager.opToPermission(op);
final int permissionFlags = pm.getPermissionFlags(permission, packageName,
user);
- if (PermissionChecker.checkPermission(mContext, permission, -1, uid,
- packageName)
- == PermissionChecker.PERMISSION_GRANTED) {
+ if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+ PermissionChecker.PID_UNKNOWN, uid, packageName)
+ == PermissionChecker.PERMISSION_GRANTED) {
if ((permissionFlags
& PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
== 0) {
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index d66803b2cbe97..fff9ec7f02c58 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -49,7 +49,6 @@ import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManagerInternal;
-import android.provider.Telephony;
import android.service.sms.FinancialSmsService;
import android.telephony.IFinancialSmsCallback;
import android.text.TextUtils;
@@ -682,7 +681,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
@Override
public void getSmsMessagesForFinancialApp(
String callingPkg, Bundle params, IFinancialSmsCallback callback) {
- int mode = PermissionChecker.checkCallingOrSelfPermission(
+ int mode = PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(
getContext(),
AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e5518d05e9c5a..37931be4eb10f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11830,10 +11830,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
try {
int uid = packageManager.getPackageUidAsUser(packageName,
user.getIdentifier());
-
- // TODO: Prevent noting the app-op
- granted = PermissionChecker.checkPermission(mContext, permission, -1,
- uid, packageName);
+ if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
+ PermissionChecker.PID_UNKNOWN, uid, packageName)
+ != PermissionChecker.PERMISSION_GRANTED) {
+ granted = PackageManager.PERMISSION_DENIED;
+ } else {
+ granted = PackageManager.PERMISSION_GRANTED;
+ }
} catch (NameNotFoundException e) {
throw new RemoteException(
"Cannot check if " + permission + "is a runtime permission", e,
From 055976434b5d0ec5f6a3746124f4e81aecf8a426 Mon Sep 17 00:00:00 2001
From: Evan Laird
Date: Mon, 5 Aug 2019 17:11:54 -0400
Subject: [PATCH 4/9] Force FGS notifications to show for a minimum time
It's possible for a service to do a start/stop foreground and cause a
couple of things to happen:
NotificationManagerService will enqueue a EnqueueNotificationRunnable,
post a PostNotificationRunnable (for the startForeground), and then also
enqueue a CancelNotificationRunnable. There is some racy behavior here
in that the cancel runnable can get triggered in between enqueue and
post runnables. If the cancel happens first, then
NotificationListenerServices will never get the message.
This behavior is technically allowed, however for foreground services we
want to ensure that there is a minmum amount of time that notification
listeners are aware of the foreground service so that (for instance) the
FGS notification can be shown.
This CL does two things to mitigate this problem:
1. Introduce checking in the CancelNotificationRunnable such that it
will not cancel until after PostNotificationRunnable has finished
executing.
2. Introduce a NotificationLifetimeExtender method that will allow a
lifetime extender to manage the lifetime of a notification that has been
enqueued but not inflated yet.
Bug: 119041698
Test: atest NotificationManagerServiceTest
Test: atest ForegroundServiceNotificationListenerTest
Change-Id: I0680034ed9315aa2c05282524d48faaed066ebd0
Merged-In: I0680034ed9315aa2c05282524d48faaed066ebd0
(cherry picked from commit 5136eefeb3e343ad2a487296063d19e01ea554e0)
---
.../ForegroundServiceLifetimeExtender.java | 90 +++++++++++++++++++
...ForegroundServiceNotificationListener.java | 3 +
.../NotificationLifetimeExtender.java | 12 +++
.../NotificationEntryManager.java | 20 ++++-
.../phone/StatusBarNotificationPresenter.java | 2 +-
...ForegroundServiceLifetimeExtenderTest.java | 82 +++++++++++++++++
.../NotificationManagerService.java | 12 ++-
.../NotificationManagerServiceTest.java | 14 +++
8 files changed, 229 insertions(+), 6 deletions(-)
create mode 100644 packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
create mode 100644 packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
new file mode 100644
index 0000000000000..05acdd080aa53
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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.systemui;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.NotificationLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+/**
+ * Extends the lifetime of foreground notification services such that they show for at least
+ * five seconds
+ */
+public class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender {
+
+ private static final String TAG = "FGSLifetimeExtender";
+ @VisibleForTesting
+ static final int MIN_FGS_TIME_MS = 5000;
+
+ private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback;
+ private ArraySet mManagedEntries = new ArraySet<>();
+ private Handler mHandler = new Handler(Looper.getMainLooper());
+
+ public ForegroundServiceLifetimeExtender() {
+ }
+
+ @Override
+ public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) {
+ mNotificationSafeToRemoveCallback = callback;
+ }
+
+ @Override
+ public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
+ if ((entry.notification.getNotification().flags
+ & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
+ return false;
+ }
+
+ long currentTime = System.currentTimeMillis();
+ return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS;
+ }
+
+ @Override
+ public boolean shouldExtendLifetimeForPendingNotification(
+ @NonNull NotificationEntry entry) {
+ return shouldExtendLifetime(entry);
+ }
+
+ @Override
+ public void setShouldManageLifetime(
+ @NonNull NotificationEntry entry, boolean shouldManage) {
+ if (!shouldManage) {
+ mManagedEntries.remove(entry);
+ return;
+ }
+
+ mManagedEntries.add(entry);
+
+ Runnable r = () -> {
+ if (mManagedEntries.contains(entry)) {
+ mManagedEntries.remove(entry);
+ if (mNotificationSafeToRemoveCallback != null) {
+ mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key);
+ }
+ }
+ };
+ long delayAmt = MIN_FGS_TIME_MS
+ - (System.currentTimeMillis() - entry.notification.getPostTime());
+ mHandler.postDelayed(r, delayAmt);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 96b62ac918ab4..0162deb55143f 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -66,6 +66,9 @@ public class ForegroundServiceNotificationListener {
removeNotification(entry.notification);
}
});
+
+ notificationEntryManager.addNotificationLifetimeExtender(
+ new ForegroundServiceLifetimeExtender());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
index 0f295ba75fe40..48e2923c97d99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
@@ -26,6 +26,18 @@ public interface NotificationLifetimeExtender {
*/
boolean shouldExtendLifetime(@NonNull NotificationEntry entry);
+ /**
+ * It's possible that a notification was canceled before it ever became visible. This callback
+ * gives lifetime extenders a chance to make sure it shows up. For example if a foreground
+ * service is canceled too quickly but we still want to make sure a FGS notification shows.
+ * @param pendingEntry the canceled (but pending) entry
+ * @return true if the notification lifetime should be extended
+ */
+ default boolean shouldExtendLifetimeForPendingNotification(
+ @NonNull NotificationEntry pendingEntry) {
+ return false;
+ }
+
/**
* Sets whether or not the lifetime should be managed by the extender. In practice, if
* shouldManage is true, this is where the extender starts managing the entry internally and is
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index f8fef7d4778c8..a37367e4bb255 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -281,11 +281,25 @@ public class NotificationEntryManager implements
}
final NotificationEntry entry = mNotificationData.get(key);
-
- abortExistingInflation(key);
-
boolean lifetimeExtended = false;
+ // Notification was canceled before it got inflated
+ if (entry == null) {
+ NotificationEntry pendingEntry = mPendingNotifications.get(key);
+ if (pendingEntry != null) {
+ for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
+ if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) {
+ extendLifetime(pendingEntry, extender);
+ lifetimeExtended = true;
+ }
+ }
+ }
+ }
+
+ if (!lifetimeExtended) {
+ abortExistingInflation(key);
+ }
+
if (entry != null) {
// If a manager needs to keep the notification around for whatever reason, we
// keep the notification
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index a870590c08ac7..069219802cc3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -224,7 +224,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mVisualStabilityManager.setUpWithPresenter(this);
mGutsManager.setUpWithPresenter(this,
notifListContainer, mCheckSaveListener, mOnSettingsClickListener);
- // ForegroundServiceControllerListener adds its listener in its constructor
+ // ForegroundServiceNotificationListener adds its listener in its constructor
// but we need to request it here in order for it to be instantiated.
// TODO: figure out how to do this correctly once Dependency.get() is gone.
Dependency.get(ForegroundServiceNotificationListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java
new file mode 100644
index 0000000000000..b1dabdda2241b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 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.systemui;
+
+import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ForegroundServiceLifetimeExtenderTest extends SysuiTestCase {
+ private ForegroundServiceLifetimeExtender mExtender = new ForegroundServiceLifetimeExtender();
+ private StatusBarNotification mSbn;
+ private NotificationEntry mEntry;
+ private Notification mNotif;
+
+ @Before
+ public void setup() {
+ mNotif = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text")
+ .build();
+
+ mSbn = mock(StatusBarNotification.class);
+ when(mSbn.getNotification()).thenReturn(mNotif);
+
+ mEntry = new NotificationEntry(mSbn);
+ }
+
+ @Test
+ public void testShouldExtendLifetime_should_foreground() {
+ // Extend the lifetime of a FGS notification iff it has not been visible
+ // for the minimum time
+ mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+ when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis());
+ assertTrue(mExtender.shouldExtendLifetime(mEntry));
+ }
+
+ @Test
+ public void testShouldExtendLifetime_shouldNot_foreground() {
+ mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+ when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1);
+ assertFalse(mExtender.shouldExtendLifetime(mEntry));
+ }
+
+ @Test
+ public void testShouldExtendLifetime_shouldNot_notForeground() {
+ mNotif.flags = 0;
+ when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1);
+ assertFalse(mExtender.shouldExtendLifetime(mEntry));
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c8d0682437885..3eb442f9bdda1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5343,8 +5343,16 @@ public class NotificationManagerService extends SystemService {
}
synchronized (mNotificationLock) {
- // Look for the notification, searching both the posted and enqueued lists.
- NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
+ // If the notification is currently enqueued, repost this runnable so it has a
+ // chance to notify listeners
+ if ((findNotificationByListLocked(mEnqueuedNotifications, mPkg, mTag, mId, mUserId))
+ != null) {
+ mHandler.post(this);
+ return;
+ }
+ // Look for the notification in the posted list, since we already checked enqueued.
+ NotificationRecord r =
+ findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId);
if (r != null) {
// The notification was found, check if it should be removed.
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index dc5edcd815861..6c91e2f52f0c5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1016,6 +1016,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(0, mService.getNotificationRecordCount());
}
+ @Test
+ public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
+ throws Exception {
+ final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+ sbn.getNotification().flags =
+ Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
+ waitForIdle();
+ verify(mListeners, times(1)).notifyPostedLocked(any(), any());
+ verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
+ }
+
@Test
public void testUserInitiatedClearAll_noLeak() throws Exception {
final NotificationRecord n = generateNotificationRecord(
From 17d308d142011046c6945ba84706eace327b0f06 Mon Sep 17 00:00:00 2001
From: Mady Mellor
Date: Mon, 7 Oct 2019 10:25:44 -0700
Subject: [PATCH 5/9] DO NOT MERGE Update setting to be bubbles not badging
Test: atest NotificationMangerTest NotificationManagerServiceTest
Fixes: 142166809
Change-Id: I3ac5410a5185ef78cb0f90d05738191efca02de8
(cherry picked from commit 8527dcb20bce188766985cedfd5553e22808ff17)
---
.../android/server/notification/NotificationManagerService.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3eb442f9bdda1..35268fe0da044 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1450,7 +1450,7 @@ public class NotificationManagerService extends SystemService {
} else {
// Secure => Global
Settings.Secure.putInt(resolver,
- Settings.Secure.NOTIFICATION_BADGING,
+ Settings.Secure.NOTIFICATION_BUBBLES,
globalSettingValue);
}
}
From cac03faf1a82f701b6a614e5c02fb2d14b6d4be2 Mon Sep 17 00:00:00 2001
From: Lucas Dupin
Date: Wed, 25 Sep 2019 13:39:21 -0700
Subject: [PATCH 6/9] Keep interrupts on when in battery saver mode
Battery saver was completely aborting the doze service, disabling
all interrupts. This is not ideal since it impacts the user journey,
especially when using face auth.
From now on the screen will still be off, but DozeService will be
retained, in order to receive sensor events.
Test: w/ battery saver: lift, tap, and observe aod being off
Test: w/ battery saver: receive notification, no HUN.
Test: w/o battery saver: lift, tap, and observe aod being on
Test: w/o battery saver: receive notification, HUN is received.
Fixes: 134157254
Change-Id: I9b713c78857c4e4c22d8d9bfff165b1b51dfd804
Merged-In: I9b713c78857c4e4c22d8d9bfff165b1b51dfd804
(cherry picked from commit 6edeb187015a04e7ff6a8f06275336b7e4ac82e7)
---
.../CarNotificationInterruptionStateProvider.java | 6 ++++--
.../statusbar/car/CarBatteryController.java | 5 +++++
.../src/com/android/systemui/doze/DozeFactory.java | 3 ++-
.../src/com/android/systemui/doze/DozeMachine.java | 9 ++++++++-
.../com/android/systemui/doze/DozeTriggers.java | 5 ++---
.../src/com/android/systemui/doze/DozeUi.java | 3 ++-
.../NotificationInterruptionStateProvider.java | 14 +++++++++++++-
.../statusbar/policy/BatteryController.java | 4 +---
.../systemui/bubbles/BubbleControllerTest.java | 9 ++++++---
.../com/android/systemui/doze/DozeMachineTest.java | 5 +++--
.../NotificationInterruptionStateProviderTest.java | 14 +++++++++-----
.../systemui/statusbar/phone/StatusBarTest.java | 9 ++++++---
.../utils/leaks/FakeBatteryController.java | 5 +++++
13 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
index afd722ba00914..447e579ece429 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
@@ -22,6 +22,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -34,8 +35,9 @@ public class CarNotificationInterruptionStateProvider extends
@Inject
public CarNotificationInterruptionStateProvider(Context context,
NotificationFilter filter,
- StatusBarStateController stateController) {
- super(context, filter, stateController);
+ StatusBarStateController stateController,
+ BatteryController batteryController) {
+ super(context, filter, stateController, batteryController);
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
index 58f80a4ed9680..d79849ccafc63 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
@@ -257,6 +257,11 @@ public class CarBatteryController extends BroadcastReceiver implements BatteryCo
return false;
}
+ @Override
+ public boolean isAodPowerSave() {
+ return false;
+ }
+
private void notifyBatteryLevelChanged() {
for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) {
mChangeCallbacks.get(i)
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 90cb05a8e6ee1..0e124e48f165c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -33,6 +33,7 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -64,7 +65,7 @@ public class DozeFactory {
params);
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
- wakefulnessLifecycle);
+ wakefulnessLifecycle, Dependency.get(BatteryController.class));
machine.setParts(new DozeMachine.Part[]{
new DozePauser(handler, machine, alarmManager, params.getPolicy()),
new DozeFalsingManagerAdapter(falsingManager),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 93a51cc20db2a..7f2d52780a239 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -27,6 +27,7 @@ import com.android.internal.util.Preconditions;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -121,6 +122,7 @@ public class DozeMachine {
private final WakeLock mWakeLock;
private final AmbientDisplayConfiguration mConfig;
private final WakefulnessLifecycle mWakefulnessLifecycle;
+ private final BatteryController mBatteryController;
private Part[] mParts;
private final ArrayList mQueuedRequests = new ArrayList<>();
@@ -129,11 +131,13 @@ public class DozeMachine {
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
- WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle) {
+ WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle,
+ BatteryController batteryController) {
mDozeService = service;
mConfig = config;
mWakefulnessLifecycle = wakefulnessLifecycle;
mWakeLock = wakeLock;
+ mBatteryController = batteryController;
}
/** Initializes the set of {@link Part}s. Must be called exactly once after construction. */
@@ -316,6 +320,9 @@ public class DozeMachine {
Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
return mState;
}
+ if (requestedState == State.DOZE_AOD && mBatteryController.isAodPowerSave()) {
+ return State.DOZE;
+ }
if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index bab64db4519c1..6199a0deb31ff 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -345,7 +345,6 @@ public class DozeTriggers implements DozeMachine.Part {
private void checkTriggersAtInit() {
if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
- || mDozeHost.isPowerSaveActive()
|| mDozeHost.isBlockingDoze()
|| !mDozeHost.isProvisioned()) {
mMachine.requestState(DozeMachine.State.FINISH);
@@ -574,8 +573,8 @@ public class DozeTriggers implements DozeMachine.Part {
@Override
public void onPowerSaveChanged(boolean active) {
- if (active) {
- mMachine.requestState(DozeMachine.State.FINISH);
+ if (mDozeHost.isPowerSaveActive()) {
+ mMachine.requestState(DozeMachine.State.DOZE);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 1f33af8c3f559..3869e77294e74 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -83,7 +83,8 @@ public class DozeUi implements DozeMachine.Part {
*/
private void updateAnimateScreenOff() {
if (mCanAnimateTransition) {
- final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing;
+ final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing
+ && !mHost.isPowerSaveActive();
mDozeParameters.setControlScreenOffAnimation(controlScreenOff);
mHost.setAnimateScreenOff(controlScreenOff);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index 150667b86828e..ef09434aa3951 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -39,6 +39,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import javax.inject.Inject;
@@ -63,6 +64,7 @@ public class NotificationInterruptionStateProvider {
private final Context mContext;
private final PowerManager mPowerManager;
private final IDreamManager mDreamManager;
+ private final BatteryController mBatteryController;
private NotificationPresenter mPresenter;
private HeadsUpManager mHeadsUpManager;
@@ -75,13 +77,14 @@ public class NotificationInterruptionStateProvider {
@Inject
public NotificationInterruptionStateProvider(Context context, NotificationFilter filter,
- StatusBarStateController stateController) {
+ StatusBarStateController stateController, BatteryController batteryController) {
this(context,
(PowerManager) context.getSystemService(Context.POWER_SERVICE),
IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE)),
new AmbientDisplayConfiguration(context),
filter,
+ batteryController,
stateController);
}
@@ -92,10 +95,12 @@ public class NotificationInterruptionStateProvider {
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
+ BatteryController batteryController,
StatusBarStateController statusBarStateController) {
mContext = context;
mPowerManager = powerManager;
mDreamManager = dreamManager;
+ mBatteryController = batteryController;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mNotificationFilter = notificationFilter;
mStatusBarStateController = statusBarStateController;
@@ -293,6 +298,13 @@ public class NotificationInterruptionStateProvider {
return false;
}
+ if (mBatteryController.isAodPowerSave()) {
+ if (DEBUG_HEADS_UP) {
+ Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
+ }
+ return false;
+ }
+
if (!canAlertCommon(entry)) {
if (DEBUG_HEADS_UP) {
Log.d(TAG, "No pulsing: notification shouldn't alert: " + sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 111cdd2cc32a6..738d076e13c5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -45,9 +45,7 @@ public interface BatteryController extends DemoMode, Dumpable,
/**
* Returns {@code true} if AOD was disabled by power saving policies.
*/
- default boolean isAodPowerSave() {
- return isPowerSave();
- }
+ boolean isAodPowerSave();
/**
* A listener that will be notified whenever a change in battery level or power save mode has
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index ba434d4fd0bde..5a4e6c903650d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -173,7 +174,8 @@ public class BubbleControllerTest extends SysuiTestCase {
TestableNotificationInterruptionStateProvider interruptionStateProvider =
new TestableNotificationInterruptionStateProvider(mContext,
mock(NotificationFilter.class),
- mock(StatusBarStateController.class));
+ mock(StatusBarStateController.class),
+ mock(BatteryController.class));
interruptionStateProvider.setUpWithPresenter(
mock(NotificationPresenter.class),
mock(HeadsUpManager.class),
@@ -659,8 +661,9 @@ public class BubbleControllerTest extends SysuiTestCase {
NotificationInterruptionStateProvider {
TestableNotificationInterruptionStateProvider(Context context,
- NotificationFilter filter, StatusBarStateController controller) {
- super(context, filter, controller);
+ NotificationFilter filter, StatusBarStateController controller,
+ BatteryController batteryController) {
+ super(context, filter, controller, batteryController);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 1e18e51bc079f..1eb75aaacbfb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -46,6 +46,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.wakelock.WakeLockFake;
import org.junit.Before;
@@ -76,8 +77,8 @@ public class DozeMachineTest extends SysuiTestCase {
mConfigMock = mock(AmbientDisplayConfiguration.class);
mPartMock = mock(DozeMachine.Part.class);
- mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake, mWakefulnessLifecycle);
-
+ mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake,
+ mWakefulnessLifecycle, mock(BatteryController.class));
mMachine.setParts(new DozeMachine.Part[]{mPartMock});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
index a66cf843bbc34..0db1f681a7ac8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
@@ -53,6 +53,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import org.junit.Before;
@@ -85,6 +86,8 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
HeadsUpManager mHeadsUpManager;
@Mock
NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
+ @Mock
+ BatteryController mBatteryController;
private NotificationInterruptionStateProvider mNotifInterruptionStateProvider;
@@ -98,7 +101,8 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
mDreamManager,
mAmbientDisplayConfiguration,
mNotificationFilter,
- mStatusBarStateController);
+ mStatusBarStateController,
+ mBatteryController);
mNotifInterruptionStateProvider.setUpWithPresenter(
mPresenter,
@@ -573,17 +577,17 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
/**
* Testable class overriding constructor.
*/
- public class TestableNotificationInterruptionStateProvider extends
+ public static class TestableNotificationInterruptionStateProvider extends
NotificationInterruptionStateProvider {
TestableNotificationInterruptionStateProvider(Context context,
PowerManager powerManager, IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController,
+ BatteryController batteryController) {
super(context, powerManager, dreamManager, ambientDisplayConfiguration,
- notificationFilter,
- statusBarStateController);
+ notificationFilter, batteryController, statusBarStateController);
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 178ff22eede23..02215a984203b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -110,6 +110,7 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -156,6 +157,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
@Mock private StatusBarStateControllerImpl mStatusBarStateController;
+ @Mock private BatteryController mBatteryController;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private StatusBarNotificationPresenter mNotificationPresenter;
@Mock
@@ -209,7 +211,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationInterruptionStateProvider =
new TestableNotificationInterruptionStateProvider(mContext, mPowerManager,
mDreamManager, mAmbientDisplayConfiguration, mNotificationFilter,
- mStatusBarStateController);
+ mStatusBarStateController, mBatteryController);
mDependency.injectTestDependency(NotificationInterruptionStateProvider.class,
mNotificationInterruptionStateProvider);
mDependency.injectMockDependency(NavigationBarController.class);
@@ -873,9 +875,10 @@ public class StatusBarTest extends SysuiTestCase {
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter filter,
- StatusBarStateController controller) {
+ StatusBarStateController controller,
+ BatteryController batteryController) {
super(context, powerManager, dreamManager, ambientDisplayConfiguration, filter,
- controller);
+ batteryController, controller);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
index a843cca498a08..df76f01494f3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -48,4 +48,9 @@ public class FakeBatteryController extends BaseLeakChecker
Date: Fri, 11 Oct 2019 19:06:27 +0000
Subject: [PATCH 7/9] Revert "Keep interrupts on when in battery saver mode"
This reverts commit 6edeb187015a04e7ff6a8f06275336b7e4ac82e7.
Reason for revert: cherry-picked into incorrect release branch
Bug: 134157254
Change-Id: I914e36b29ad2e0cc13619dbe8d32c8f0f9b77399
(cherry picked from commit 599a8ea144af095f530545c5b73dafe083068449)
---
.../CarNotificationInterruptionStateProvider.java | 6 ++----
.../statusbar/car/CarBatteryController.java | 5 -----
.../src/com/android/systemui/doze/DozeFactory.java | 3 +--
.../src/com/android/systemui/doze/DozeMachine.java | 9 +--------
.../com/android/systemui/doze/DozeTriggers.java | 5 +++--
.../src/com/android/systemui/doze/DozeUi.java | 3 +--
.../NotificationInterruptionStateProvider.java | 14 +-------------
.../statusbar/policy/BatteryController.java | 4 +++-
.../systemui/bubbles/BubbleControllerTest.java | 9 +++------
.../com/android/systemui/doze/DozeMachineTest.java | 5 ++---
.../NotificationInterruptionStateProviderTest.java | 14 +++++---------
.../systemui/statusbar/phone/StatusBarTest.java | 9 +++------
.../utils/leaks/FakeBatteryController.java | 5 -----
13 files changed, 25 insertions(+), 66 deletions(-)
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
index 447e579ece429..afd722ba00914 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
@@ -22,7 +22,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.policy.BatteryController;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -35,9 +34,8 @@ public class CarNotificationInterruptionStateProvider extends
@Inject
public CarNotificationInterruptionStateProvider(Context context,
NotificationFilter filter,
- StatusBarStateController stateController,
- BatteryController batteryController) {
- super(context, filter, stateController, batteryController);
+ StatusBarStateController stateController) {
+ super(context, filter, stateController);
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
index d79849ccafc63..58f80a4ed9680 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
@@ -257,11 +257,6 @@ public class CarBatteryController extends BroadcastReceiver implements BatteryCo
return false;
}
- @Override
- public boolean isAodPowerSave() {
- return false;
- }
-
private void notifyBatteryLevelChanged() {
for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) {
mChangeCallbacks.get(i)
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 0e124e48f165c..90cb05a8e6ee1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -33,7 +33,6 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -65,7 +64,7 @@ public class DozeFactory {
params);
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
- wakefulnessLifecycle, Dependency.get(BatteryController.class));
+ wakefulnessLifecycle);
machine.setParts(new DozeMachine.Part[]{
new DozePauser(handler, machine, alarmManager, params.getPolicy()),
new DozeFalsingManagerAdapter(falsingManager),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 7f2d52780a239..93a51cc20db2a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -27,7 +27,6 @@ import com.android.internal.util.Preconditions;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness;
import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -122,7 +121,6 @@ public class DozeMachine {
private final WakeLock mWakeLock;
private final AmbientDisplayConfiguration mConfig;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private final BatteryController mBatteryController;
private Part[] mParts;
private final ArrayList mQueuedRequests = new ArrayList<>();
@@ -131,13 +129,11 @@ public class DozeMachine {
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
- WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle,
- BatteryController batteryController) {
+ WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle) {
mDozeService = service;
mConfig = config;
mWakefulnessLifecycle = wakefulnessLifecycle;
mWakeLock = wakeLock;
- mBatteryController = batteryController;
}
/** Initializes the set of {@link Part}s. Must be called exactly once after construction. */
@@ -320,9 +316,6 @@ public class DozeMachine {
Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
return mState;
}
- if (requestedState == State.DOZE_AOD && mBatteryController.isAodPowerSave()) {
- return State.DOZE;
- }
if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 6199a0deb31ff..bab64db4519c1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -345,6 +345,7 @@ public class DozeTriggers implements DozeMachine.Part {
private void checkTriggersAtInit() {
if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
+ || mDozeHost.isPowerSaveActive()
|| mDozeHost.isBlockingDoze()
|| !mDozeHost.isProvisioned()) {
mMachine.requestState(DozeMachine.State.FINISH);
@@ -573,8 +574,8 @@ public class DozeTriggers implements DozeMachine.Part {
@Override
public void onPowerSaveChanged(boolean active) {
- if (mDozeHost.isPowerSaveActive()) {
- mMachine.requestState(DozeMachine.State.DOZE);
+ if (active) {
+ mMachine.requestState(DozeMachine.State.FINISH);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 3869e77294e74..1f33af8c3f559 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -83,8 +83,7 @@ public class DozeUi implements DozeMachine.Part {
*/
private void updateAnimateScreenOff() {
if (mCanAnimateTransition) {
- final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing
- && !mHost.isPowerSaveActive();
+ final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing;
mDozeParameters.setControlScreenOffAnimation(controlScreenOff);
mHost.setAnimateScreenOff(controlScreenOff);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index ef09434aa3951..150667b86828e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -39,7 +39,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import javax.inject.Inject;
@@ -64,7 +63,6 @@ public class NotificationInterruptionStateProvider {
private final Context mContext;
private final PowerManager mPowerManager;
private final IDreamManager mDreamManager;
- private final BatteryController mBatteryController;
private NotificationPresenter mPresenter;
private HeadsUpManager mHeadsUpManager;
@@ -77,14 +75,13 @@ public class NotificationInterruptionStateProvider {
@Inject
public NotificationInterruptionStateProvider(Context context, NotificationFilter filter,
- StatusBarStateController stateController, BatteryController batteryController) {
+ StatusBarStateController stateController) {
this(context,
(PowerManager) context.getSystemService(Context.POWER_SERVICE),
IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE)),
new AmbientDisplayConfiguration(context),
filter,
- batteryController,
stateController);
}
@@ -95,12 +92,10 @@ public class NotificationInterruptionStateProvider {
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
- BatteryController batteryController,
StatusBarStateController statusBarStateController) {
mContext = context;
mPowerManager = powerManager;
mDreamManager = dreamManager;
- mBatteryController = batteryController;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mNotificationFilter = notificationFilter;
mStatusBarStateController = statusBarStateController;
@@ -298,13 +293,6 @@ public class NotificationInterruptionStateProvider {
return false;
}
- if (mBatteryController.isAodPowerSave()) {
- if (DEBUG_HEADS_UP) {
- Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
- }
- return false;
- }
-
if (!canAlertCommon(entry)) {
if (DEBUG_HEADS_UP) {
Log.d(TAG, "No pulsing: notification shouldn't alert: " + sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 738d076e13c5c..111cdd2cc32a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -45,7 +45,9 @@ public interface BatteryController extends DemoMode, Dumpable,
/**
* Returns {@code true} if AOD was disabled by power saving policies.
*/
- boolean isAodPowerSave();
+ default boolean isAodPowerSave() {
+ return isPowerSave();
+ }
/**
* A listener that will be notified whenever a change in battery level or power save mode has
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 5a4e6c903650d..ba434d4fd0bde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -74,7 +74,6 @@ import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -174,8 +173,7 @@ public class BubbleControllerTest extends SysuiTestCase {
TestableNotificationInterruptionStateProvider interruptionStateProvider =
new TestableNotificationInterruptionStateProvider(mContext,
mock(NotificationFilter.class),
- mock(StatusBarStateController.class),
- mock(BatteryController.class));
+ mock(StatusBarStateController.class));
interruptionStateProvider.setUpWithPresenter(
mock(NotificationPresenter.class),
mock(HeadsUpManager.class),
@@ -661,9 +659,8 @@ public class BubbleControllerTest extends SysuiTestCase {
NotificationInterruptionStateProvider {
TestableNotificationInterruptionStateProvider(Context context,
- NotificationFilter filter, StatusBarStateController controller,
- BatteryController batteryController) {
- super(context, filter, controller, batteryController);
+ NotificationFilter filter, StatusBarStateController controller) {
+ super(context, filter, controller);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 1eb75aaacbfb8..1e18e51bc079f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -46,7 +46,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.wakelock.WakeLockFake;
import org.junit.Before;
@@ -77,8 +76,8 @@ public class DozeMachineTest extends SysuiTestCase {
mConfigMock = mock(AmbientDisplayConfiguration.class);
mPartMock = mock(DozeMachine.Part.class);
- mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake,
- mWakefulnessLifecycle, mock(BatteryController.class));
+ mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake, mWakefulnessLifecycle);
+
mMachine.setParts(new DozeMachine.Part[]{mPartMock});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
index 0db1f681a7ac8..a66cf843bbc34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
@@ -53,7 +53,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import org.junit.Before;
@@ -86,8 +85,6 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
HeadsUpManager mHeadsUpManager;
@Mock
NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
- @Mock
- BatteryController mBatteryController;
private NotificationInterruptionStateProvider mNotifInterruptionStateProvider;
@@ -101,8 +98,7 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
mDreamManager,
mAmbientDisplayConfiguration,
mNotificationFilter,
- mStatusBarStateController,
- mBatteryController);
+ mStatusBarStateController);
mNotifInterruptionStateProvider.setUpWithPresenter(
mPresenter,
@@ -577,17 +573,17 @@ public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
/**
* Testable class overriding constructor.
*/
- public static class TestableNotificationInterruptionStateProvider extends
+ public class TestableNotificationInterruptionStateProvider extends
NotificationInterruptionStateProvider {
TestableNotificationInterruptionStateProvider(Context context,
PowerManager powerManager, IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
- StatusBarStateController statusBarStateController,
- BatteryController batteryController) {
+ StatusBarStateController statusBarStateController) {
super(context, powerManager, dreamManager, ambientDisplayConfiguration,
- notificationFilter, batteryController, statusBarStateController);
+ notificationFilter,
+ statusBarStateController);
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 02215a984203b..178ff22eede23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -110,7 +110,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -157,7 +156,6 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
@Mock private StatusBarStateControllerImpl mStatusBarStateController;
- @Mock private BatteryController mBatteryController;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private StatusBarNotificationPresenter mNotificationPresenter;
@Mock
@@ -211,7 +209,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationInterruptionStateProvider =
new TestableNotificationInterruptionStateProvider(mContext, mPowerManager,
mDreamManager, mAmbientDisplayConfiguration, mNotificationFilter,
- mStatusBarStateController, mBatteryController);
+ mStatusBarStateController);
mDependency.injectTestDependency(NotificationInterruptionStateProvider.class,
mNotificationInterruptionStateProvider);
mDependency.injectMockDependency(NavigationBarController.class);
@@ -875,10 +873,9 @@ public class StatusBarTest extends SysuiTestCase {
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter filter,
- StatusBarStateController controller,
- BatteryController batteryController) {
+ StatusBarStateController controller) {
super(context, powerManager, dreamManager, ambientDisplayConfiguration, filter,
- batteryController, controller);
+ controller);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
index df76f01494f3e..a843cca498a08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -48,9 +48,4 @@ public class FakeBatteryController extends BaseLeakChecker
Date: Mon, 14 Oct 2019 12:00:36 -0700
Subject: [PATCH 8/9] Fixed a bug where the statusbar wasn't interactive
Our restriction if it has finished was too strict before,
let's loosen it to call whenever the animation has actually
finished not when it reached the final value
Fixes: 142189043
Test: atest SystemUITests
Change-Id: Ic8a252316346782b485b25d0f5d5458b30511f09
(cherry picked from commit 9449cfc4a608e7d801da642958249a16c536411b)
---
.../statusbar/phone/ScrimController.java | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index fd3c9526149dd..2f567177f8146 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -590,6 +590,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
setScrimAlpha(mScrimInFront, mInFrontAlpha);
setScrimAlpha(mScrimBehind, mBehindAlpha);
setScrimAlpha(mScrimForBubble, mBubbleAlpha);
+ // The animation could have all already finished, let's call onFinished just in case
+ onFinished();
dispatchScrimsVisible();
}
@@ -688,9 +690,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Override
public void onAnimationEnd(Animator animation) {
+ scrim.setTag(TAG_KEY_ANIM, null);
onFinished(lastCallback);
- scrim.setTag(TAG_KEY_ANIM, null);
dispatchScrimsVisible();
if (!mDeferFinishedListener && mOnAnimationFinished != null) {
@@ -754,9 +756,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
private void onFinished(Callback callback) {
- if (!hasReachedFinalState(mScrimBehind)
- || !hasReachedFinalState(mScrimInFront)
- || !hasReachedFinalState(mScrimForBubble)) {
+ if (isAnimating(mScrimBehind)
+ || isAnimating(mScrimInFront)
+ || isAnimating(mScrimForBubble)) {
if (callback != null && callback != mCallback) {
// Since we only notify the callback that we're finished once everything has
// finished, we need to make sure that any changing callbacks are also invoked
@@ -789,11 +791,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
}
- private boolean hasReachedFinalState(ScrimView scrim) {
- return scrim.getViewAlpha() == getCurrentScrimAlpha(scrim)
- && scrim.getTint() == getCurrentScrimTint(scrim);
- }
-
private boolean isAnimating(View scrim) {
return scrim.getTag(TAG_KEY_ANIM) != null;
}
@@ -849,10 +846,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
} else {
// update the alpha directly
updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
- onFinished();
}
- } else {
- onFinished();
}
}
From b4ba5c9144685a1847d46c75ea3c2e06b0ed203d Mon Sep 17 00:00:00 2001
From: Selim Cinek
Date: Fri, 25 Oct 2019 17:37:00 -0700
Subject: [PATCH 9/9] DO NOT MERGE Revert all scrim related changes in qpr
This reverts commit 9449cfc4a608e7d801da642958249a16c536411b.
This reverts commit 22fa97577f39524e3ffbfbbf37040eff540bcb49.
This reverts commit bde48202e7bb1ffa04acd5c42a332c62b73f34d8.
Bug: 141649119
Bug: 143195895 is also fixed on my taimen with the above.
Bug: 143185828
Test: atest SystemUITests
Change-Id: I225b10fef2f88d3436ef3a683c09717467b071ad
(cherry picked from commit f97d7f73cf965f30b645ddd01a5f639e7e79d192)
---
.../SystemUI/res/layout/super_status_bar.xml | 10 +-
.../com/android/systemui/SystemUIFactory.java | 3 +-
.../systemui/bubbles/BubbleController.java | 7 +-
.../systemui/statusbar/phone/LockIcon.java | 2 +-
.../statusbar/phone/ScrimController.java | 233 ++++++--------
.../systemui/statusbar/phone/ScrimState.java | 123 +++-----
.../systemui/statusbar/phone/StatusBar.java | 6 +-
.../phone/StatusBarWindowController.java | 4 +-
.../statusbar/phone/ScrimControllerTest.java | 285 ++++++------------
9 files changed, 225 insertions(+), 448 deletions(-)
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 9716a00a7f72f..a91493003bb54 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -44,7 +44,7 @@
-
-
scrimStateListener,
Consumer scrimVisibleListener, DozeParameters dozeParameters,
AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
- return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
+ return new ScrimController(scrimBehind, scrimInFront, scrimStateListener,
scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 3cc91de434385..5559d29a90506 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -316,9 +316,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (mStackView == null) {
mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer);
ViewGroup sbv = mStatusBarWindowController.getStatusBarView();
- int bubbleScrimIndex = sbv.indexOfChild(sbv.findViewById(R.id.scrim_for_bubble));
- int stackIndex = bubbleScrimIndex + 1; // Show stack above bubble scrim.
- sbv.addView(mStackView, stackIndex,
+ // TODO(b/130237686): When you expand the shade on top of expanded bubble, there is no
+ // scrim between bubble and the shade
+ int bubblePosition = sbv.indexOfChild(sbv.findViewById(R.id.scrim_behind)) + 1;
+ sbv.addView(mStackView, bubblePosition,
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index ecfc45bb11829..06a2225ed0bf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -604,7 +604,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
*/
public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
if (mWakeAndUnlockRunning
- && scrimsVisible == ScrimController.TRANSPARENT) {
+ && scrimsVisible == ScrimController.VISIBILITY_FULLY_TRANSPARENT) {
mWakeAndUnlockRunning = false;
update();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 2f567177f8146..9019e9a3f44b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -79,24 +79,23 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
/**
* When both scrims have 0 alpha.
*/
- public static final int TRANSPARENT = 0;
+ public static final int VISIBILITY_FULLY_TRANSPARENT = 0;
/**
* When scrims aren't transparent (alpha 0) but also not opaque (alpha 1.)
*/
- public static final int SEMI_TRANSPARENT = 1;
+ public static final int VISIBILITY_SEMI_TRANSPARENT = 1;
/**
* When at least 1 scrim is fully opaque (alpha set to 1.)
*/
- public static final int OPAQUE = 2;
+ public static final int VISIBILITY_FULLY_OPAQUE = 2;
- @IntDef(prefix = {"VISIBILITY_"}, value = {
- TRANSPARENT,
- SEMI_TRANSPARENT,
- OPAQUE
+ @IntDef(prefix = { "VISIBILITY_" }, value = {
+ VISIBILITY_FULLY_TRANSPARENT,
+ VISIBILITY_SEMI_TRANSPARENT,
+ VISIBILITY_FULLY_OPAQUE
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ScrimVisibility {
- }
+ public @interface ScrimVisibility {}
/**
* Default alpha value for most scrims.
@@ -124,11 +123,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private ScrimState mState = ScrimState.UNINITIALIZED;
private final Context mContext;
-
- protected final ScrimView mScrimInFront;
protected final ScrimView mScrimBehind;
- protected final ScrimView mScrimForBubble;
-
+ protected final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final DozeParameters mDozeParameters;
@@ -157,15 +153,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private Runnable mOnAnimationFinished;
private boolean mDeferFinishedListener;
private final Interpolator mInterpolator = new DecelerateInterpolator();
-
- private float mInFrontAlpha = NOT_INITIALIZED;
- private float mBehindAlpha = NOT_INITIALIZED;
- private float mBubbleAlpha = NOT_INITIALIZED;
-
- private int mInFrontTint;
- private int mBehindTint;
- private int mBubbleTint;
-
+ private float mCurrentInFrontAlpha = NOT_INITIALIZED;
+ private float mCurrentBehindAlpha = NOT_INITIALIZED;
+ private int mCurrentInFrontTint;
+ private int mCurrentBehindTint;
private boolean mWallpaperVisibilityTimedOut;
private int mScrimsVisibility;
private final TriConsumer mScrimStateListener;
@@ -184,17 +175,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private boolean mWakeLockHeld;
private boolean mKeyguardOccluded;
- public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble,
+ public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
TriConsumer scrimStateListener,
Consumer scrimVisibleListener, DozeParameters dozeParameters,
AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
mScrimBehind = scrimBehind;
mScrimInFront = scrimInFront;
- mScrimForBubble = scrimForBubble;
-
mScrimStateListener = scrimStateListener;
mScrimVisibleListener = scrimVisibleListener;
-
mContext = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
@@ -225,13 +213,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
final ScrimState[] states = ScrimState.values();
for (int i = 0; i < states.length; i++) {
- states[i].init(mScrimInFront, mScrimBehind, mScrimForBubble, mDozeParameters);
+ states[i].init(mScrimInFront, mScrimBehind, mDozeParameters);
states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard);
}
mScrimBehind.setDefaultFocusHighlightEnabled(false);
mScrimInFront.setDefaultFocusHighlightEnabled(false);
- mScrimForBubble.setDefaultFocusHighlightEnabled(false);
updateScrims();
}
@@ -270,14 +257,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
mBlankScreen = state.getBlanksScreen();
mAnimateChange = state.getAnimateChange();
mAnimationDuration = state.getAnimationDuration();
-
- mInFrontTint = state.getFrontTint();
- mBehindTint = state.getBehindTint();
- mBubbleTint = state.getBubbleTint();
-
- mInFrontAlpha = state.getFrontAlpha();
- mBehindAlpha = state.getBehindAlpha();
- mBubbleAlpha = state.getBubbleAlpha();
+ mCurrentInFrontTint = state.getFrontTint();
+ mCurrentBehindTint = state.getBehindTint();
+ mCurrentInFrontAlpha = state.getFrontAlpha();
+ mCurrentBehindAlpha = state.getBehindAlpha();
applyExpansionToAlpha();
// Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
@@ -410,20 +393,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
if (mExpansionFraction != fraction) {
mExpansionFraction = fraction;
- boolean relevantState = (mState == ScrimState.UNLOCKED
- || mState == ScrimState.KEYGUARD
- || mState == ScrimState.PULSING
- || mState == ScrimState.BUBBLE_EXPANDED);
- if (!(relevantState && mExpansionAffectsAlpha)) {
+ final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED
+ || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING;
+ if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) {
return;
}
+
applyExpansionToAlpha();
+
if (mUpdatePending) {
return;
}
+
setOrAdaptCurrentAnimation(mScrimBehind);
setOrAdaptCurrentAnimation(mScrimInFront);
- setOrAdaptCurrentAnimation(mScrimForBubble);
+
dispatchScrimState(mScrimBehind.getViewAlpha());
// Reset wallpaper timeout if it's already timeout like expanding panel while PULSING
@@ -437,10 +421,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
private void setOrAdaptCurrentAnimation(View scrim) {
- float alpha = getCurrentScrimAlpha(scrim);
- if (isAnimating(scrim)) {
- // Adapt current animation.
+ if (!isAnimating(scrim)) {
+ updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim));
+ } else {
ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM);
+ float alpha = getCurrentScrimAlpha(scrim);
float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA);
float previousStartValue = (Float) scrim.getTag(TAG_START_ALPHA);
float relativeDiff = alpha - previousEndValue;
@@ -448,9 +433,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
scrim.setTag(TAG_START_ALPHA, newStartValue);
scrim.setTag(TAG_END_ALPHA, alpha);
previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
- } else {
- // Set animation.
- updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
}
}
@@ -459,27 +441,27 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
return;
}
- if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) {
+ if (mState == ScrimState.UNLOCKED) {
// Darken scrim as you pull down the shade when unlocked
float behindFraction = getInterpolatedFraction();
behindFraction = (float) Math.pow(behindFraction, 0.8f);
- mBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
- mInFrontAlpha = 0;
+ mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
+ mCurrentInFrontAlpha = 0;
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) {
// Either darken of make the scrim transparent when you
// pull down the shade
float interpolatedFract = getInterpolatedFraction();
float alphaBehind = mState.getBehindAlpha();
if (mDarkenWhileDragging) {
- mBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
+ mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind,
interpolatedFract);
- mInFrontAlpha = mState.getFrontAlpha();
+ mCurrentInFrontAlpha = mState.getFrontAlpha();
} else {
- mBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
+ mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind,
interpolatedFract);
- mInFrontAlpha = mState.getFrontAlpha();
+ mCurrentInFrontAlpha = mState.getFrontAlpha();
}
- mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+ mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
mState.getBehindTint(), interpolatedFract);
}
}
@@ -504,8 +486,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
*/
public void setAodFrontScrimAlpha(float alpha) {
if (((mState == ScrimState.AOD && mDozeParameters.getAlwaysOn())
- || mState == ScrimState.PULSING) && mInFrontAlpha != alpha) {
- mInFrontAlpha = alpha;
+ || mState == ScrimState.PULSING) && mCurrentInFrontAlpha != alpha) {
+ mCurrentInFrontAlpha = alpha;
updateScrims();
}
@@ -519,9 +501,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
*/
public void prepareForGentleWakeUp() {
if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
- mInFrontAlpha = 1f;
- mInFrontTint = Color.BLACK;
- mBehindTint = Color.BLACK;
+ mCurrentInFrontAlpha = 1f;
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
mAnimateChange = false;
updateScrims();
mAnimateChange = true;
@@ -539,8 +521,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
if (mState == ScrimState.PULSING) {
float newBehindAlpha = mState.getBehindAlpha();
- if (mBehindAlpha != newBehindAlpha) {
- mBehindAlpha = newBehindAlpha;
+ if (mCurrentBehindAlpha != newBehindAlpha) {
+ mCurrentBehindAlpha = newBehindAlpha;
updateScrims();
}
}
@@ -562,11 +544,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
// Only animate scrim color if the scrim view is actually visible
boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen;
boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen;
- boolean animateScrimForBubble = mScrimForBubble.getViewAlpha() != 0 && !mBlankScreen;
-
mScrimInFront.setColors(mColors, animateScrimInFront);
mScrimBehind.setColors(mColors, animateScrimBehind);
- mScrimForBubble.setColors(mColors, animateScrimForBubble);
// Calculate minimum scrim opacity for white or black text.
int textColor = mColors.supportsDarkText() ? Color.BLACK : Color.WHITE;
@@ -585,13 +564,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD)
&& mKeyguardOccluded;
if (aodWallpaperTimeout || occludedKeyguard) {
- mBehindAlpha = 1;
+ mCurrentBehindAlpha = 1;
}
- setScrimAlpha(mScrimInFront, mInFrontAlpha);
- setScrimAlpha(mScrimBehind, mBehindAlpha);
- setScrimAlpha(mScrimForBubble, mBubbleAlpha);
- // The animation could have all already finished, let's call onFinished just in case
- onFinished();
+
+ setScrimInFrontAlpha(mCurrentInFrontAlpha);
+ setScrimBehindAlpha(mCurrentBehindAlpha);
+
dispatchScrimsVisible();
}
@@ -602,11 +580,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private void dispatchScrimsVisible() {
final int currentScrimVisibility;
if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) {
- currentScrimVisibility = OPAQUE;
+ currentScrimVisibility = VISIBILITY_FULLY_OPAQUE;
} else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) {
- currentScrimVisibility = TRANSPARENT;
+ currentScrimVisibility = VISIBILITY_FULLY_TRANSPARENT;
} else {
- currentScrimVisibility = SEMI_TRANSPARENT;
+ currentScrimVisibility = VISIBILITY_SEMI_TRANSPARENT;
}
if (mScrimsVisibility != currentScrimVisibility) {
@@ -623,10 +601,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
return 0;
} else {
// woo, special effects
- return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * Math.pow(1f - frac, 2f))));
+ return (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
}
}
+ private void setScrimBehindAlpha(float alpha) {
+ setScrimAlpha(mScrimBehind, alpha);
+ }
+
+ private void setScrimInFrontAlpha(float alpha) {
+ setScrimAlpha(mScrimInFront, alpha);
+ }
+
private void setScrimAlpha(ScrimView scrim, float alpha) {
if (alpha == 0f) {
scrim.setClickable(false);
@@ -637,26 +623,17 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
updateScrim(scrim, alpha);
}
- private String getScrimName(ScrimView scrim) {
- if (scrim == mScrimInFront) {
- return "front_scrim";
- } else if (scrim == mScrimBehind) {
- return "back_scrim";
- } else if (scrim == mScrimForBubble) {
- return "bubble_scrim";
- }
- return "unknown_scrim";
- }
-
private void updateScrimColor(View scrim, float alpha, int tint) {
alpha = Math.max(0, Math.min(1.0f, alpha));
if (scrim instanceof ScrimView) {
ScrimView scrimView = (ScrimView) scrim;
- Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_alpha",
+ Trace.traceCounter(Trace.TRACE_TAG_APP,
+ scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha",
(int) (alpha * 255));
- Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
+ Trace.traceCounter(Trace.TRACE_TAG_APP,
+ scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint",
Color.alpha(tint));
scrimView.setTint(tint);
@@ -690,9 +667,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Override
public void onAnimationEnd(Animator animation) {
- scrim.setTag(TAG_KEY_ANIM, null);
onFinished(lastCallback);
+ scrim.setTag(TAG_KEY_ANIM, null);
dispatchScrimsVisible();
if (!mDeferFinishedListener && mOnAnimationFinished != null) {
@@ -713,11 +690,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private float getCurrentScrimAlpha(View scrim) {
if (scrim == mScrimInFront) {
- return mInFrontAlpha;
+ return mCurrentInFrontAlpha;
} else if (scrim == mScrimBehind) {
- return mBehindAlpha;
- } else if (scrim == mScrimForBubble) {
- return mBubbleAlpha;
+ return mCurrentBehindAlpha;
} else {
throw new IllegalArgumentException("Unknown scrim view");
}
@@ -725,11 +700,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
private int getCurrentScrimTint(View scrim) {
if (scrim == mScrimInFront) {
- return mInFrontTint;
+ return mCurrentInFrontTint;
} else if (scrim == mScrimBehind) {
- return mBehindTint;
- } else if (scrim == mScrimForBubble) {
- return mBubbleTint;
+ return mCurrentBehindTint;
} else {
throw new IllegalArgumentException("Unknown scrim view");
}
@@ -756,16 +729,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
private void onFinished(Callback callback) {
- if (isAnimating(mScrimBehind)
- || isAnimating(mScrimInFront)
- || isAnimating(mScrimForBubble)) {
- if (callback != null && callback != mCallback) {
- // Since we only notify the callback that we're finished once everything has
- // finished, we need to make sure that any changing callbacks are also invoked
- callback.onFinished();
- }
- return;
- }
if (mWakeLockHeld) {
mWakeLock.release(TAG);
mWakeLockHeld = false;
@@ -782,12 +745,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
// When unlocking with fingerprint, we'll fade the scrims from black to transparent.
// At the end of the animation we need to remove the tint.
if (mState == ScrimState.UNLOCKED) {
- mInFrontTint = Color.TRANSPARENT;
- mBehindTint = Color.TRANSPARENT;
- mBubbleTint = Color.TRANSPARENT;
- updateScrimColor(mScrimInFront, mInFrontAlpha, mInFrontTint);
- updateScrimColor(mScrimBehind, mBehindAlpha, mBehindTint);
- updateScrimColor(mScrimForBubble, mBubbleAlpha, mBubbleTint);
+ mCurrentInFrontTint = Color.TRANSPARENT;
+ mCurrentBehindTint = Color.TRANSPARENT;
}
}
@@ -846,7 +805,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
} else {
// update the alpha directly
updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim));
+ onFinished();
}
+ } else {
+ onFinished();
}
}
@@ -889,7 +851,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
/**
* Executes a callback after the frame has hit the display.
- *
* @param callback What to run.
*/
@VisibleForTesting
@@ -933,35 +894,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(" ScrimController: ");
- pw.print(" state: ");
- pw.println(mState);
+ pw.print(" state: "); pw.println(mState);
+ pw.print(" frontScrim:"); pw.print(" viewAlpha="); pw.print(mScrimInFront.getViewAlpha());
+ pw.print(" alpha="); pw.print(mCurrentInFrontAlpha);
+ pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimInFront.getTint()));
- pw.print(" frontScrim:");
- pw.print(" viewAlpha=");
- pw.print(mScrimInFront.getViewAlpha());
- pw.print(" alpha=");
- pw.print(mInFrontAlpha);
- pw.print(" tint=0x");
- pw.println(Integer.toHexString(mScrimInFront.getTint()));
+ pw.print(" backScrim:"); pw.print(" viewAlpha="); pw.print(mScrimBehind.getViewAlpha());
+ pw.print(" alpha="); pw.print(mCurrentBehindAlpha);
+ pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint()));
- pw.print(" backScrim:");
- pw.print(" viewAlpha=");
- pw.print(mScrimBehind.getViewAlpha());
- pw.print(" alpha=");
- pw.print(mBehindAlpha);
- pw.print(" tint=0x");
- pw.println(Integer.toHexString(mScrimBehind.getTint()));
-
- pw.print(" bubbleScrim:");
- pw.print(" viewAlpha=");
- pw.print(mScrimForBubble.getViewAlpha());
- pw.print(" alpha=");
- pw.print(mBubbleAlpha);
- pw.print(" tint=0x");
- pw.println(Integer.toHexString(mScrimForBubble.getTint()));
-
- pw.print(" mTracking=");
- pw.println(mTracking);
+ pw.print(" mTracking="); pw.println(mTracking);
}
public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
@@ -1008,8 +950,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
// in this case, back-scrim needs to be re-evaluated
if (mState == ScrimState.AOD || mState == ScrimState.PULSING) {
float newBehindAlpha = mState.getBehindAlpha();
- if (mBehindAlpha != newBehindAlpha) {
- mBehindAlpha = newBehindAlpha;
+ if (mCurrentBehindAlpha != newBehindAlpha) {
+ mCurrentBehindAlpha = newBehindAlpha;
updateScrims();
}
}
@@ -1030,13 +972,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
public interface Callback {
default void onStart() {
}
-
default void onDisplayBlanked() {
}
-
default void onFinished() {
}
-
default void onCancelled() {
}
/** Returns whether to timeout wallpaper or not. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 7463c7c232bdd..5fa861c8a2ac2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -36,6 +36,7 @@ public enum ScrimState {
* On the lock screen.
*/
KEYGUARD(0) {
+
@Override
public void prepare(ScrimState previousState) {
mBlankScreen = false;
@@ -52,13 +53,10 @@ public enum ScrimState {
} else {
mAnimationDuration = ScrimController.ANIMATION_DURATION;
}
- mFrontTint = Color.BLACK;
- mBehindTint = Color.BLACK;
- mBubbleTint = Color.TRANSPARENT;
-
- mFrontAlpha = 0;
- mBehindAlpha = mScrimBehindAlphaKeyguard;
- mBubbleAlpha = 0;
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
+ mCurrentBehindAlpha = mScrimBehindAlphaKeyguard;
+ mCurrentInFrontAlpha = 0;
}
},
@@ -68,9 +66,8 @@ public enum ScrimState {
BOUNCER(1) {
@Override
public void prepare(ScrimState previousState) {
- mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
- mFrontAlpha = 0f;
- mBubbleAlpha = 0f;
+ mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
+ mCurrentInFrontAlpha = 0f;
}
},
@@ -80,9 +77,8 @@ public enum ScrimState {
BOUNCER_SCRIMMED(2) {
@Override
public void prepare(ScrimState previousState) {
- mBehindAlpha = 0;
- mBubbleAlpha = 0f;
- mFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
+ mCurrentBehindAlpha = 0;
+ mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
}
},
@@ -92,9 +88,8 @@ public enum ScrimState {
BRIGHTNESS_MIRROR(3) {
@Override
public void prepare(ScrimState previousState) {
- mBehindAlpha = 0;
- mFrontAlpha = 0;
- mBubbleAlpha = 0;
+ mCurrentBehindAlpha = 0;
+ mCurrentInFrontAlpha = 0;
}
},
@@ -106,16 +101,9 @@ public enum ScrimState {
public void prepare(ScrimState previousState) {
final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
mBlankScreen = mDisplayRequiresBlanking;
-
- mFrontTint = Color.BLACK;
- mFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
-
- mBehindTint = Color.BLACK;
- mBehindAlpha = ScrimController.TRANSPARENT;
-
- mBubbleTint = Color.TRANSPARENT;
- mBubbleAlpha = ScrimController.TRANSPARENT;
-
+ mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
// DisplayPowerManager may blank the screen for us,
// in this case we just need to set our state.
@@ -139,10 +127,9 @@ public enum ScrimState {
PULSING(5) {
@Override
public void prepare(ScrimState previousState) {
- mFrontAlpha = mAodFrontScrimAlpha;
- mBubbleAlpha = 0f;
- mBehindTint = Color.BLACK;
- mFrontTint = Color.BLACK;
+ mCurrentInFrontAlpha = mAodFrontScrimAlpha;
+ mCurrentBehindTint = Color.BLACK;
+ mCurrentInFrontTint = Color.BLACK;
mBlankScreen = mDisplayRequiresBlanking;
mAnimationDuration = mWakeLockScreenSensorActive
? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
@@ -167,33 +154,26 @@ public enum ScrimState {
UNLOCKED(6) {
@Override
public void prepare(ScrimState previousState) {
- // State that UI will sync to.
- mBehindAlpha = 0;
- mFrontAlpha = 0;
- mBubbleAlpha = 0;
-
+ mCurrentBehindAlpha = 0;
+ mCurrentInFrontAlpha = 0;
mAnimationDuration = mKeyguardFadingAway
? mKeyguardFadingAwayDuration
: StatusBar.FADE_KEYGUARD_DURATION;
mAnimateChange = !mLaunchingAffordanceWithPreview;
- mFrontTint = Color.TRANSPARENT;
- mBehindTint = Color.TRANSPARENT;
- mBubbleTint = Color.TRANSPARENT;
- mBlankScreen = false;
-
if (previousState == ScrimState.AOD) {
- // Set all scrims black, before they fade transparent.
- updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */);
- updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */);
- updateScrimColor(mScrimForBubble, 1f /* alpha */, Color.BLACK /* tint */);
-
+ // Fade from black to transparent when coming directly from AOD
+ updateScrimColor(mScrimInFront, 1, Color.BLACK);
+ updateScrimColor(mScrimBehind, 1, Color.BLACK);
// Scrims should still be black at the end of the transition.
- mFrontTint = Color.BLACK;
- mBehindTint = Color.BLACK;
- mBubbleTint = Color.BLACK;
+ mCurrentInFrontTint = Color.BLACK;
+ mCurrentBehindTint = Color.BLACK;
mBlankScreen = true;
+ } else {
+ mCurrentInFrontTint = Color.TRANSPARENT;
+ mCurrentBehindTint = Color.TRANSPARENT;
+ mBlankScreen = false;
}
}
},
@@ -204,36 +184,25 @@ public enum ScrimState {
BUBBLE_EXPANDED(7) {
@Override
public void prepare(ScrimState previousState) {
- mFrontTint = Color.TRANSPARENT;
- mBehindTint = Color.TRANSPARENT;
- mBubbleTint = Color.TRANSPARENT;
-
- mFrontAlpha = ScrimController.TRANSPARENT;
- mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
- mBubbleAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
-
+ mCurrentInFrontTint = Color.TRANSPARENT;
+ mCurrentBehindTint = Color.TRANSPARENT;
mAnimationDuration = ScrimController.ANIMATION_DURATION;
+ mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY;
mBlankScreen = false;
}
};
boolean mBlankScreen = false;
long mAnimationDuration = ScrimController.ANIMATION_DURATION;
- int mFrontTint = Color.TRANSPARENT;
- int mBehindTint = Color.TRANSPARENT;
- int mBubbleTint = Color.TRANSPARENT;
-
+ int mCurrentInFrontTint = Color.TRANSPARENT;
+ int mCurrentBehindTint = Color.TRANSPARENT;
boolean mAnimateChange = true;
+ float mCurrentInFrontAlpha;
+ float mCurrentBehindAlpha;
float mAodFrontScrimAlpha;
- float mFrontAlpha;
- float mBehindAlpha;
- float mBubbleAlpha;
-
float mScrimBehindAlphaKeyguard;
ScrimView mScrimInFront;
ScrimView mScrimBehind;
- ScrimView mScrimForBubble;
-
DozeParameters mDozeParameters;
boolean mDisplayRequiresBlanking;
boolean mWallpaperSupportsAmbientMode;
@@ -248,17 +217,13 @@ public enum ScrimState {
mIndex = index;
}
- public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble,
- DozeParameters dozeParameters) {
+ public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) {
mScrimInFront = scrimInFront;
mScrimBehind = scrimBehind;
- mScrimForBubble = scrimForBubble;
-
mDozeParameters = dozeParameters;
mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
}
- /** Prepare state for transition. */
public void prepare(ScrimState previousState) {
}
@@ -267,27 +232,19 @@ public enum ScrimState {
}
public float getFrontAlpha() {
- return mFrontAlpha;
+ return mCurrentInFrontAlpha;
}
public float getBehindAlpha() {
- return mBehindAlpha;
- }
-
- public float getBubbleAlpha() {
- return mBubbleAlpha;
+ return mCurrentBehindAlpha;
}
public int getFrontTint() {
- return mFrontTint;
+ return mCurrentInFrontTint;
}
public int getBehindTint() {
- return mBehindTint;
- }
-
- public int getBubbleTint() {
- return mBubbleTint;
+ return mCurrentBehindTint;
}
public long getAnimationDuration() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index fc20d83b9ddb7..559df18ef478a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -229,6 +229,7 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
@@ -811,7 +812,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// TODO: Deal with the ugliness that comes from having some of the statusbar broken out
// into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
-
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
mZenController.addCallback(this);
NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
@@ -932,10 +932,8 @@ public class StatusBar extends SystemUI implements DemoMode,
ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
- ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble);
-
mScrimController = SystemUIFactory.getInstance().createScrimController(
- scrimBehind, scrimInFront, scrimForBubble, mLockscreenWallpaper,
+ scrimBehind, scrimInFront, mLockscreenWallpaper,
(state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
scrimsVisible -> {
if (mStatusBarWindowController != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index d3ae5cf35b0cc..946fe0b3a2f85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -222,7 +222,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
}
final boolean scrimsOccludingWallpaper =
- state.scrimsVisibility == ScrimController.OPAQUE;
+ state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
final boolean keyguardOrAod = state.keyguardShowing
|| (state.dozing && mDozeParameters.getAlwaysOn());
if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
@@ -308,7 +308,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
|| state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
|| state.headsUpShowing || state.bubblesShowing
- || state.scrimsVisibility != ScrimController.TRANSPARENT);
+ || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT);
}
private void applyFitsSystemWindows(State state) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index d4ad4b6d4f166..205312ca508ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE;
-import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
+import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_OPAQUE;
+import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_SEMI_TRANSPARENT;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -69,7 +69,6 @@ public class ScrimControllerTest extends SysuiTestCase {
private SynchronousScrimController mScrimController;
private ScrimView mScrimBehind;
private ScrimView mScrimInFront;
- private ScrimView mScrimForBubble;
private ScrimState mScrimState;
private float mScrimBehindAlpha;
private GradientColors mScrimInFrontColor;
@@ -85,7 +84,6 @@ public class ScrimControllerTest extends SysuiTestCase {
public void setup() {
mScrimBehind = spy(new ScrimView(getContext()));
mScrimInFront = new ScrimView(getContext());
- mScrimForBubble = new ScrimView(getContext());
mWakeLock = mock(WakeLock.class);
mAlarmManager = mock(AlarmManager.class);
mAlwaysOnEnabled = true;
@@ -94,7 +92,6 @@ public class ScrimControllerTest extends SysuiTestCase {
when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
- mScrimForBubble,
(scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
mScrimState = scrimState;
mScrimBehindAlpha = scrimBehindAlpha;
@@ -117,28 +114,21 @@ public class ScrimControllerTest extends SysuiTestCase {
public void transitionToKeyguard() {
mScrimController.transitionTo(ScrimState.KEYGUARD);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be visible without tint
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+ assertScrimTint(mScrimBehind, true /* tinted */);
}
@Test
public void transitionToAod_withRegularWallpaper() {
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be visible with tint
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+ assertScrimTint(mScrimBehind, true /* tinted */);
+ assertScrimTint(mScrimInFront, true /* tinted */);
}
@Test
@@ -146,18 +136,14 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setWallpaperSupportsAmbientMode(true);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be transparent
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
// Pulsing notification should conserve AOD wallpaper.
mScrimController.transitionTo(ScrimState.PULSING);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
}
@Test
@@ -166,14 +152,11 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setWallpaperSupportsAmbientMode(true);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be visible with tint
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+ assertScrimTint(mScrimBehind, true /* tinted */);
+ assertScrimTint(mScrimInFront, true /* tinted */);
}
@Test
@@ -183,14 +166,11 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.finishAnimationsImmediately();
mScrimController.setHasBackdrop(true);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be visible with tint
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+ assertScrimTint(mScrimBehind, true /* tinted */);
+ assertScrimTint(mScrimInFront, true /* tinted */);
}
@Test
@@ -199,32 +179,27 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.transitionTo(ScrimState.KEYGUARD);
mScrimController.setAodFrontScrimAlpha(0.5f);
mScrimController.finishAnimationsImmediately();
-
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be visible without tint
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
// ... but that it does take effect once we enter the AOD state.
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ // Front scrim should be semi-transparent
+ // Back scrim should be visible
+ assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
// ... and that if we set it while we're in AOD, it does take immediate effect.
mScrimController.setAodFrontScrimAlpha(1f);
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
// ... and make sure we recall the previous front scrim alpha even if we transition away
// for a bit.
mScrimController.transitionTo(ScrimState.UNLOCKED);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(OPAQUE /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
// ... and alpha updates should be completely ignored if always_on is off.
// Passing it forward would mess up the wake-up transition.
@@ -248,36 +223,27 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setWallpaperSupportsAmbientMode(false);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
mScrimController.transitionTo(ScrimState.PULSING);
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent, but tinted
// Back scrim should be semi-transparent so the user can see the wallpaper
// Pulse callback should have been invoked
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(true /* front */,
- true /* behind */,
- false /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+ assertScrimTint(mScrimBehind, true /* tinted */);
// ... and when ambient goes dark, front scrim should be semi-transparent
mScrimController.setAodFrontScrimAlpha(0.5f);
mScrimController.finishAnimationsImmediately();
// Front scrim should be semi-transparent
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- OPAQUE /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */,
+ VISIBILITY_FULLY_OPAQUE /* back */);
mScrimController.setWakeLockScreenSensorActive(true);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */,
+ VISIBILITY_SEMI_TRANSPARENT /* back */);
// Reset value since enums are static.
mScrimController.setAodFrontScrimAlpha(0f);
@@ -289,13 +255,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent
// Back scrim should be visible without tint
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+ assertScrimTint(mScrimBehind, false /* tinted */);
}
@Test
@@ -304,12 +265,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.finishAnimationsImmediately();
// Front scrim should be transparent
// Back scrim should be visible without tint
- assertScrimAlpha(SEMI_TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
+ assertScrimTint(mScrimBehind, false /* tinted */);
}
@Test
@@ -317,19 +274,15 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setPanelExpansion(0f);
mScrimController.transitionTo(ScrimState.UNLOCKED);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
-
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be transparent
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
+ assertScrimTint(mScrimBehind, false /* tinted */);
+ assertScrimTint(mScrimInFront, false /* tinted */);
// Back scrim should be visible after start dragging
mScrimController.setPanelExpansion(0.5f);
- assertScrimAlpha(TRANSPARENT /* front */,
- SEMI_TRANSPARENT /* back */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
}
@Test
@@ -337,19 +290,12 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
mScrimController.finishAnimationsImmediately();
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
-
// Front scrim should be transparent
- Assert.assertEquals(ScrimController.TRANSPARENT,
+ Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT,
mScrimInFront.getViewAlpha(), 0.0f);
// Back scrim should be visible
Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
mScrimBehind.getViewAlpha(), 0.0f);
- // Bubble scrim should be visible
- Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY,
- mScrimBehind.getViewAlpha(), 0.0f);
}
@Test
@@ -418,23 +364,16 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setPanelExpansion(0f);
mScrimController.finishAnimationsImmediately();
mScrimController.transitionTo(ScrimState.UNLOCKED);
-
- // Immediately tinted black after the transition starts
- assertScrimTint(true /* front */,
- true /* behind */,
- true /* bubble */);
-
+ // Immediately tinted after the transition starts
+ assertScrimTint(mScrimInFront, true /* tinted */);
+ assertScrimTint(mScrimBehind, true /* tinted */);
mScrimController.finishAnimationsImmediately();
-
- // All scrims should be transparent at the end of fade transition.
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* behind */,
- TRANSPARENT /* bubble */);
-
- // Make sure at the very end of the animation, we're reset to transparent
- assertScrimTint(false /* front */,
- false /* behind */,
- false /* bubble */);
+ // Front scrim should be transparent
+ // Back scrim should be transparent
+ // Neither scrims should be tinted anymore after the animation.
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
+ assertScrimTint(mScrimInFront, false /* tinted */);
+ assertScrimTint(mScrimBehind, false /* tinted */);
}
@Test
@@ -449,11 +388,9 @@ public class ScrimControllerTest extends SysuiTestCase {
// Front scrim should be black in the middle of the transition
Assert.assertTrue("Scrim should be visible during transition. Alpha: "
+ mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0);
- assertScrimTint(true /* front */,
- true /* behind */,
- true /* bubble */);
+ assertScrimTint(mScrimInFront, true /* tinted */);
Assert.assertSame("Scrim should be visible during transition.",
- mScrimVisibility, OPAQUE);
+ mScrimVisibility, VISIBILITY_FULLY_OPAQUE);
}
});
mScrimController.finishAnimationsImmediately();
@@ -661,15 +598,11 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setKeyguardOccluded(true);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
mScrimController.transitionTo(ScrimState.PULSING);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
}
@Test
@@ -677,15 +610,11 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimController.setWallpaperSupportsAmbientMode(true);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- TRANSPARENT /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT);
mScrimController.setKeyguardOccluded(true);
mScrimController.finishAnimationsImmediately();
- assertScrimAlpha(TRANSPARENT /* front */,
- OPAQUE /* behind */,
- TRANSPARENT /* bubble */);
+ assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
}
@Test
@@ -724,68 +653,33 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimInFront.getDefaultFocusHighlightEnabled());
Assert.assertFalse("Scrim shouldn't have focus highlight",
mScrimBehind.getDefaultFocusHighlightEnabled());
- Assert.assertFalse("Scrim shouldn't have focus highlight",
- mScrimForBubble.getDefaultFocusHighlightEnabled());
}
- private void assertScrimTint(boolean front, boolean behind, boolean bubble) {
+ private void assertScrimTint(ScrimView scrimView, boolean tinted) {
+ final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
+ final String name = scrimView == mScrimInFront ? "front" : "back";
Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimInFront) + " and tint: "
- + Integer.toHexString(mScrimInFront.getTint()),
- front, mScrimInFront.getTint() != Color.TRANSPARENT);
-
- Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimBehind) + " and tint: "
- + Integer.toHexString(mScrimBehind.getTint()),
- behind, mScrimBehind.getTint() != Color.TRANSPARENT);
-
- Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
- + " with scrim: " + getScrimName(mScrimForBubble) + " and tint: "
- + Integer.toHexString(mScrimForBubble.getTint()),
- bubble, mScrimForBubble.getTint() != Color.TRANSPARENT);
+ +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()),
+ tinted, viewIsTinted);
}
- private String getScrimName(ScrimView scrim) {
- if (scrim == mScrimInFront) {
- return "front";
- } else if (scrim == mScrimBehind) {
- return "back";
- } else if (scrim == mScrimForBubble) {
- return "bubble";
- }
- return "unknown_scrim";
- }
+ private void assertScrimVisibility(int inFront, int behind) {
+ boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
+ boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT;
+ Assert.assertEquals("Unexpected front scrim visibility. Alpha is "
+ + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0);
+ Assert.assertEquals("Unexpected back scrim visibility. Alpha is "
+ + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0);
- private void assertScrimAlpha(int front, int behind, int bubble) {
- // Check single scrim visibility.
- Assert.assertEquals("Unexpected front scrim alpha: "
- + mScrimInFront.getViewAlpha(),
- front != TRANSPARENT /* expected */,
- mScrimInFront.getViewAlpha() > TRANSPARENT /* actual */);
-
- Assert.assertEquals("Unexpected back scrim alpha: "
- + mScrimBehind.getViewAlpha(),
- behind != TRANSPARENT /* expected */,
- mScrimBehind.getViewAlpha() > TRANSPARENT /* actual */);
-
- Assert.assertEquals(
- "Unexpected bubble scrim alpha: "
- + mScrimForBubble.getViewAlpha(), /* message */
- bubble != TRANSPARENT /* expected */,
- mScrimForBubble.getViewAlpha() > TRANSPARENT /* actual */);
-
- // Check combined scrim visibility.
final int visibility;
- if (front == OPAQUE || behind == OPAQUE || bubble == OPAQUE) {
- visibility = OPAQUE;
- } else if (front > TRANSPARENT || behind > TRANSPARENT || bubble > TRANSPARENT) {
- visibility = SEMI_TRANSPARENT;
+ if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) {
+ visibility = VISIBILITY_FULLY_OPAQUE;
+ } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) {
+ visibility = VISIBILITY_SEMI_TRANSPARENT;
} else {
- visibility = TRANSPARENT;
+ visibility = VISIBILITY_FULLY_TRANSPARENT;
}
- Assert.assertEquals("Invalid visibility.",
- visibility /* expected */,
- mScrimVisibility);
+ Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility);
}
/**
@@ -797,12 +691,11 @@ public class ScrimControllerTest extends SysuiTestCase {
boolean mOnPreDrawCalled;
SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
- ScrimView scrimForBubble,
TriConsumer scrimStateListener,
Consumer scrimVisibleListener, DozeParameters dozeParameters,
AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) {
- super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
- scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor);
+ super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
+ dozeParameters, alarmManager, keyguardMonitor);
}
@Override
@@ -813,14 +706,13 @@ public class ScrimControllerTest extends SysuiTestCase {
void finishAnimationsImmediately() {
boolean[] animationFinished = {false};
- setOnAnimationFinished(() -> animationFinished[0] = true);
+ setOnAnimationFinished(()-> animationFinished[0] = true);
// Execute code that will trigger animations.
onPreDraw();
// Force finish all animations.
mLooper.processAllMessages();
endAnimation(mScrimBehind, TAG_KEY_ANIM);
endAnimation(mScrimInFront, TAG_KEY_ANIM);
- endAnimation(mScrimForBubble, TAG_KEY_ANIM);
if (!animationFinished[0]) {
throw new IllegalStateException("Animation never finished");
@@ -858,7 +750,6 @@ public class ScrimControllerTest extends SysuiTestCase {
/**
* Do not wait for a frame since we're in a test environment.
- *
* @param callback What to execute.
*/
@Override