summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java3
-rw-r--r--core/java/android/app/ActivityThread.java24
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java9
-rw-r--r--core/proto/android/server/windowmanagertransitiontrace.proto2
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java16
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java265
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java123
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java23
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java12
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java6
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java7
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayFrames.java17
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java12
-rw-r--r--services/core/java/com/android/server/wm/Task.java8
-rw-r--r--services/core/java/com/android/server/wm/Transition.java14
-rw-r--r--services/core/java/com/android/server/wm/TransitionTracer.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java7
-rw-r--r--services/proguard.flags3
-rw-r--r--services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java58
-rw-r--r--services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java34
43 files changed, 655 insertions, 346 deletions
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index 517e3ce39d7e..31c92ba5e207 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -70,6 +70,9 @@ public class ZipFilePerfTest {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
+ state.pauseTiming();
+ zf.close();
+ state.resumeTiming();
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9e9e985d27de..802458b1793c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5894,16 +5894,16 @@ public final class ActivityThread extends ClientTransactionHandler
final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(),
displayId);
- final Configuration currentConfig = activity.mCurrentConfig;
- final int diff = currentConfig.diffPublicOnly(newConfig);
- final boolean hasPublicConfigChange = diff != 0;
+ final Configuration currentResConfig = activity.getResources().getConfiguration();
+ final int diff = currentResConfig.diffPublicOnly(newConfig);
+ final boolean hasPublicResConfigChange = diff != 0;
final ActivityClientRecord r = getActivityClient(activityToken);
// TODO(b/173090263): Use diff instead after the improvement of AssetManager and
// ResourcesImpl constructions.
- final boolean shouldUpdateResources = hasPublicConfigChange
- || shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig,
- movedToDifferentDisplay, hasPublicConfigChange);
- final boolean shouldReportChange = shouldReportChange(diff, currentConfig, newConfig,
+ final boolean shouldUpdateResources = hasPublicResConfigChange
+ || shouldUpdateResources(activityToken, currentResConfig, newConfig,
+ amOverrideConfig, movedToDifferentDisplay, hasPublicResConfigChange);
+ final boolean shouldReportChange = shouldReportChange(activity.mCurrentConfig, newConfig,
r != null ? r.mSizeConfigurations : null,
activity.mActivityInfo.getRealConfigChanged());
// Nothing significant, don't proceed with updating and reporting.
@@ -5927,9 +5927,6 @@ public final class ActivityThread extends ClientTransactionHandler
amOverrideConfig, contextThemeWrapperOverrideConfig);
mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig, displayId);
- activity.mConfigChangeFlags = 0;
- activity.mCurrentConfig = new Configuration(newConfig);
-
// Apply the ContextThemeWrapper override if necessary.
// NOTE: Make sure the configurations are not modified, as they are treated as immutable
// in many places.
@@ -5940,8 +5937,10 @@ public final class ActivityThread extends ClientTransactionHandler
activity.dispatchMovedToDisplay(displayId, configToReport);
}
+ activity.mConfigChangeFlags = 0;
if (shouldReportChange) {
activity.mCalled = false;
+ activity.mCurrentConfig = new Configuration(newConfig);
activity.onConfigurationChanged(configToReport);
if (!activity.mCalled) {
throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
@@ -5956,8 +5955,6 @@ public final class ActivityThread extends ClientTransactionHandler
* Returns {@code true} if {@link Activity#onConfigurationChanged(Configuration)} should be
* dispatched.
*
- * @param publicDiff Usually computed by {@link Configuration#diffPublicOnly(Configuration)}.
- * This parameter is to prevent we compute it again.
* @param currentConfig The current configuration cached in {@link Activity#mCurrentConfig}.
* It is {@code null} before the first config update from the server side.
* @param newConfig The updated {@link Configuration}
@@ -5966,9 +5963,10 @@ public final class ActivityThread extends ClientTransactionHandler
* @return {@code true} if the config change should be reported to the Activity
*/
@VisibleForTesting
- public static boolean shouldReportChange(int publicDiff, @Nullable Configuration currentConfig,
+ public static boolean shouldReportChange(@Nullable Configuration currentConfig,
@NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets,
int handledConfigChanges) {
+ final int publicDiff = currentConfig.diffPublicOnly(newConfig);
// Don't report the change if there's no public diff between current and new config.
if (publicDiff == 0) {
return false;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6829f3da5717..98d4c5976adc 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4503,10 +4503,13 @@ public class BatteryStatsImpl extends BatteryStats {
for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
entry.setValue(entry.getValue() | TAG_FIRST_OCCURRENCE_FLAG);
}
+ // Make a copy of mHistoryCur.
+ HistoryItem copy = new HistoryItem();
+ copy.setTo(cur);
+ // startRecordingHistory will reset mHistoryCur.
startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- HistoryItem newItem = new HistoryItem();
- newItem.setTo(cur);
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
+ // Add the copy into history buffer.
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy);
return;
}
diff --git a/core/proto/android/server/windowmanagertransitiontrace.proto b/core/proto/android/server/windowmanagertransitiontrace.proto
index 9429127b2f6e..4161f6554fb6 100644
--- a/core/proto/android/server/windowmanagertransitiontrace.proto
+++ b/core/proto/android/server/windowmanagertransitiontrace.proto
@@ -58,6 +58,8 @@ message Transition {
State state = 5;
int32 flags = 6;
repeated ChangeInfo change = 7;
+ uint64 start_transaction_id = 8;
+ uint64 finish_transaction_id = 9;
}
message ChangeInfo {
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
index 385879210d4a..dd0e9ff8b5e8 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
@@ -154,19 +154,21 @@ public class BatteryStatsHistoryIteratorTest {
for (int i = 0; i < eventCount; i++) {
String name = "a" + (i % 10);
- assertThat(iterator.next(item)).isTrue();
- // Skip a blank event inserted at the start of every buffer
- if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) {
+ do {
assertThat(iterator.next(item)).isTrue();
- }
+ // Skip a blank event inserted at the start of every buffer
+ } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE
+ || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE);
+
assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM
| BatteryStats.HistoryItem.EVENT_FLAG_START);
assertThat(item.eventTag.string).isEqualTo(name);
- assertThat(iterator.next(item)).isTrue();
- if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) {
+ do {
assertThat(iterator.next(item)).isTrue();
- }
+ } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE
+ || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE);
+
assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM
| BatteryStats.HistoryItem.EVENT_FLAG_FINISH);
assertThat(item.eventTag.string).isEqualTo(name);
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 8d3751e6ad6c..47f70ddf2d42 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -207,8 +207,8 @@ public class ActivityThreadClientTest {
final Configuration currentConfig = new Configuration();
assertFalse("Must not report change if no public diff",
- shouldReportChange(0 /* publicDiff */, currentConfig, newConfig,
- null /* sizeBuckets */, 0 /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, null /* sizeBuckets */,
+ 0 /* handledConfigChanges */));
final int[] verticalThresholds = {100, 400};
final SizeConfigurationBuckets buckets = new SizeConfigurationBuckets(
@@ -221,25 +221,25 @@ public class ActivityThreadClientTest {
newConfig.screenHeightDp = 300;
assertFalse("Must not report changes if the diff is small and not handled",
- shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig,
- newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
assertTrue("Must report changes if the small diff is handled",
- shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, newConfig,
- buckets, CONFIG_SCREEN_SIZE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_SCREEN_SIZE /* handledConfigChanges */));
currentConfig.fontScale = 0.8f;
newConfig.fontScale = 1.2f;
assertTrue("Must report handled changes regardless of small unhandled change",
- shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
- currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
newConfig.screenHeightDp = 500;
assertFalse("Must not report changes if there's unhandled big changes",
- shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
- currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
}
private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 172418057b86..920dcc70ad46 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -216,24 +216,24 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) {
- // Always update configuration after orientation changed to make sure to render divider bar
- // with proper resources that matching screen orientation.
- final int orientation = configuration.orientation;
- if (mOrientation != orientation) {
- mContext = mContext.createConfigurationContext(configuration);
- mSplitWindowManager.setConfiguration(configuration);
- mOrientation = orientation;
- }
-
// Update the split bounds when necessary. Besides root bounds changed, split bounds need to
// be updated when the rotation changed to cover the case that users rotated the screen 180
// degrees.
+ // Make sure to render the divider bar with proper resources that matching the screen
+ // orientation.
final int rotation = configuration.windowConfiguration.getRotation();
final Rect rootBounds = configuration.windowConfiguration.getBounds();
- if (mRotation == rotation && mRootBounds.equals(rootBounds)) {
+ final int orientation = configuration.orientation;
+
+ if (mOrientation == orientation
+ && mRotation == rotation
+ && mRootBounds.equals(rootBounds)) {
return false;
}
+ mContext = mContext.createConfigurationContext(configuration);
+ mSplitWindowManager.setConfiguration(configuration);
+ mOrientation = orientation;
mTempRect.set(mRootBounds);
mRootBounds.set(rootBounds);
mRotation = rotation;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
index 3dd43866e465..f9fc1f3ca184 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
@@ -33,13 +32,10 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
-import javax.inject.Inject;
-
/***
* {@link DreamOverlayNotificationCountProvider} provides the current notification count to
* registered callbacks. Ongoing notifications are not included in the count.
*/
-@SysUISingleton
public class DreamOverlayNotificationCountProvider
implements CallbackController<DreamOverlayNotificationCountProvider.Callback> {
private final Set<String> mNotificationKeys = new HashSet<>();
@@ -82,7 +78,6 @@ public class DreamOverlayNotificationCountProvider
}
};
- @Inject
public DreamOverlayNotificationCountProvider(
NotificationListener notificationListener,
@Background Executor bgExecutor) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index e878b22f61ed..250313d0aae8 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -49,6 +49,7 @@ import com.android.systemui.util.time.DateFormatUtil;
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -65,7 +66,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
private final Resources mResources;
private final DateFormatUtil mDateFormatUtil;
private final IndividualSensorPrivacyController mSensorPrivacyController;
- private final DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider;
+ private final Optional<DreamOverlayNotificationCountProvider>
+ mDreamOverlayNotificationCountProvider;
private final ZenModeController mZenModeController;
private final Executor mMainExecutor;
@@ -125,7 +127,7 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
NextAlarmController nextAlarmController,
DateFormatUtil dateFormatUtil,
IndividualSensorPrivacyController sensorPrivacyController,
- DreamOverlayNotificationCountProvider dreamOverlayNotificationCountProvider,
+ Optional<DreamOverlayNotificationCountProvider> dreamOverlayNotificationCountProvider,
ZenModeController zenModeController,
StatusBarWindowStateController statusBarWindowStateController) {
super(view);
@@ -161,7 +163,9 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
mZenModeController.addCallback(mZenModeCallback);
updatePriorityModeStatusIcon();
- mDreamOverlayNotificationCountProvider.addCallback(mNotificationCountCallback);
+ mDreamOverlayNotificationCountProvider.ifPresent(
+ provider -> provider.addCallback(mNotificationCountCallback));
+
mTouchInsetSession.addViewToTracking(mView);
}
@@ -171,7 +175,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
mSensorPrivacyController.removeCallback(mSensorCallback);
mNextAlarmController.removeCallback(mNextAlarmCallback);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
- mDreamOverlayNotificationCountProvider.removeCallback(mNotificationCountCallback);
+ mDreamOverlayNotificationCountProvider.ifPresent(
+ provider -> provider.removeCallback(mNotificationCountCallback));
mTouchInsetSession.clear();
mIsAttached = false;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index cd23f149cf7d..2dd2098a78b9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -20,9 +20,13 @@ import android.content.Context;
import android.content.res.Resources;
import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
+import java.util.Optional;
+
import javax.inject.Named;
import dagger.Module;
@@ -50,6 +54,18 @@ public interface DreamModule {
return DreamBackend.getInstance(context);
}
+ /**
+ * Provides an instance of a {@link DreamOverlayNotificationCountProvider}.
+ */
+ @SysUISingleton
+ @Provides
+ static Optional<DreamOverlayNotificationCountProvider>
+ providesDreamOverlayNotificationCountProvider() {
+ // If we decide to bring this back, we should gate it on a config that can be changed in
+ // an overlay.
+ return Optional.empty();
+ }
+
/** */
@Provides
@Named(DREAM_ONLY_ENABLED_FOR_SYSTEM_USER)
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index f86541a90109..47c678b4b8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -45,9 +45,6 @@ public class Flags {
/***************************************/
// 100 - notification
- public static final BooleanFlag NEW_NOTIFICATION_PIPELINE_RENDERING =
- new BooleanFlag(101, true);
-
public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
new BooleanFlag(103, false);
@@ -194,6 +191,8 @@ public class Flags {
public static final SysPropBooleanFlag WM_ALWAYS_ENFORCE_PREDICTIVE_BACK =
new SysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", false);
+ public static final BooleanFlag NEW_BACK_AFFORDANCE = new BooleanFlag(1203, true);
+
// Pay no attention to the reflection behind the curtain.
// ========================== Curtain ==========================
// | |
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c5f6b7831ecf..d29655a5408d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -486,6 +486,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private IRemoteAnimationRunner mKeyguardExitAnimationRunner;
+ private CentralSurfaces mCentralSurfaces;
+
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -846,6 +848,13 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
+ mOccluded);
}
+ @Override
+ public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+ if (launchIsFullScreen) {
+ mCentralSurfaces.instantCollapseNotificationPanel();
+ }
+ }
+
@NonNull
@Override
public ViewGroup getLaunchContainer() {
@@ -2853,6 +2862,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
@Nullable PanelExpansionStateManager panelExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer, KeyguardBypassController bypassController) {
+ mCentralSurfaces = centralSurfaces;
mKeyguardViewControllerLazy.get().registerCentralSurfaces(
centralSurfaces,
panelView,
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 05da4bb4d1ad..90cca15ddf21 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -52,7 +52,7 @@ public class LogModule {
return factory.create("NotifLog", 1000 /* maxSize */, false /* systrace */);
}
- /** Provides a logging buffer for all logs related to the data layer of notifications. */
+ /** Provides a logging buffer for logs related to heads up presentation of notifications. */
@Provides
@SysUISingleton
@NotificationHeadsUpLog
@@ -60,6 +60,14 @@ public class LogModule {
return factory.create("NotifHeadsUpLog", 1000);
}
+ /** Provides a logging buffer for notification interruption calculations. */
+ @Provides
+ @SysUISingleton
+ @NotificationInterruptLog
+ public static LogBuffer provideNotificationInterruptLogBuffer(LogBufferFactory factory) {
+ return factory.create("NotifInterruptLog", 100);
+ }
+
/** Provides a logging buffer for all logs for lockscreen to shade transition events. */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
new file mode 100644
index 000000000000..760fbf3928b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification interruption logging. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationInterruptLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index d41837b7cf4d..e210d685a370 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -234,7 +234,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private boolean mIsBackGestureAllowed;
private boolean mGestureBlockingActivityRunning;
private boolean mIsInPipMode;
- private boolean mIsPredictiveBackAnimEnabled;
+ private boolean mIsNewBackAffordanceEnabled;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -524,8 +524,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
Choreographer.getInstance(), this::onInputEvent);
// Add a nav bar panel window
- mIsPredictiveBackAnimEnabled =
- mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_ANIM);
+ mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);
resetEdgeBackPlugin();
mPluginManager.addPluginListener(
this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
@@ -545,7 +544,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
}
private void resetEdgeBackPlugin() {
- if (mIsPredictiveBackAnimEnabled) {
+ if (mIsNewBackAffordanceEnabled) {
setEdgeBackPlugin(
mBackPanelControllerFactory.create(mContext, mBackAnimation));
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index f6a55e6b75c6..478f7aa8ce09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -48,8 +48,7 @@ class NotifPipelineFlags @Inject constructor(
fun assertLegacyPipelineEnabled(): Unit =
check(!isNewPipelineEnabled()) { "Old pipeline code running w/ new pipeline enabled" }
- fun isNewPipelineEnabled(): Boolean =
- featureFlags.isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING)
+ fun isNewPipelineEnabled(): Boolean = true
fun isDevLoggingEnabled(): Boolean =
featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
new file mode 100644
index 000000000000..63c37e9584d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/OWNERS
@@ -0,0 +1,12 @@
+set noparent
+
+# Bug component: 78010
+
+aaliomer@google.com
+aroederer@google.com
+jeffdq@google.com
+juliacr@google.com
+juliatuttle@google.com
+lynhan@google.com
+steell@google.com
+yurilin@google.com \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index e98ae8db4122..792ff8d20b97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -115,6 +115,7 @@ public class ListDumper {
) {
sb.append(indent)
.append("[").append(index).append("] ")
+ .append(index.length() == 1 ? " " : "")
.append(entry.getKey());
if (includeParent) {
@@ -192,7 +193,7 @@ public class ListDumper {
if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) {
rksb.append("suppressedSection=")
.append(notifEntry.getAttachState().getSuppressedChanges()
- .getSection())
+ .getSection().getLabel())
.append(" ");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 410593ac5493..ecce1ba25702 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -104,6 +104,7 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -829,11 +830,9 @@ public class NotifCollection implements Dumpable {
@Override
public void dump(PrintWriter pw, @NonNull String[] args) {
final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs());
+ entries.sort(Comparator.comparing(NotificationEntry::getKey));
- pw.println("\t" + TAG + " unsorted/unfiltered notifications:");
- if (entries.size() == 0) {
- pw.println("\t\t None");
- }
+ pw.println("\t" + TAG + " unsorted/unfiltered notifications: " + entries.size());
pw.println(
ListDumper.dumpList(
entries,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
index 6c99e3adb73e..1d18ca3dfade 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
@@ -20,16 +20,14 @@ import android.service.notification.StatusBarNotification
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.INFO
-import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationInterruptLog
import javax.inject.Inject
class NotificationInterruptLogger @Inject constructor(
- @NotificationLog val notifBuffer: LogBuffer,
- @NotificationHeadsUpLog val hunBuffer: LogBuffer
+ @NotificationInterruptLog val buffer: LogBuffer
) {
fun logHeadsUpFeatureChanged(useHeadsUp: Boolean) {
- hunBuffer.log(TAG, INFO, {
+ buffer.log(TAG, INFO, {
bool1 = useHeadsUp
}, {
"heads up is enabled=$bool1"
@@ -37,14 +35,14 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logWillDismissAll() {
- hunBuffer.log(TAG, INFO, {
+ buffer.log(TAG, INFO, {
}, {
"dismissing any existing heads up notification on disable event"
})
}
fun logNoBubbleNotAllowed(sbn: StatusBarNotification) {
- notifBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No bubble up: not allowed to bubble: $str1"
@@ -52,7 +50,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoBubbleNoMetadata(sbn: StatusBarNotification) {
- notifBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No bubble up: notification: $str1 doesn't have valid metadata"
@@ -60,14 +58,14 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoHeadsUpFeatureDisabled() {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
}, {
"No heads up: no huns"
})
}
fun logNoHeadsUpPackageSnoozed(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: snoozed package: $str1"
@@ -75,7 +73,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoHeadsUpAlreadyBubbled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: in unlocked shade where notification is shown as a bubble: $str1"
@@ -83,7 +81,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoHeadsUpSuppressedByDnd(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: suppressed by DND: $str1"
@@ -91,7 +89,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoHeadsUpNotImportant(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: unimportant notification: $str1"
@@ -99,7 +97,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoHeadsUpNotInUse(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: not in use: $str1"
@@ -110,7 +108,7 @@ class NotificationInterruptLogger @Inject constructor(
sbn: StatusBarNotification,
suppressor: NotificationInterruptSuppressor
) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
str2 = suppressor.name
}, {
@@ -119,7 +117,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logHeadsUp(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"Heads up: $str1"
@@ -127,7 +125,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoAlertingFilteredOut(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: filtered notification: $str1"
@@ -135,7 +133,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoAlertingGroupAlertBehavior(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: suppressed due to group alert behavior: $str1"
@@ -147,7 +145,7 @@ class NotificationInterruptLogger @Inject constructor(
suppressor: NotificationInterruptSuppressor,
awake: Boolean
) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
str2 = suppressor.name
bool1 = awake
@@ -157,7 +155,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoAlertingRecentFullscreen(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: recent fullscreen: $str1"
@@ -165,7 +163,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoPulsingSettingDisabled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: disabled by setting: $str1"
@@ -173,7 +171,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoPulsingBatteryDisabled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: disabled by battery saver: $str1"
@@ -181,7 +179,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoPulsingNoAlert(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: notification shouldn't alert: $str1"
@@ -189,7 +187,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoPulsingNoAmbientEffect(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: ambient effect suppressed: $str1"
@@ -197,7 +195,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logNoPulsingNotImportant(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: not important enough: $str1"
@@ -205,7 +203,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun logPulsing(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"Pulsing: $str1"
@@ -213,7 +211,7 @@ class NotificationInterruptLogger @Inject constructor(
}
fun keyguardHideNotification(key: String) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = key
}, {
"Keyguard Hide Notification: $str1"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index b785435f41f2..cd4a44e1c6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -141,7 +141,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30);
- private boolean mUpdateBackgroundOnUpdate;
+ private boolean mUpdateSelfBackgroundOnUpdate;
private boolean mNotificationTranslationFinished = false;
private boolean mIsSnoozed;
private boolean mIsFaded;
@@ -553,9 +553,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
updateLimits();
updateShelfIconColor();
updateRippleAllowed();
- if (mUpdateBackgroundOnUpdate) {
- mUpdateBackgroundOnUpdate = false;
- updateBackgroundColors();
+ if (mUpdateSelfBackgroundOnUpdate) {
+ // Because this is triggered by UiMode change which we already propagated to children,
+ // we know that child rows will receive the same event, and will update their own
+ // backgrounds when they finish inflating, so propagating again would be redundant.
+ mUpdateSelfBackgroundOnUpdate = false;
+ updateBackgroundColorsOfSelf();
+ }
+ }
+
+ private void updateBackgroundColorsOfSelf() {
+ super.updateBackgroundColors();
+ }
+
+ @Override
+ public void updateBackgroundColors() {
+ // Because this call is made by the NSSL only on attached rows at the moment of the
+ // UiMode or Theme change, we have to propagate to our child views.
+ updateBackgroundColorsOfSelf();
+ if (mIsSummaryWithChildren) {
+ for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) {
+ child.updateBackgroundColors();
+ }
}
}
@@ -1242,7 +1261,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
public void onUiModeChanged() {
- mUpdateBackgroundOnUpdate = true;
+ mUpdateSelfBackgroundOnUpdate = true;
reInflateViews();
if (mChildrenContainer != null) {
for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 8c6176408821..5181af773d9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1597,7 +1597,7 @@ public class CentralSurfacesImpl extends CoreStartable implements
}
}
});
- mStatusBarKeyguardViewManager.registerCentralSurfaces(
+ mKeyguardViewMediator.registerCentralSurfaces(
/* statusBar= */ this,
mNotificationPanelViewController,
mPanelExpansionStateManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS
new file mode 100644
index 000000000000..18f0fb38999c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/OWNERS
@@ -0,0 +1,3 @@
+per-file *Notification* = set noparent
+per-file *Notification* = file:../notification/OWNERS
+per-file NotificationIcon* = ccassidy@google.com, evanlaird@google.com, pixel@google.com \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
index 313d56febb75..4e9030f8045c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
@@ -16,17 +16,17 @@
package com.android.systemui.util.condition;
+import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.policy.CallbackController;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -37,154 +37,200 @@ import javax.inject.Inject;
* {@link Monitor} takes in a set of conditions, monitors whether all of them have
* been fulfilled, and informs any registered listeners.
*/
-public class Monitor implements CallbackController<Monitor.Callback> {
+public class Monitor {
private final String mTag = getClass().getSimpleName();
+ private final Executor mExecutor;
- private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final HashMap<Condition, ArraySet<Subscription.Token>> mConditions = new HashMap<>();
+ private final HashMap<Subscription.Token, SubscriptionState> mSubscriptions = new HashMap<>();
- // Set of all conditions that need to be monitored.
- private final Set<Condition> mConditions;
- private final Executor mExecutor;
+ private static class SubscriptionState {
+ private final Subscription mSubscription;
+ private Boolean mAllConditionsMet;
- // Whether all conditions have been met.
- private boolean mAllConditionsMet = false;
+ SubscriptionState(Subscription subscription) {
+ mSubscription = subscription;
+ }
+
+ public Set<Condition> getConditions() {
+ return mSubscription.mConditions;
+ }
- // Whether the monitor has started listening for all the conditions.
- private boolean mHaveConditionsStarted = false;
+ public void update() {
+ // Overriding conditions do not override each other
+ final Collection<Condition> overridingConditions = mSubscription.mConditions.stream()
+ .filter(Condition::isOverridingCondition).collect(Collectors.toSet());
+
+ final Collection<Condition> targetCollection = overridingConditions.isEmpty()
+ ? mSubscription.mConditions : overridingConditions;
+
+ final boolean newAllConditionsMet = targetCollection.isEmpty() ? true : targetCollection
+ .stream()
+ .map(Condition::isConditionMet)
+ .allMatch(conditionMet -> conditionMet);
+
+ if (mAllConditionsMet != null && newAllConditionsMet == mAllConditionsMet) {
+ return;
+ }
+
+ mAllConditionsMet = newAllConditionsMet;
+ mSubscription.mCallback.onConditionsChanged(mAllConditionsMet);
+ }
+ }
// Callback for when each condition has been updated.
private final Condition.Callback mConditionCallback = new Condition.Callback() {
@Override
public void onConditionChanged(Condition condition) {
- mExecutor.execute(() -> updateConditionMetState());
+ mExecutor.execute(() -> updateConditionMetState(condition));
}
};
@Inject
- public Monitor(@Main Executor executor, Set<Condition> conditions) {
- mConditions = new HashSet<>();
+ public Monitor(@Main Executor executor) {
mExecutor = executor;
-
- if (conditions != null) {
- mConditions.addAll(conditions);
- }
}
- private void updateConditionMetState() {
- // Overriding conditions do not override each other
- final Collection<Condition> overridingConditions = mConditions.stream()
- .filter(Condition::isOverridingCondition).collect(Collectors.toSet());
-
- final Collection<Condition> targetCollection = overridingConditions.isEmpty()
- ? mConditions : overridingConditions;
-
- final boolean newAllConditionsMet = targetCollection.isEmpty() ? true : targetCollection
- .stream()
- .map(Condition::isConditionMet)
- .allMatch(conditionMet -> conditionMet);
+ private void updateConditionMetState(Condition condition) {
+ mConditions.get(condition).stream().forEach(token -> mSubscriptions.get(token).update());
+ }
- if (newAllConditionsMet == mAllConditionsMet) {
- return;
- }
+ /**
+ * Registers a callback and the set of conditions to trigger it.
+ * @param subscription A {@link Subscription} detailing the desired conditions and callback.
+ * @return A {@link Subscription.Token} that can be used to remove the subscription.
+ */
+ public Subscription.Token addSubscription(@NotNull Subscription subscription) {
+ final Subscription.Token token = new Subscription.Token();
+ final SubscriptionState state = new SubscriptionState(subscription);
- if (shouldLog()) Log.d(mTag, "all conditions met: " + newAllConditionsMet);
- mAllConditionsMet = newAllConditionsMet;
-
- // Updates all callbacks.
- final Iterator<Callback> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback callback = iterator.next();
- if (callback == null) {
- iterator.remove();
- } else {
- callback.onConditionsChanged(mAllConditionsMet);
- }
- }
- }
+ mExecutor.execute(() -> {
+ mSubscriptions.put(token, state);
- private void addConditionLocked(@NotNull Condition condition) {
- mConditions.add(condition);
+ // Add and associate conditions.
+ subscription.getConditions().stream().forEach(condition -> {
+ if (!mConditions.containsKey(condition)) {
+ mConditions.put(condition, new ArraySet<>());
+ condition.addCallback(mConditionCallback);
+ }
- if (!mHaveConditionsStarted) {
- return;
- }
+ mConditions.get(condition).add(token);
+ });
- condition.addCallback(mConditionCallback);
- updateConditionMetState();
- }
+ // Update subscription state.
+ state.update();
- /**
- * Adds a condition for the monitor to listen to and consider when determining whether the
- * overall condition state is met.
- */
- public void addCondition(@NotNull Condition condition) {
- mExecutor.execute(() -> addConditionLocked(condition));
+ });
+ return token;
}
/**
- * Removes a condition from further consideration.
+ * Removes a subscription from participating in future callbacks.
+ * @param token The {@link Subscription.Token} returned when the {@link Subscription} was
+ * originally added.
*/
- public void removeCondition(@NotNull Condition condition) {
+ public void removeSubscription(@NotNull Subscription.Token token) {
mExecutor.execute(() -> {
- mConditions.remove(condition);
-
- if (!mHaveConditionsStarted) {
+ if (shouldLog()) Log.d(mTag, "removing callback");
+ if (!mSubscriptions.containsKey(token)) {
+ Log.e(mTag, "subscription not present:" + token);
return;
}
- condition.removeCallback(mConditionCallback);
- updateConditionMetState();
+ mSubscriptions.remove(token).getConditions().forEach(condition -> {
+ if (!mConditions.containsKey(condition)) {
+ Log.e(mTag, "condition not present:" + condition);
+ return;
+
+ }
+ final Set<Subscription.Token> conditionSubscriptions = mConditions.get(condition);
+
+ conditionSubscriptions.remove(token);
+ if (conditionSubscriptions.isEmpty()) {
+ condition.removeCallback(mConditionCallback);
+ mConditions.remove(condition);
+ }
+ });
});
}
- private void addCallbackLocked(@NotNull Callback callback) {
- if (mCallbacks.contains(callback)) {
- return;
- }
+ private boolean shouldLog() {
+ return Log.isLoggable(mTag, Log.DEBUG);
+ }
- if (shouldLog()) Log.d(mTag, "adding callback");
- mCallbacks.add(callback);
+ /**
+ * A {@link Subscription} represents a set of conditions and a callback that is informed when
+ * these conditions change.
+ */
+ public static class Subscription {
+ private final Set<Condition> mConditions;
+ private final Callback mCallback;
+
+ /** */
+ public Subscription(Set<Condition> conditions, Callback callback) {
+ this.mConditions = Collections.unmodifiableSet(conditions);
+ this.mCallback = callback;
+ }
- // Updates the callback immediately.
- callback.onConditionsChanged(mAllConditionsMet);
+ public Set<Condition> getConditions() {
+ return mConditions;
+ }
- if (!mHaveConditionsStarted) {
- if (shouldLog()) Log.d(mTag, "starting all conditions");
- mConditions.forEach(condition -> condition.addCallback(mConditionCallback));
- updateConditionMetState();
- mHaveConditionsStarted = true;
+ public Callback getCallback() {
+ return mCallback;
}
- }
- @Override
- public void addCallback(@NotNull Callback callback) {
- mExecutor.execute(() -> addCallbackLocked(callback));
- }
+ /**
+ * A {@link Token} is an identifier that is associated with a {@link Subscription} which is
+ * registered with a {@link Monitor}.
+ */
+ public static class Token {
+ }
- @Override
- public void removeCallback(@NotNull Callback callback) {
- mExecutor.execute(() -> {
- if (shouldLog()) Log.d(mTag, "removing callback");
- final Iterator<Callback> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback cb = iterator.next();
- if (cb == null || cb == callback) {
- iterator.remove();
- }
+ /**
+ * {@link Builder} is a helper class for constructing a {@link Subscription}.
+ */
+ public static class Builder {
+ private final Callback mCallback;
+ private final ArraySet<Condition> mConditions;
+
+ /**
+ * Default constructor specifying the {@link Callback} for the {@link Subscription}.
+ * @param callback
+ */
+ public Builder(Callback callback) {
+ mCallback = callback;
+ mConditions = new ArraySet<>();
}
- if (mCallbacks.isEmpty() && mHaveConditionsStarted) {
- if (shouldLog()) Log.d(mTag, "stopping all conditions");
- mConditions.forEach(condition -> condition.removeCallback(mConditionCallback));
+ /**
+ * Adds a {@link Condition} to be associated with the {@link Subscription}.
+ * @param condition
+ * @return The updated {@link Builder}.
+ */
+ public Builder addCondition(Condition condition) {
+ mConditions.add(condition);
+ return this;
+ }
- mAllConditionsMet = false;
- mHaveConditionsStarted = false;
+ /**
+ * Adds a set of {@link Condition} to be associated with the {@link Subscription}.
+ * @param condition
+ * @return The updated {@link Builder}.
+ */
+ public Builder addConditions(Set<Condition> condition) {
+ mConditions.addAll(condition);
+ return this;
}
- });
- }
- private boolean shouldLog() {
- return Log.isLoggable(mTag, Log.DEBUG);
+ /**
+ * Builds the {@link Subscription}.
+ * @return The resulting {@link Subscription}.
+ */
+ public Subscription build() {
+ return new Subscription(mConditions, mCallback);
+ }
+ }
}
/**
@@ -192,6 +238,13 @@ public class Monitor implements CallbackController<Monitor.Callback> {
*/
public interface Callback {
/**
+ * Returns the conditions associated with this callback.
+ */
+ default ArrayList<Condition> getConditions() {
+ return new ArrayList<>();
+ }
+
+ /**
* Triggered when the fulfillment of all conditions have been met.
*
* @param allConditionsMet True if all conditions have been fulfilled. False if none or
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
deleted file mode 100644
index 8e739d61b4f2..000000000000
--- a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 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.util.condition.dagger;
-
-import com.android.systemui.util.condition.Condition;
-import com.android.systemui.util.condition.Monitor;
-
-import java.util.Set;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Component for {@link Monitor}.
- */
-@Subcomponent
-public interface MonitorComponent {
- /**
- * Factory for {@link MonitorComponent}.
- */
- @Subcomponent.Factory
- interface Factory {
- MonitorComponent create(@BindsInstance Set<Condition> conditions);
- }
-
- /**
- * Provides {@link Monitor}.
- * @return
- */
- Monitor getMonitor();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
index 7892d6eec98d..981bf01164e3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
@@ -18,7 +18,6 @@ package com.android.systemui.util.dagger;
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.RingerModeTrackerImpl;
-import com.android.systemui.util.condition.dagger.MonitorComponent;
import com.android.systemui.util.wrapper.UtilWrapperModule;
import dagger.Binds;
@@ -27,9 +26,6 @@ import dagger.Module;
/** Dagger Module for code in the util package. */
@Module(includes = {
UtilWrapperModule.class
- },
- subcomponents = {
- MonitorComponent.class,
})
public interface UtilModule {
/** */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 3c28d48c2eb5..d334694805fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -57,6 +57,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
import java.util.concurrent.Executor;
@SmallTest
@@ -115,7 +116,7 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
mNextAlarmController,
mDateFormatUtil,
mSensorPrivacyController,
- mDreamOverlayNotificationCountProvider,
+ Optional.of(mDreamOverlayNotificationCountProvider),
mZenModeController,
mStatusBarWindowStateController);
}
@@ -231,6 +232,26 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
}
@Test
+ public void testNotificationsIconNotShownWhenCountProviderAbsent() {
+ DreamOverlayStatusBarViewController controller = new DreamOverlayStatusBarViewController(
+ mView,
+ mResources,
+ mMainExecutor,
+ mConnectivityManager,
+ mTouchSession,
+ mAlarmManager,
+ mNextAlarmController,
+ mDateFormatUtil,
+ mSensorPrivacyController,
+ Optional.empty(),
+ mZenModeController,
+ mStatusBarWindowStateController);
+ controller.onViewAttached();
+ verify(mView, never()).showIcon(
+ eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
+ }
+
+ @Test
public void testOnViewAttachedShowsPriorityModeIconWhenEnabled() {
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index b1bf971c52fc..f8b39e8cff71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -43,6 +43,7 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.NotificationChannel;
+import android.graphics.Color;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -110,6 +111,28 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
}
@Test
+ public void testUpdateBackgroundColors_isRecursive() {
+ mGroupRow.setTintColor(Color.RED);
+ mGroupRow.getChildNotificationAt(0).setTintColor(Color.GREEN);
+ mGroupRow.getChildNotificationAt(1).setTintColor(Color.BLUE);
+
+ assertThat(mGroupRow.getCurrentBackgroundTint()).isEqualTo(Color.RED);
+ assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint())
+ .isEqualTo(Color.GREEN);
+ assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint())
+ .isEqualTo(Color.BLUE);
+
+ mGroupRow.updateBackgroundColors();
+
+ int resetTint = mGroupRow.getCurrentBackgroundTint();
+ assertThat(resetTint).isNotEqualTo(Color.RED);
+ assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint())
+ .isEqualTo(resetTint);
+ assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint())
+ .isEqualTo(resetTint);
+ }
+
+ @Test
public void testSetSensitiveOnNotifRowNotifiesOfHeightChange() throws InterruptedException {
// GIVEN a sensitive notification row that's currently redacted
measureAndLayout(mNotifRow);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
index 758961658f2a..1e35b0f0e68a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
@@ -65,7 +65,12 @@ public class ConditionMonitorTest extends SysuiTestCase {
mCondition3 = spy(new FakeCondition());
mConditions = new HashSet<>(Arrays.asList(mCondition1, mCondition2, mCondition3));
- mConditionMonitor = new Monitor(mExecutor, mConditions);
+ mConditionMonitor = new Monitor(mExecutor);
+ }
+
+ public Monitor.Subscription.Builder getDefaultBuilder(Monitor.Callback callback) {
+ return new Monitor.Subscription.Builder(callback)
+ .addConditions(mConditions);
}
@Test
@@ -74,11 +79,19 @@ public class ConditionMonitorTest extends SysuiTestCase {
final Condition regularCondition = Mockito.mock(Condition.class);
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
- final Monitor monitor = new Monitor(
- mExecutor,
- new HashSet<>(Arrays.asList(overridingCondition, regularCondition)));
+ final Monitor.Callback referenceCallback = Mockito.mock(Monitor.Callback.class);
+
+ final Monitor monitor = new Monitor(mExecutor);
+
+ monitor.addSubscription(getDefaultBuilder(callback)
+ .addCondition(overridingCondition)
+ .addCondition(regularCondition)
+ .build());
+
+ monitor.addSubscription(getDefaultBuilder(referenceCallback)
+ .addCondition(regularCondition)
+ .build());
- monitor.addCallback(callback);
mExecutor.runAllReady();
when(overridingCondition.isOverridingCondition()).thenReturn(true);
@@ -94,7 +107,9 @@ public class ConditionMonitorTest extends SysuiTestCase {
mExecutor.runAllReady();
verify(callback).onConditionsChanged(eq(true));
+ verify(referenceCallback).onConditionsChanged(eq(false));
Mockito.clearInvocations(callback);
+ Mockito.clearInvocations(referenceCallback);
when(regularCondition.isConditionMet()).thenReturn(true);
when(overridingCondition.isConditionMet()).thenReturn(false);
@@ -103,12 +118,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
mExecutor.runAllReady();
verify(callback).onConditionsChanged(eq(false));
-
- clearInvocations(callback);
- monitor.removeCondition(overridingCondition);
- mExecutor.runAllReady();
-
- verify(callback).onConditionsChanged(eq(true));
+ verify(referenceCallback, never()).onConditionsChanged(anyBoolean());
}
/**
@@ -122,11 +132,13 @@ public class ConditionMonitorTest extends SysuiTestCase {
final Condition regularCondition = Mockito.mock(Condition.class);
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
- final Monitor monitor = new Monitor(
- mExecutor,
- new HashSet<>(Arrays.asList(overridingCondition, overridingCondition2,
- regularCondition)));
- monitor.addCallback(callback);
+ final Monitor monitor = new Monitor(mExecutor);
+
+ monitor.addSubscription(getDefaultBuilder(callback)
+ .addCondition(overridingCondition)
+ .addCondition(overridingCondition2)
+ .build());
+
mExecutor.runAllReady();
when(overridingCondition.isOverridingCondition()).thenReturn(true);
@@ -151,13 +163,13 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void addCallback_addFirstCallback_addCallbackToAllConditions() {
final Monitor.Callback callback1 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback1);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback1).build());
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition).addCallback(any()));
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback2);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback2).build());
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition, times(1)).addCallback(any()));
}
@@ -166,7 +178,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void addCallback_addFirstCallback_reportWithDefaultValue() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
}
@@ -177,66 +189,65 @@ public class ConditionMonitorTest extends SysuiTestCase {
mock(Monitor.Callback.class);
final Condition condition = mock(Condition.class);
when(condition.isConditionMet()).thenReturn(true);
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)));
- monitor.addCallback(callback1);
+ final Monitor monitor = new Monitor(mExecutor);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback1)
+ .addCondition(condition)
+ .build());
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- monitor.addCallback(callback2);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback2)
+ .addCondition(condition)
+ .build());
mExecutor.runAllReady();
verify(callback2).onConditionsChanged(eq(true));
}
@Test
public void addCallback_noConditions_reportAllConditionsMet() {
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>());
+ final Monitor monitor = new Monitor(mExecutor);
final Monitor.Callback callback = mock(Monitor.Callback.class);
- monitor.addCallback(callback);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
- public void addCallback_withMultipleInstancesOfTheSameCallback_registerOnlyOne() {
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>());
- final Monitor.Callback callback = mock(Monitor.Callback.class);
-
- // Adds the same instance multiple times.
- monitor.addCallback(callback);
- monitor.addCallback(callback);
- monitor.addCallback(callback);
+ public void removeCallback_noFailureOnDoubleRemove() {
+ final Condition condition = mock(Condition.class);
+ final Monitor monitor = new Monitor(mExecutor);
+ final Monitor.Callback callback =
+ mock(Monitor.Callback.class);
+ final Monitor.Subscription.Token token = monitor.addSubscription(
+ new Monitor.Subscription.Builder(callback).addCondition(condition).build()
+ );
+ monitor.removeSubscription(token);
+ mExecutor.runAllReady();
+ // Ensure second removal doesn't cause an exception.
+ monitor.removeSubscription(token);
mExecutor.runAllReady();
-
- // Callback should only be triggered once.
- verify(callback, times(1)).onConditionsChanged(true);
}
@Test
public void removeCallback_shouldNoLongerReceiveUpdate() {
final Condition condition = mock(Condition.class);
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)));
+ final Monitor monitor = new Monitor(mExecutor);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- monitor.addCallback(callback);
- monitor.removeCallback(callback);
+ final Monitor.Subscription.Token token = monitor.addSubscription(
+ new Monitor.Subscription.Builder(callback).addCondition(condition).build()
+ );
+ monitor.removeSubscription(token);
mExecutor.runAllReady();
clearInvocations(callback);
final ArgumentCaptor<Condition.Callback> conditionCallbackCaptor =
ArgumentCaptor.forClass(Condition.Callback.class);
verify(condition).addCallback(conditionCallbackCaptor.capture());
- final Condition.Callback conditionCallback = conditionCallbackCaptor.getValue();
-
- when(condition.isConditionMet()).thenReturn(true);
- conditionCallback.onConditionChanged(condition);
- mExecutor.runAllReady();
- verify(callback, never()).onConditionsChanged(true);
- when(condition.isConditionMet()).thenReturn(false);
- conditionCallback.onConditionChanged(condition);
- mExecutor.runAllReady();
- verify(callback, never()).onConditionsChanged(false);
+ final Condition.Callback conditionCallback = conditionCallbackCaptor.getValue();
+ verify(condition).removeCallback(conditionCallback);
}
@Test
@@ -245,14 +256,16 @@ public class ConditionMonitorTest extends SysuiTestCase {
mock(Monitor.Callback.class);
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback1);
- mConditionMonitor.addCallback(callback2);
+ final Monitor.Subscription.Token subscription1 =
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback1).build());
+ final Monitor.Subscription.Token subscription2 =
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback2).build());
- mConditionMonitor.removeCallback(callback1);
+ mConditionMonitor.removeSubscription(subscription1);
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition, never()).removeCallback(any()));
- mConditionMonitor.removeCallback(callback2);
+ mConditionMonitor.removeSubscription(subscription2);
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition).removeCallback(any()));
}
@@ -261,7 +274,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void updateCallbacks_allConditionsMet_reportTrue() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
clearInvocations(callback);
mCondition1.fakeUpdateCondition(true);
@@ -276,7 +289,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void updateCallbacks_oneConditionStoppedMeeting_reportFalse() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
@@ -292,7 +305,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
public void updateCallbacks_shouldOnlyUpdateWhenValueChanges() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
clearInvocations(callback);
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 03e18a04c2d5..8e00ccf68fb1 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -40,6 +40,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemProperties;
+import android.os.Trace;
import android.util.Slog;
import android.util.SparseArray;
@@ -144,15 +146,30 @@ public final class DeviceStateManagerService extends SystemService {
private Set<Integer> mDeviceStatesAvailableForAppRequests;
+ @VisibleForTesting
+ interface SystemPropertySetter {
+ void setDebugTracingDeviceStateProperty(String value);
+ }
+ @NonNull
+ private final SystemPropertySetter mSystemPropertySetter;
+
public DeviceStateManagerService(@NonNull Context context) {
this(context, DeviceStatePolicy.Provider
.fromResources(context.getResources())
.instantiate(context));
}
+ private DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
+ this(context, policy, (value) -> {
+ SystemProperties.set("debug.tracing.device_state", value);
+ });
+ }
+
@VisibleForTesting
- DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
+ DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy,
+ @NonNull SystemPropertySetter systemPropertySetter) {
super(context);
+ mSystemPropertySetter = systemPropertySetter;
// We use the DisplayThread because this service indirectly drives
// display (on/off) and window (position) events through its callbacks.
DisplayThread displayThread = DisplayThread.get();
@@ -462,6 +479,10 @@ public final class DeviceStateManagerService extends SystemService {
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_STATE_CHANGED,
newState.getIdentifier(), !mCommittedState.isPresent());
+ String traceString = newState.getIdentifier() + ":" + newState.getName();
+ Trace.instantForTrack(
+ Trace.TRACE_TAG_SYSTEM_SERVER, "DeviceStateChanged", traceString);
+ mSystemPropertySetter.setDebugTracingDeviceStateProperty(traceString);
mCommittedState = Optional.of(newState);
mPendingState = Optional.empty();
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index cf63b69254f8..6fd88411593f 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1057,7 +1057,17 @@ class AutomaticBrightnessController {
public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment);
- updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
+
+ // If rbc is turned on, off or there is a change in strength, we want to reset the short
+ // term model. Since the nits range at which brightness now operates has changed due to
+ // RBC/strength change, any short term model based on the previous range should be
+ // invalidated.
+ resetShortTermModel();
+
+ // When rbc is turned on, we want to accommodate this change in the short term model.
+ if (applyAdjustment) {
+ setScreenBrightnessByUser(getAutomaticScreenBrightness());
+ }
}
private final class AutomaticBrightnessHandler extends Handler {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index a5bb716e67b7..d05a902c6593 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -657,12 +657,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
-
- // If rbc is turned on, off or there is a change in strength, we want to reset the short
- // term model. Since the nits range at which brightness now operates has changed due to
- // RBC/strength change, any short term model based on the previous range should be
- // invalidated.
- mAutomaticBrightnessController.resetShortTermModel();
}
/**
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index dd0ec948aa3a..43d62aaa120a 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -21,6 +21,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.AsyncTask;
+import android.os.Trace;
import android.os.UserHandle;
import android.util.Slog;
import android.webkit.UserPackage;
@@ -265,10 +266,12 @@ class WebViewUpdateServiceImpl {
// Either the current relro creation isn't done yet, or the new relro creatioin
// hasn't kicked off yet (the last relro creation used an out-of-date WebView).
webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
- Slog.e(TAG, "Timed out waiting for relro creation, relros started "
+ String timeoutError = "Timed out waiting for relro creation, relros started "
+ mNumRelroCreationsStarted
+ " relros finished " + mNumRelroCreationsFinished
- + " package dirty? " + mWebViewPackageDirty);
+ + " package dirty? " + mWebViewPackageDirty;
+ Slog.e(TAG, timeoutError);
+ Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, timeoutError);
}
}
if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 3f31ad503c01..53f2c7146656 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -314,6 +314,10 @@ public class AppTransition implements Dump {
setAppTransitionState(APP_STATE_TIMEOUT);
}
+ @ColorInt int getNextAppTransitionBackgroundColor() {
+ return mNextAppTransitionBackgroundColor;
+ }
+
HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) {
AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
container.hashCode());
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index fd0631320520..7ca38b8fcc00 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -99,19 +99,28 @@ public class DisplayFrames {
state.setRoundedCorners(roundedCorners);
state.setPrivacyIndicatorBounds(indicatorBounds);
state.getDisplayCutoutSafe(safe);
- if (!cutout.isEmpty()) {
+ if (safe.left > unrestricted.left) {
state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom);
+ } else {
+ state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
+ }
+ if (safe.top > unrestricted.top) {
state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, unrestricted.right, safe.top);
+ } else {
+ state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
+ }
+ if (safe.right < unrestricted.right) {
state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(
safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom);
+ } else {
+ state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
+ }
+ if (safe.bottom < unrestricted.bottom) {
state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(
unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom);
} else {
- state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
- state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
- state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
}
return true;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 878413cb9d78..ad158c7b45b9 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
@@ -431,6 +432,7 @@ class RemoteAnimationController implements DeathRecipient {
final WindowContainer mWindowContainer;
final Rect mStartBounds;
final boolean mShowBackdrop;
+ @ColorInt int mBackdropColor = 0;
private @RemoteAnimationTarget.Mode int mMode = RemoteAnimationTarget.MODE_CHANGING;
RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
@@ -456,6 +458,10 @@ class RemoteAnimationController implements DeathRecipient {
}
}
+ void setBackDropColor(@ColorInt int backdropColor) {
+ mBackdropColor = backdropColor;
+ }
+
RemoteAnimationTarget createRemoteAnimationTarget() {
if (mAdapter == null
|| mAdapter.mCapturedFinishCallback == null
@@ -510,6 +516,12 @@ class RemoteAnimationController implements DeathRecipient {
}
@Override
+ @ColorInt
+ public int getBackgroundColor() {
+ return mRecord.mBackdropColor;
+ }
+
+ @Override
public boolean getShowBackground() {
return mShowBackdrop;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fc1b89348c25..3a272859c70c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4427,13 +4427,13 @@ class Task extends TaskFragment {
: WINDOWING_MODE_FULLSCREEN;
}
if (currentMode == WINDOWING_MODE_PINNED) {
+ // In the case that we've disabled affecting the SysUI flags as a part of seamlessly
+ // transferring the transform on the leash to the task, reset this state once we're
+ // moving out of pip
+ setCanAffectSystemUiFlags(true);
mRootWindowContainer.notifyActivityPipModeChanged(this, null);
}
if (likelyResolvedMode == WINDOWING_MODE_PINNED) {
- // In the case that we've disabled affecting the SysUI flags as a part of seamlessly
- // transferring the transform on the leash to the task, reset this state once we've
- // actually entered pip
- setCanAffectSystemUiFlags(true);
if (taskDisplayArea.getRootPinnedTask() != null) {
// Can only have 1 pip at a time, so replace an existing pip
taskDisplayArea.getRootPinnedTask().dismissPip();
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index d8404a79e794..3c0cac0079e8 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -305,6 +305,16 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
return mFlags;
}
+ @VisibleForTesting
+ SurfaceControl.Transaction getStartTransaction() {
+ return mStartTransaction;
+ }
+
+ @VisibleForTesting
+ SurfaceControl.Transaction getFinishTransaction() {
+ return mFinishTransaction;
+ }
+
/** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
void startCollecting(long timeoutMs) {
if (mState != STATE_PENDING) {
@@ -771,6 +781,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
}
mState = STATE_PLAYING;
+ mStartTransaction = transaction;
+ mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
mController.moveToPlaying(this);
if (dc.isKeyguardLocked()) {
@@ -856,8 +868,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
if (controller != null && mTargets.contains(dc)) {
controller.setupStartTransaction(transaction);
}
- mStartTransaction = transaction;
- mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
buildFinishTransaction(mFinishTransaction, info.getRootLeash());
if (mController.getTransitionPlayer() != null) {
mController.dispatchLegacyAppTransitionStarting(info);
diff --git a/services/core/java/com/android/server/wm/TransitionTracer.java b/services/core/java/com/android/server/wm/TransitionTracer.java
index 192b9abc62a7..b1951e038177 100644
--- a/services/core/java/com/android/server/wm/TransitionTracer.java
+++ b/services/core/java/com/android/server/wm/TransitionTracer.java
@@ -23,8 +23,10 @@ import static com.android.server.wm.shell.ChangeInfo.HAS_CHANGED;
import static com.android.server.wm.shell.ChangeInfo.TRANSIT_MODE;
import static com.android.server.wm.shell.ChangeInfo.WINDOW_IDENTIFIER;
import static com.android.server.wm.shell.Transition.CHANGE;
+import static com.android.server.wm.shell.Transition.FINISH_TRANSACTION_ID;
import static com.android.server.wm.shell.Transition.FLAGS;
import static com.android.server.wm.shell.Transition.ID;
+import static com.android.server.wm.shell.Transition.START_TRANSACTION_ID;
import static com.android.server.wm.shell.Transition.STATE;
import static com.android.server.wm.shell.Transition.TIMESTAMP;
import static com.android.server.wm.shell.Transition.TRANSITION_TYPE;
@@ -82,6 +84,13 @@ public class TransitionTracer {
outputStream.write(TRANSITION_TYPE, transition.mType);
outputStream.write(STATE, transition.getState());
outputStream.write(FLAGS, transition.getFlags());
+ if (transition.getStartTransaction() != null) {
+ outputStream.write(START_TRANSACTION_ID, transition.getStartTransaction().getId());
+ }
+ if (transition.getFinishTransaction() != null) {
+ outputStream.write(FINISH_TRANSACTION_ID,
+ transition.getFinishTransaction().getId());
+ }
for (int i = 0; i < transition.mChanges.size(); ++i) {
final WindowContainer window = transition.mChanges.keyAt(i);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cfc4db969a6f..59aed833f3f3 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2949,11 +2949,15 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
// Here we load App XML in order to read com.android.R.styleable#Animation_showBackdrop.
boolean showBackdrop = false;
+ // Optionally set backdrop color if App explicitly provides it through
+ // {@link Activity#overridePendingTransition(int, int, int)}.
+ @ColorInt int backdropColor = 0;
if (controller.isFromActivityEmbedding()) {
final int animAttr = AppTransition.mapOpenCloseTransitTypes(transit, enter);
final Animation a = animAttr != 0
? appTransition.loadAnimationAttr(lp, animAttr, transit) : null;
showBackdrop = a != null && a.getShowBackdrop();
+ backdropColor = appTransition.getNextAppTransitionBackgroundColor();
}
final Rect localBounds = new Rect(mTmpRect);
localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
@@ -2961,6 +2965,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
controller.createRemoteAnimationRecord(
this, mTmpPoint, localBounds, screenBounds,
(isChanging ? mSurfaceFreezer.mFreezeBounds : null), showBackdrop);
+ if (backdropColor != 0) {
+ adapters.setBackDropColor(backdropColor);
+ }
if (!isChanging) {
adapters.setMode(enter
? RemoteAnimationTarget.MODE_OPENING
diff --git a/services/proguard.flags b/services/proguard.flags
index bad02b47031c..c648f7d3ac45 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -68,6 +68,9 @@
# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+# OEM provided DisplayAreaPolicy.Provider defined in frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification class com.android.server.wm.** implements com.android.server.wm.DisplayAreaPolicy$Provider
+
# JNI keep rules
# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
# frameworks/base/services/core/jni/onload.cpp.
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index fe3034dc569d..038cbc032375 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -76,12 +76,15 @@ public final class DeviceStateManagerServiceTest {
private TestDeviceStatePolicy mPolicy;
private TestDeviceStateProvider mProvider;
private DeviceStateManagerService mService;
+ private TestSystemPropertySetter mSysPropSetter;
@Before
public void setup() {
mProvider = new TestDeviceStateProvider();
mPolicy = new TestDeviceStatePolicy(mProvider);
- mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy);
+ mSysPropSetter = new TestSystemPropertySetter();
+ mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy,
+ mSysPropSetter);
// Necessary to allow us to check for top app process id in tests
mService.mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
@@ -107,6 +110,8 @@ public final class DeviceStateManagerServiceTest {
public void baseStateChanged() {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -115,6 +120,8 @@ public final class DeviceStateManagerServiceTest {
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -128,6 +135,8 @@ public final class DeviceStateManagerServiceTest {
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -136,6 +145,8 @@ public final class DeviceStateManagerServiceTest {
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -157,6 +168,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -170,6 +183,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -182,6 +197,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -193,6 +210,8 @@ public final class DeviceStateManagerServiceTest {
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE);
@@ -211,6 +230,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -223,6 +244,8 @@ public final class DeviceStateManagerServiceTest {
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -315,6 +338,8 @@ public final class DeviceStateManagerServiceTest {
TestDeviceStateManagerCallback.STATUS_ACTIVE);
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -333,6 +358,8 @@ public final class DeviceStateManagerServiceTest {
TestDeviceStateManagerCallback.STATUS_CANCELED);
// Committed state is set back to the requested state once the override is cleared.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -385,9 +412,10 @@ public final class DeviceStateManagerServiceTest {
// callback.
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
TestDeviceStateManagerCallback.STATUS_UNKNOWN);
-
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -397,6 +425,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -412,6 +442,8 @@ public final class DeviceStateManagerServiceTest {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -458,6 +490,8 @@ public final class DeviceStateManagerServiceTest {
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -471,6 +505,8 @@ public final class DeviceStateManagerServiceTest {
// Committed state is set back to the requested state once the override is cleared.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -495,6 +531,8 @@ public final class DeviceStateManagerServiceTest {
TestDeviceStateManagerCallback.STATUS_ACTIVE);
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -509,6 +547,8 @@ public final class DeviceStateManagerServiceTest {
// Committed state is set back to the requested state as the override state is no longer
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -673,4 +713,18 @@ public final class DeviceStateManagerServiceTest {
return mLastNotifiedStatus.getOrDefault(requestToken, STATUS_UNKNOWN);
}
}
+
+ private static final class TestSystemPropertySetter implements
+ DeviceStateManagerService.SystemPropertySetter {
+ private String mValue;
+
+ @Override
+ public void setDebugTracingDeviceStateProperty(String value) {
+ mValue = value;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index b0c52f1fdbb8..9d82f1a90c77 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -258,29 +259,36 @@ public class AutomaticBrightnessControllerTest {
@Test
public void testRecalculateSplines() throws Exception {
// Enabling the light sensor, and setting the ambient lux to 1000
+ int currentLux = 1000;
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, currentLux));
- //Setting the brightnessFloat to 0.5f
- float currentBrightnessFloat = 0.5f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(currentBrightnessFloat);
+ // User sets brightness to 0.5f
+ when(mBrightnessMappingStrategy.getBrightness(currentLux,
+ null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(0.5f);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
- currentBrightnessFloat /* brightness */, false /* userChangedBrightness */,
- 0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
+ 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
+ false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
- // Adjusting spline, and accordingly remapping the current 0.5f brightnessFloat to 0.3f
- float updatedBrightnessFloat = 0.3f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(updatedBrightnessFloat);
- float[] adjustments = new float[]{0.2f, 0.5f};
+ //Recalculating the spline with RBC enabled, verifying that the short term model is reset,
+ //and the interaction is learnt in short term model
+ float[] adjustments = new float[]{0.2f, 0.6f};
mController.recalculateSplines(true, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- assertEquals(mController.getAutomaticScreenBrightness(), updatedBrightnessFloat, EPSILON);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+
+ clearInvocations(mBrightnessMappingStrategy);
+
+ // Verify short term model is not learnt when RBC is disabled
+ mController.recalculateSplines(false, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
+ verify(mBrightnessMappingStrategy).recalculateSplines(false, adjustments);
+ verifyNoMoreInteractions(mBrightnessMappingStrategy);
}
@Test