summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapi/system-current.txt1
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.cpp48
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.h10
-rw-r--r--cmds/statsd/src/condition/ConditionTracker.h41
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.cpp98
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.h19
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp13
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h5
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp247
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h90
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp55
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h14
-rw-r--r--cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp18
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp486
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp132
-rw-r--r--core/java/android/app/ActivityThread.java5
-rw-r--r--core/java/android/app/ContextImpl.java20
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java15
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutorHelper.java3
-rw-r--r--core/java/android/companion/TEST_MAPPING12
-rw-r--r--core/java/android/content/pm/PackageManager.java9
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java6
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java14
-rw-r--r--core/java/android/inputmethodservice/TEST_MAPPING7
-rw-r--r--core/java/android/os/UserManager.java56
-rw-r--r--core/java/android/provider/CallLog.java2
-rw-r--r--core/java/android/provider/DocumentsProvider.java17
-rw-r--r--core/java/android/telephony/PhoneStateListener.java18
-rw-r--r--core/java/android/view/FrameMetrics.java7
-rw-r--r--core/java/android/view/NotificationHeaderView.java4
-rw-r--r--core/java/android/view/inputmethod/TEST_MAPPING18
-rw-r--r--core/java/android/window/ITaskOrganizerController.aidl3
-rw-r--r--core/java/android/window/TaskOrganizer.java5
-rw-r--r--core/java/android/window/TaskOrganizerTaskEmbedder.java2
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java234
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java181
-rw-r--r--core/java/com/android/internal/jank/PerfettoTrigger.java115
-rw-r--r--core/java/com/android/internal/view/ScrollCaptureViewHelper.java37
-rw-r--r--core/java/com/android/internal/view/ScrollCaptureViewSupport.java94
-rw-r--r--core/java/com/android/internal/view/ScrollViewCaptureHelper.java40
-rw-r--r--core/jni/android_media_AudioTrack.cpp76
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--core/res/res/values-cs/strings.xml6
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-eu/strings.xml4
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-ne/strings.xml16
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java130
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java120
-rw-r--r--core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java200
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java72
-rw-r--r--media/java/android/media/AudioTrack.java9
-rw-r--r--media/java/android/media/MediaPlayer.java5
-rw-r--r--media/java/android/media/PlayerBase.java5
-rw-r--r--media/jni/android_media_MediaPlayer.cpp9
-rw-r--r--media/packages/BluetoothMidiService/Android.bp1
-rw-r--r--media/packages/BluetoothMidiService/AndroidManifest.xml2
-rw-r--r--media/packages/BluetoothMidiService/AndroidManifestBase.xml2
-rw-r--r--non-updatable-api/system-current.txt1
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java2
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java64
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java38
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java9
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java22
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java61
-rw-r--r--packages/CompanionDeviceManager/TEST_MAPPING12
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml31
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml27
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java32
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java20
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java98
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java30
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java42
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/dagger/AppOpsModule.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java268
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java)191
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java113
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java112
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/dagger/TunerModule.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java (renamed from packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java)37
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java65
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java)25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java67
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java69
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java10
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java50
-rw-r--r--services/companion/TEST_MAPPING12
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java3
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java135
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/Face10.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java2
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java2
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java4
-rw-r--r--services/core/java/com/android/server/inputmethod/TEST_MAPPING7
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsStorage.java2
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java101
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java32
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java34
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java2
-rw-r--r--services/core/java/com/android/server/slice/SliceFullAccessList.java2
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java5
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimator.java22
-rw-r--r--services/core/java/com/android/server/wm/Task.java8
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java31
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java22
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/Owners.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java77
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java1
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java2
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java63
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java17
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java39
-rw-r--r--tests/RollbackTest/Android.bp1
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java2
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java3
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java2
-rw-r--r--tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java2
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java5
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java10
-rw-r--r--wifi/tests/src/android/net/wifi/ScanResultTest.java8
228 files changed, 5042 insertions, 1987 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 41e859363581..00a59bf4f1e3 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -219,6 +219,7 @@ package android {
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+ field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
diff --git a/api/test-current.txt b/api/test-current.txt
index 529dcf71ef6e..5741fe7e90a4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5579,7 +5579,7 @@ package android.window {
method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer();
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer();
}
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 3b65f8225ee9..4574b2e34547 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -25,8 +25,9 @@ namespace statsd {
using std::unordered_map;
using std::vector;
-CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index)
- : ConditionTracker(id, index) {
+CombinationConditionTracker::CombinationConditionTracker(const int64_t& id, const int index,
+ const uint64_t protoHash)
+ : ConditionTracker(id, index, protoHash) {
VLOG("creating CombinationConditionTracker %lld", (long long)mConditionId);
}
@@ -122,6 +123,49 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
return true;
}
+bool CombinationConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ mTrackerIndex.clear();
+ mChildren.clear();
+ mUnSlicedChildren.clear();
+ mSlicedChildren.clear();
+ Predicate_Combination combinationCondition = allConditionProtos[mIndex].combination();
+
+ for (const int64_t child : combinationCondition.predicate()) {
+ const auto& it = conditionTrackerMap.find(child);
+
+ if (it == conditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)child);
+ return false;
+ }
+
+ int childIndex = it->second;
+ const sp<ConditionTracker>& childTracker = allConditionTrackers[childIndex];
+
+ // Ensures that the child's tracker indices are updated.
+ if (!childTracker->onConfigUpdated(allConditionProtos, childIndex, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap)) {
+ ALOGW("Child update failed %lld ", (long long)child);
+ return false;
+ }
+
+ if (allConditionTrackers[childIndex]->isSliced()) {
+ mSlicedChildren.push_back(childIndex);
+ } else {
+ mUnSlicedChildren.push_back(childIndex);
+ }
+ mChildren.push_back(childIndex);
+ mTrackerIndex.insert(childTracker->getAtomMatchingTrackerIndex().begin(),
+ childTracker->getAtomMatchingTrackerIndex().end());
+ }
+ return true;
+}
+
void CombinationConditionTracker::isConditionMet(
const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions,
const bool isPartialLink,
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index a7fac3deaabe..672d61c82268 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -24,9 +24,9 @@ namespace android {
namespace os {
namespace statsd {
-class CombinationConditionTracker : public virtual ConditionTracker {
+class CombinationConditionTracker : public ConditionTracker {
public:
- CombinationConditionTracker(const int64_t& id, const int index);
+ CombinationConditionTracker(const int64_t& id, const int index, const uint64_t protoHash);
~CombinationConditionTracker();
@@ -35,6 +35,11 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
std::vector<ConditionState>& conditionCache) override;
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
+
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -102,6 +107,7 @@ private:
std::vector<int> mSlicedChildren;
std::vector<int> mUnSlicedChildren;
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 4e1253506be7..3bf4e636be89 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -31,18 +31,17 @@ namespace statsd {
class ConditionTracker : public virtual RefBase {
public:
- ConditionTracker(const int64_t& id, const int index)
+ ConditionTracker(const int64_t& id, const int index, const uint64_t protoHash)
: mConditionId(id),
mIndex(index),
mInitialized(false),
mTrackerIndex(),
mUnSlicedPartCondition(ConditionState::kUnknown),
- mSliced(false){};
+ mSliced(false),
+ mProtoHash(protoHash){};
virtual ~ConditionTracker(){};
- inline const int64_t& getId() { return mConditionId; }
-
// Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
// be done in the constructor, but we do it separately because (1) easy to return a bool to
// indicate whether the initialization is successful. (2) makes unit test easier.
@@ -50,7 +49,7 @@ public:
// fill the condition cache with the current condition.
// allConditionConfig: the list of all Predicate config from statsd_config.
// allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
- // need to call init() on children conditions)
+ // need to call init() on child conditions)
// conditionIdIndexMap: the mapping from condition id to its index.
// stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
// conditionCache: tracks initial conditions of all ConditionTrackers. returns the
@@ -60,6 +59,26 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap,
std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;
+ // Update appropriate state on config updates. Primarily, all indices need to be updated.
+ // This predicate and all of its children are guaranteed to be preserved across the update.
+ // This function is recursive and will call onConfigUpdated on child conditions. It does not
+ // manage cycle detection since all preserved conditions should not have any cycles.
+ //
+ // allConditionProtos: the new predicates.
+ // index: the new index of this tracker in allConditionProtos and allConditionTrackers.
+ // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
+ // need to call onConfigUpdated() on child conditions)
+ // [atomMatchingTrackerMap]: map of atom matcher id to index after the config update
+ // [conditionTrackerMap]: map of condition tracker id to index after the config update.
+ // returns whether or not the update is successful
+ virtual bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) {
+ mIndex = index;
+ return true;
+ }
+
// evaluate current condition given the new event.
// event: the new log event
// eventMatcherValues: the results of the AtomMatchingTrackers. AtomMatchingTrackers always
@@ -112,6 +131,10 @@ public:
return mConditionId;
}
+ inline uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
virtual void getTrueSlicedDimensions(
const std::vector<sp<ConditionTracker>>& allConditions,
std::set<HashableDimensionKey>* dimensions) const = 0;
@@ -133,7 +156,7 @@ protected:
const int64_t mConditionId;
// the index of this condition in the manager's condition list.
- const int mIndex;
+ int mIndex;
// if it's properly initialized.
bool mInitialized;
@@ -151,6 +174,12 @@ protected:
ConditionState mUnSlicedPartCondition;
bool mSliced;
+
+ // Hash of the Predicate's proto bytes from StatsdConfig.
+ // Used to determine if the definition of this condition has changed across a config update.
+ const uint64_t mProtoHash;
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index f45759b6a77e..1dcc8f96131a 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -27,54 +27,21 @@ namespace statsd {
using std::unordered_map;
SimpleConditionTracker::SimpleConditionTracker(
- const ConfigKey& key, const int64_t& id, const int index,
+ const ConfigKey& key, const int64_t& id, const uint64_t protoHash, const int index,
const SimplePredicate& simplePredicate,
- const unordered_map<int64_t, int>& trackerNameIndexMap)
- : ConditionTracker(id, index), mConfigKey(key), mContainANYPositionInInternalDimensions(false) {
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap)
+ : ConditionTracker(id, index, protoHash),
+ mConfigKey(key),
+ mContainANYPositionInInternalDimensions(false) {
VLOG("creating SimpleConditionTracker %lld", (long long)mConditionId);
mCountNesting = simplePredicate.count_nesting();
- if (simplePredicate.has_start()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.start());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
- return;
- }
- mStartLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStartLogMatcherIndex);
- } else {
- mStartLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
- return;
- }
- mStopLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopLogMatcherIndex);
- } else {
- mStopLogMatcherIndex = -1;
- }
-
- if (simplePredicate.has_stop_all()) {
- auto pair = trackerNameIndexMap.find(simplePredicate.stop_all());
- if (pair == trackerNameIndexMap.end()) {
- ALOGW("Stop all matcher %lld found in the config", (long long)simplePredicate.stop_all());
- return;
- }
- mStopAllLogMatcherIndex = pair->second;
- mTrackerIndex.insert(mStopAllLogMatcherIndex);
- } else {
- mStopAllLogMatcherIndex = -1;
- }
+ setMatcherIndices(simplePredicate, atomMatchingTrackerMap);
if (simplePredicate.has_dimensions()) {
translateFieldMatcher(simplePredicate.dimensions(), &mOutputDimensions);
if (mOutputDimensions.size() > 0) {
mSliced = true;
- mDimensionTag = mOutputDimensions[0].mMatcher.getTag();
}
mContainANYPositionInInternalDimensions = HasPositionANY(simplePredicate.dimensions());
}
@@ -106,6 +73,59 @@ bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
return mInitialized;
}
+bool SimpleConditionTracker::onConfigUpdated(
+ const vector<Predicate>& allConditionProtos, const int index,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& conditionTrackerMap) {
+ ConditionTracker::onConfigUpdated(allConditionProtos, index, allConditionTrackers,
+ atomMatchingTrackerMap, conditionTrackerMap);
+ setMatcherIndices(allConditionProtos[index].simple_predicate(), atomMatchingTrackerMap);
+ return true;
+}
+
+void SimpleConditionTracker::setMatcherIndices(
+ const SimplePredicate& simplePredicate,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ mTrackerIndex.clear();
+ if (simplePredicate.has_start()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.start());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Start matcher %lld not found in the config", (long long)simplePredicate.start());
+ return;
+ }
+ mStartLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStartLogMatcherIndex);
+ } else {
+ mStartLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop matcher %lld not found in the config", (long long)simplePredicate.stop());
+ return;
+ }
+ mStopLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopLogMatcherIndex);
+ } else {
+ mStopLogMatcherIndex = -1;
+ }
+
+ if (simplePredicate.has_stop_all()) {
+ auto pair = atomMatchingTrackerMap.find(simplePredicate.stop_all());
+ if (pair == atomMatchingTrackerMap.end()) {
+ ALOGW("Stop all matcher %lld found in the config",
+ (long long)simplePredicate.stop_all());
+ return;
+ }
+ mStopAllLogMatcherIndex = pair->second;
+ mTrackerIndex.insert(mStopAllLogMatcherIndex);
+ } else {
+ mStopAllLogMatcherIndex = -1;
+ }
+}
+
void SimpleConditionTracker::dumpState() {
VLOG("%lld DUMP:", (long long)mConditionId);
for (const auto& pair : mSlicedConditionState) {
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index 1a9e35e38207..7a8b40108448 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -27,11 +27,11 @@ namespace android {
namespace os {
namespace statsd {
-class SimpleConditionTracker : public virtual ConditionTracker {
+class SimpleConditionTracker : public ConditionTracker {
public:
- SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const int index,
- const SimplePredicate& simplePredicate,
- const std::unordered_map<int64_t, int>& trackerNameIndexMap);
+ SimpleConditionTracker(const ConfigKey& key, const int64_t& id, const uint64_t protoHash,
+ const int index, const SimplePredicate& simplePredicate,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap);
~SimpleConditionTracker();
@@ -40,6 +40,11 @@ public:
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
std::vector<ConditionState>& conditionCache) override;
+ bool onConfigUpdated(const std::vector<Predicate>& allConditionProtos, const int index,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap) override;
+
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
const std::vector<sp<ConditionTracker>>& mAllConditions,
@@ -112,10 +117,11 @@ private:
std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
- int mDimensionTag;
-
std::map<HashableDimensionKey, int> mSlicedConditionState;
+ void setMatcherIndices(const SimplePredicate& predicate,
+ const std::unordered_map<int64_t, int>& logTrackerMap);
+
void handleStopAll(std::vector<ConditionState>& conditionCache,
std::vector<bool>& changedCache);
@@ -129,6 +135,7 @@ private:
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedCondition);
FRIEND_TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim);
FRIEND_TEST(SimpleConditionTrackerTest, TestStopAll);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateConditions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 5a520326116a..a0c701ea4229 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -80,7 +80,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mConfigValid = initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
- mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers,
+ mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mAllAnomalyTrackers,
mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap,
mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
mDeactivationAtomTrackerToMetricMap, mAlertTrackerMap, mMetricIndexesWithActivation,
@@ -204,13 +204,20 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
const sp<AlarmMonitor>& periodicAlarmMonitor) {
vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int64_t, int> newConditionTrackerMap;
mTagIds.clear();
+ mTrackerToConditionMap.clear();
mConfigValid = updateStatsdConfig(
mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap, mTagIds,
- newAtomMatchingTrackers, newAtomMatchingTrackerMap);
+ timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
+ mAllConditionTrackers, mConditionTrackerMap, mTagIds, newAtomMatchingTrackers,
+ newAtomMatchingTrackerMap, newConditionTrackers, newConditionTrackerMap,
+ mTrackerToConditionMap);
mAllAtomMatchingTrackers = newAtomMatchingTrackers;
mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
+ mAllConditionTrackers = newConditionTrackers;
+ mConditionTrackerMap = newConditionTrackerMap;
return mConfigValid;
}
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 6f4b2d7e9fa4..bd0c8161a884 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -242,9 +242,12 @@ private:
// To make updating configs faster, we map the id of a AtomMatchingTracker, MetricProducer, and
// ConditionTracker to its index in the corresponding vector.
- // Maps the id of an atom matcher to its index in mAllAtomMatchingTrackers.
+ // Maps the id of an atom matching tracker to its index in mAllAtomMatchingTrackers.
std::unordered_map<int64_t, int> mAtomMatchingTrackerMap;
+ // Maps the id of a condition tracker to its index in mAllConditionTrackers.
+ std::unordered_map<int64_t, int> mConditionTrackerMap;
+
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 0983dc0b2c83..bd60b6bfcb8e 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -15,6 +15,7 @@
*/
#define DEBUG false // STOPSHIP if true
+#include "Log.h"
#include "config_update_utils.h"
@@ -44,7 +45,7 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
// Check if new matcher.
const auto& oldAtomMatchingTrackerIt = oldAtomMatchingTrackerMap.find(id);
if (oldAtomMatchingTrackerIt == oldAtomMatchingTrackerMap.end()) {
- matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
+ matchersToUpdate[matcherIdx] = UPDATE_NEW;
return true;
}
@@ -103,11 +104,13 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
return true;
}
-bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers) {
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ set<int>& allTagIds,
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ set<int64_t>& replacedMatchers) {
const int atomMatcherCount = config.atom_matcher_size();
vector<AtomMatcher> matcherProtos;
@@ -157,7 +160,10 @@ bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
newAtomMatchingTrackers.push_back(tracker);
break;
}
- case UPDATE_REPLACE: {
+ case UPDATE_REPLACE:
+ replacedMatchers.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new matcher.
+ case UPDATE_NEW: {
sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(matcher, i, uidMap);
if (tracker == nullptr) {
return false;
@@ -187,6 +193,207 @@ bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
return true;
}
+// Recursive function to determine if a condition needs to be updated. Populates conditionsToUpdate.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& newConditionTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ vector<UpdateStatus>& conditionsToUpdate,
+ vector<bool>& cycleTracker) {
+ // Have already examined this condition.
+ if (conditionsToUpdate[conditionIdx] != UPDATE_UNKNOWN) {
+ return true;
+ }
+
+ const Predicate& predicate = config.predicate(conditionIdx);
+ int64_t id = predicate.id();
+ // Check if new condition.
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing condition. Check if it has changed.
+ string serializedCondition;
+ if (!predicate.SerializeToString(&serializedCondition)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)id);
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedCondition);
+ if (newProtoHash != oldConditionTrackers[oldConditionTrackerIt->second]->getProtoHash()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ // Need to check if any of the underlying matchers changed.
+ const SimplePredicate& simplePredicate = predicate.simple_predicate();
+ if (simplePredicate.has_start()) {
+ if (replacedMatchers.find(simplePredicate.start()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop()) {
+ if (replacedMatchers.find(simplePredicate.stop()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ if (simplePredicate.has_stop_all()) {
+ if (replacedMatchers.find(simplePredicate.stop_all()) != replacedMatchers.end()) {
+ conditionsToUpdate[conditionIdx] = UPDATE_REPLACE;
+ return true;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = UPDATE_PRESERVE;
+ return true;
+ }
+ case Predicate::ContentsCase::kCombination: {
+ // Need to recurse on the children to see if any of the child predicates changed.
+ cycleTracker[conditionIdx] = true;
+ UpdateStatus status = UPDATE_PRESERVE;
+ for (const int64_t childPredicateId : predicate.combination().predicate()) {
+ const auto& childIt = newConditionTrackerMap.find(childPredicateId);
+ if (childIt == newConditionTrackerMap.end()) {
+ ALOGW("Predicate %lld not found in the config", (long long)childPredicateId);
+ return false;
+ }
+ const int childIdx = childIt->second;
+ if (cycleTracker[childIdx]) {
+ ALOGE("Cycle detected in predicate config");
+ return false;
+ }
+ if (!determineConditionUpdateStatus(config, childIdx, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate,
+ cycleTracker)) {
+ return false;
+ }
+
+ if (conditionsToUpdate[childIdx] == UPDATE_REPLACE) {
+ status = UPDATE_REPLACE;
+ break;
+ }
+ }
+ conditionsToUpdate[conditionIdx] = status;
+ cycleTracker[conditionIdx] = false;
+ return true;
+ }
+ default: {
+ ALOGE("Predicate \"%lld\" malformed", (long long)id);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const set<int64_t>& replacedMatchers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int, vector<int>>& trackerToConditionMap,
+ vector<ConditionState>& conditionCache, set<int64_t>& replacedConditions) {
+ vector<Predicate> conditionProtos;
+ const int conditionTrackerCount = config.predicate_size();
+ conditionProtos.reserve(conditionTrackerCount);
+ newConditionTrackers.reserve(conditionTrackerCount);
+ conditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
+
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& condition = config.predicate(i);
+ if (newConditionTrackerMap.find(condition.id()) != newConditionTrackerMap.end()) {
+ ALOGE("Duplicate Predicate found!");
+ return false;
+ }
+ newConditionTrackerMap[condition.id()] = i;
+ conditionProtos.push_back(condition);
+ }
+
+ vector<UpdateStatus> conditionsToUpdate(conditionTrackerCount, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(conditionTrackerCount, false);
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ if (!determineConditionUpdateStatus(config, i, oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, replacedMatchers,
+ conditionsToUpdate, cycleTracker)) {
+ return false;
+ }
+ }
+
+ // Update status has been determined for all conditions. Now perform the update.
+ set<int> preservedConditions;
+ for (int i = 0; i < conditionTrackerCount; i++) {
+ const Predicate& predicate = config.predicate(i);
+ const int64_t id = predicate.id();
+ switch (conditionsToUpdate[i]) {
+ case UPDATE_PRESERVE: {
+ preservedConditions.insert(i);
+ const auto& oldConditionTrackerIt = oldConditionTrackerMap.find(id);
+ if (oldConditionTrackerIt == oldConditionTrackerMap.end()) {
+ ALOGE("Could not find Predicate %lld in the previous config, but expected it "
+ "to be there",
+ (long long)id);
+ return false;
+ }
+ const int oldIndex = oldConditionTrackerIt->second;
+ newConditionTrackers.push_back(oldConditionTrackers[oldIndex]);
+ break;
+ }
+ case UPDATE_REPLACE:
+ replacedConditions.insert(id);
+ [[fallthrough]]; // Intentionally fallthrough to create the new condition tracker.
+ case UPDATE_NEW: {
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, predicate, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
+ }
+ newConditionTrackers.push_back(tracker);
+ break;
+ }
+ default: {
+ ALOGE("Condition \"%lld\" update state is unknown. This should never happen",
+ (long long)id);
+ return false;
+ }
+ }
+ }
+
+ // Update indices of preserved predicates.
+ for (const int conditionIndex : preservedConditions) {
+ if (!newConditionTrackers[conditionIndex]->onConfigUpdated(
+ conditionProtos, conditionIndex, newConditionTrackers, atomMatchingTrackerMap,
+ newConditionTrackerMap)) {
+ ALOGE("Failed to update condition %lld",
+ (long long)newConditionTrackers[conditionIndex]->getConditionId());
+ return false;
+ }
+ }
+
+ std::fill(cycleTracker.begin(), cycleTracker.end(), false);
+ for (int conditionIndex = 0; conditionIndex < conditionTrackerCount; conditionIndex++) {
+ const sp<ConditionTracker>& conditionTracker = newConditionTrackers[conditionIndex];
+ // Calling init on preserved conditions is OK. It is needed to fill the condition cache.
+ if (!conditionTracker->init(conditionProtos, newConditionTrackers, newConditionTrackerMap,
+ cycleTracker, conditionCache)) {
+ return false;
+ }
+ for (const int trackerIndex : conditionTracker->getAtomMatchingTrackerIndex()) {
+ vector<int>& conditionList = trackerToConditionMap[trackerIndex];
+ conditionList.push_back(conditionIndex);
+ }
+ }
+ return true;
+}
+
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -194,14 +401,34 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const int64_t currentTimeNs,
const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const unordered_map<int64_t, int>& oldConditionTrackerMap,
set<int>& allTagIds,
vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap) {
- if (!updateAtomTrackers(config, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers,
- allTagIds, newAtomMatchingTrackerMap, newAtomMatchingTrackers)) {
+ unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& newConditionTrackers,
+ unordered_map<int64_t, int>& newConditionTrackerMap,
+ unordered_map<int, vector<int>>& trackerToConditionMap) {
+ set<int64_t> replacedMatchers;
+ set<int64_t> replacedConditions;
+ vector<ConditionState> conditionCache;
+
+ if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, allTagIds, newAtomMatchingTrackerMap,
+ newAtomMatchingTrackers, replacedMatchers)) {
ALOGE("updateAtomMatchingTrackers failed");
return false;
}
+ VLOG("updateAtomMatchingTrackers succeeded");
+
+ if (!updateConditions(key, config, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers, newConditionTrackerMap,
+ newConditionTrackers, trackerToConditionMap, conditionCache,
+ replacedConditions)) {
+ ALOGE("updateConditions failed");
+ return false;
+ }
+ VLOG("updateConditions succeeded");
return true;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
index ae7b2162e034..7ba684a65e88 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -19,6 +19,7 @@
#include <vector>
#include "anomaly/AlarmMonitor.h"
+#include "condition/ConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "matchers/AtomMatchingTracker.h"
@@ -31,30 +32,33 @@ namespace statsd {
// All other functions are intermediate steps, created to make unit testing easier.
// Possible update states for a component. PRESERVE means we should keep the existing one.
-// REPLACE means we should create a new one, either because it didn't exist or it changed.
+// REPLACE means we should create a new one because the existing one changed
+// NEW means we should create a new one because one does not currently exist.
enum UpdateStatus {
UPDATE_UNKNOWN = 0,
UPDATE_PRESERVE = 1,
UPDATE_REPLACE = 2,
+ UPDATE_NEW = 3,
};
// Recursive function to determine if a matcher needs to be updated.
// input:
// [config]: the input StatsdConfig
// [matcherIdx]: the index of the current matcher to be updated
-// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig
// [oldAtomMatchingTrackerMap]: matcher id to index mapping in the existing MetricsManager
// [oldAtomMatchingTrackers]: stores the existing AtomMatchingTrackers
+// [newAtomMatchingTrackerMap]: matcher id to index mapping in the input StatsdConfig
// output:
// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will
// be updated from UPDATE_UNKNOWN after this call.
// [cycleTracker]: intermediate param used during recursion.
-bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<UpdateStatus>& matchersToUpdate,
- vector<bool>& cycleTracker);
+// Returns whether the function was successful or not.
+bool determineMatcherUpdateStatus(
+ const StatsdConfig& config, const int matcherIdx,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<UpdateStatus>& matchersToUpdate, std::vector<bool>& cycleTracker);
// Updates the AtomMatchingTrackers.
// input:
@@ -64,12 +68,61 @@ bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherI
// output:
// [allTagIds]: contains the set of all interesting tag ids to this config.
// [newAtomMatchingTrackerMap]: new matcher id to index mapping
-// [newAtomMatchers]: stores the new AtomMatchingTrackers
-bool updateAtomTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
- const vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- set<int>& allTagIds, unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
- vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers);
+// [newAtomMatchingTrackers]: stores the new AtomMatchingTrackers
+// [replacedMatchers]: set of matcher ids that changed and have been replaced
+bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
+ std::set<int>& allTagIds,
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
+ std::set<int64_t>& replacedMatchers);
+
+// Recursive function to determine if a condition needs to be updated.
+// input:
+// [config]: the input StatsdConfig
+// [conditionIdx]: the index of the current condition to be updated
+// [oldConditionTrackerMap]: condition id to index mapping in the existing MetricsManager
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// [newConditionTrackerMap]: condition id to index mapping in the input StatsdConfig
+// [replacedMatchers]: set of replaced matcher ids. conditions using these matchers must be replaced
+// output:
+// [conditionsToUpdate]: vector of the update status of each condition. The conditionIdx index will
+// be updated from UPDATE_UNKNOWN after this call.
+// [cycleTracker]: intermediate param used during recursion.
+// Returns whether the function was successful or not.
+bool determineConditionUpdateStatus(const StatsdConfig& config, const int conditionIdx,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ std::vector<UpdateStatus>& conditionsToUpdate,
+ std::vector<bool>& cycleTracker);
+
+// Updates ConditionTrackers
+// input:
+// [config]: the input config
+// [atomMatchingTrackerMap]: AtomMatchingTracker name to index mapping from previous step.
+// [replacedMatchers]: ids of replaced matchers. conditions depending on these must also be replaced
+// [oldConditionTrackerMap]: existing matcher id to index mapping
+// [oldConditionTrackers]: stores the existing ConditionTrackers
+// output:
+// [newConditionTrackerMap]: new condition id to index mapping
+// [newConditionTrackers]: stores the sp to all the ConditionTrackers
+// [trackerToConditionMap]: contains the mapping from the index of an atom matcher
+// to indices of condition trackers that use the matcher
+// [conditionCache]: stores the current conditions for each ConditionTracker
+// [replacedConditions]: set of matcher ids that have changed and have been replaced
+bool updateConditions(const ConfigKey& key, const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const std::set<int64_t>& replacedMatchers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+ std::vector<ConditionState>& conditionCache,
+ std::set<int64_t>& replacedConditions);
// Updates the existing MetricsManager from a new StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
@@ -79,10 +132,15 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs,
const std::vector<sp<AtomMatchingTracker>>& oldAtomMatchingTrackers,
- const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::vector<sp<ConditionTracker>>& oldConditionTrackers,
+ const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
std::set<int>& allTagIds,
std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
- unordered_map<int64_t, int>& newAtomMatchingTrackerMap);
+ std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& newConditionTrackers,
+ std::unordered_map<int64_t, int>& newConditionTrackerMap,
+ std::unordered_map<int, std::vector<int>>& trackerToConditionMap);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index e40fbdb250f1..2e3e43413d54 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -74,16 +74,37 @@ sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher,
case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
return new SimpleAtomMatchingTracker(logMatcher.id(), index, protoHash,
logMatcher.simple_atom_matcher(), uidMap);
- break;
case AtomMatcher::ContentsCase::kCombination:
return new CombinationAtomMatchingTracker(logMatcher.id(), index, protoHash);
- break;
default:
ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
return nullptr;
}
}
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap) {
+ string serializedPredicate;
+ if (!predicate.SerializeToString(&serializedPredicate)) {
+ ALOGE("Unable to serialize predicate %lld", (long long)predicate.id());
+ return nullptr;
+ }
+ uint64_t protoHash = Hash64(serializedPredicate);
+ switch (predicate.contents_case()) {
+ case Predicate::ContentsCase::kSimplePredicate: {
+ return new SimpleConditionTracker(key, predicate.id(), protoHash, index,
+ predicate.simple_predicate(), atomMatchingTrackerMap);
+ }
+ case Predicate::ContentsCase::kCombination: {
+ return new CombinationConditionTracker(predicate.id(), index, protoHash);
+ }
+ default:
+ ALOGE("Predicate \"%lld\" malformed", (long long)predicate.id());
+ return nullptr;
+ }
+}
+
bool handleMetricWithAtomMatchingTrackers(
const int64_t what, const int metricIndex, const bool usedForDimension,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -266,8 +287,7 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
- int index = allAtomMatchingTrackers.size();
- sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, index, uidMap);
+ sp<AtomMatchingTracker> tracker = createAtomMatchingTracker(logMatcher, i, uidMap);
if (tracker == nullptr) {
return false;
}
@@ -276,7 +296,7 @@ bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidM
ALOGE("Duplicate AtomMatcher found!");
return false;
}
- atomMatchingTrackerMap[logMatcher.id()] = index;
+ atomMatchingTrackerMap[logMatcher.id()] = i;
matcherConfigs.push_back(logMatcher);
}
@@ -307,28 +327,17 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
- int index = allConditionTrackers.size();
- switch (condition.contents_case()) {
- case Predicate::ContentsCase::kSimplePredicate: {
- allConditionTrackers.push_back(new SimpleConditionTracker(
- key, condition.id(), index, condition.simple_predicate(),
- atomMatchingTrackerMap));
- break;
- }
- case Predicate::ContentsCase::kCombination: {
- allConditionTrackers.push_back(
- new CombinationConditionTracker(condition.id(), index));
- break;
- }
- default:
- ALOGE("Predicate \"%lld\" malformed", (long long)condition.id());
- return false;
+ sp<ConditionTracker> tracker =
+ createConditionTracker(key, condition, i, atomMatchingTrackerMap);
+ if (tracker == nullptr) {
+ return false;
}
+ allConditionTrackers.push_back(tracker);
if (conditionTrackerMap.find(condition.id()) != conditionTrackerMap.end()) {
ALOGE("Duplicate Predicate found!");
return false;
}
- conditionTrackerMap[condition.id()] = index;
+ conditionTrackerMap[condition.id()] = i;
conditionConfigs.push_back(condition);
}
@@ -934,6 +943,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
unordered_map<int64_t, int>& atomMatchingTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
+ unordered_map<int64_t, int>& conditionTrackerMap,
vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
@@ -944,7 +954,6 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) {
- unordered_map<int64_t, int> conditionTrackerMap;
vector<ConditionState> initialConditionCache;
unordered_map<int64_t, int> metricProducerMap;
unordered_map<int64_t, int> stateAtomIdMap;
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 4cfd1b0465ea..6eabcf4971d3 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -42,6 +42,17 @@ namespace statsd {
sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
const sp<UidMap>& uidMap);
+// Create a ConditionTracker.
+// input:
+// [predicate]: the input Predicate from the StatsdConfig
+// [index]: the index of the condition tracker
+// [atomMatchingTrackerMap]: map of atom matcher id to its index in allAtomMatchingTrackers
+// output:
+// new ConditionTracker, or null if the tracker is unable to be created
+sp<ConditionTracker> createConditionTracker(
+ const ConfigKey& key, const Predicate& predicate, const int index,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -77,7 +88,6 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
std::vector<ConditionState>& initialConditionCache);
// Initialize State maps using State protos in the config. These maps will
@@ -111,7 +121,6 @@ bool initMetrics(
const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
- const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
const unordered_map<int64_t, int>& stateAtomIdMap,
const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
@@ -135,6 +144,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 07b5311b1207..8998b5f98df5 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -39,6 +39,7 @@ const ConfigKey kConfigKey(0, 12345);
const int ATTRIBUTION_NODE_FIELD_ID = 1;
const int ATTRIBUTION_UID_FIELD_ID = 1;
const int TAG_ID = 1;
+const uint64_t protoHash = 0x123456789;
SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
bool outputSlicedUid, Position position) {
@@ -123,7 +124,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -177,7 +178,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -231,8 +232,9 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
- simplePredicate, trackerNameIndexMap);
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
+ 0 /*tracker index*/, simplePredicate,
+ trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
// This event is not accessed in this test besides dimensions which is why this is okay.
@@ -317,7 +319,7 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
@@ -392,7 +394,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -514,7 +516,7 @@ TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
@@ -610,7 +612,7 @@ TEST(SimpleConditionTrackerTest, TestStopAll) {
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
- SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+ SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 8c698eb15d8d..890884bc5d83 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -14,6 +14,7 @@
#include "src/metrics/parsing_utils/config_update_utils.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
@@ -23,6 +24,8 @@
#include <vector>
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/condition/CombinationConditionTracker.h"
+#include "src/condition/SimpleConditionTracker.h"
#include "src/matchers/CombinationAtomMatchingTracker.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "tests/statsd_test_util.h"
@@ -53,6 +56,7 @@ set<int> allTagIds;
vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers;
unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
vector<sp<ConditionTracker>> oldConditionTrackers;
+unordered_map<int64_t, int> oldConditionTrackerMap;
vector<sp<MetricProducer>> oldMetricProducers;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
@@ -75,6 +79,7 @@ public:
oldAtomMatchingTrackers.clear();
oldAtomMatchingTrackerMap.clear();
oldConditionTrackers.clear();
+ oldConditionTrackerMap.clear();
oldMetricProducers.clear();
oldAnomalyTrackers.clear();
oldAlarmTrackers.clear();
@@ -93,8 +98,8 @@ bool initConfig(const StatsdConfig& config) {
return initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap,
- oldConditionTrackers, oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldAnomalyTrackers,
+ oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds);
}
@@ -144,6 +149,30 @@ TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
}
+TEST_F(ConfigUpdateTest, TestSimpleMatcherNew) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ *config.add_atom_matcher() = matcher;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ // Different id, so should be a new matcher.
+ AtomMatcher newMatcher = CreateSimpleAtomMatcher("DIFFERENT_NAME", /*atom=*/10);
+ int64_t matcherId = newMatcher.id();
+ EXPECT_NE(matcherId, matcher.id());
+ *newConfig.add_atom_matcher() = newMatcher;
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ newAtomMatchingTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldAtomMatchingTrackerMap,
+ oldAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_NEW);
+}
+
TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
StatsdConfig config;
AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
@@ -338,9 +367,10 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
set<int> newTagIds;
unordered_map<int64_t, int> newAtomMatchingTrackerMap;
vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers;
- EXPECT_TRUE(updateAtomTrackers(newConfig, uidMap, oldAtomMatchingTrackerMap,
- oldAtomMatchingTrackers, newTagIds, newAtomMatchingTrackerMap,
- newAtomMatchingTrackers));
+ set<int64_t> replacedMatchers;
+ EXPECT_TRUE(updateAtomMatchingTrackers(
+ newConfig, uidMap, oldAtomMatchingTrackerMap, oldAtomMatchingTrackers, newTagIds,
+ newAtomMatchingTrackerMap, newAtomMatchingTrackers, replacedMatchers));
ASSERT_EQ(newTagIds.size(), 3);
EXPECT_EQ(newTagIds.count(10), 1);
@@ -405,8 +435,454 @@ TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
EXPECT_EQ(childMatchers->size(), 2);
EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 1), childMatchers->end());
EXPECT_NE(std::find(childMatchers->begin(), childMatchers->end(), 4), childMatchers->end());
+
+ // Expect replacedMatchers to have simple2 and combination2
+ ASSERT_EQ(replacedMatchers.size(), 2);
+ EXPECT_NE(replacedMatchers.find(simple2Id), replacedMatchers.end());
+ EXPECT_NE(replacedMatchers.find(combination2Id), replacedMatchers.end());
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Modify the predicate.
+ config.mutable_predicate(0)->mutable_simple_predicate()->set_count_nesting(true);
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+ int64_t startMatcherId = startMatcher.id();
+ *config.add_atom_matcher() = startMatcher;
+ AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = stopMatcher;
+
+ Predicate predicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = predicate;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Start matcher was replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(startMatcherId);
+
+ vector<UpdateStatus> conditionsToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ newConditionTrackerMap[predicate.id()] = 0;
+ EXPECT_TRUE(determineConditionUpdateStatus(config, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionPreserve) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Same predicates, different order
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. It should recurse the two child predicates and preserve all 3.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_PRESERVE);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_PRESERVE);
}
+TEST_F(ConfigUpdateTest, TestCombinationConditionReplace) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Changing the logical operation changes the predicate definition, so it should be replaced.
+ combination1.mutable_combination()->set_operation(LogicalOperation::OR);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. The simple conditions should not be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_UNKNOWN);
+ EXPECT_EQ(conditionsToUpdate[2], UPDATE_UNKNOWN);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationConditionDepsChange) {
+ StatsdConfig config;
+ AtomMatcher screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnMatcher;
+ AtomMatcher screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffMatcher;
+
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ *config.add_predicate() = simple1;
+ Predicate simple2 = CreateScreenIsOffPredicate();
+ *config.add_predicate() = simple2;
+
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ Predicate_Combination* combinationInternal = combination1.mutable_combination();
+ combinationInternal->set_operation(LogicalOperation::NAND);
+ combinationInternal->add_predicate(simple1.id());
+ combinationInternal->add_predicate(simple2.id());
+ *config.add_predicate() = combination1;
+
+ EXPECT_TRUE(initConfig(config));
+
+ simple2.mutable_simple_predicate()->set_count_nesting(false);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ *newConfig.add_predicate() = combination1;
+ newConditionTrackerMap[combination1.id()] = 0;
+ *newConfig.add_predicate() = simple2;
+ newConditionTrackerMap[simple2.id()] = 1;
+ *newConfig.add_predicate() = simple1;
+ newConditionTrackerMap[simple1.id()] = 2;
+
+ set<int64_t> replacedMatchers;
+ vector<UpdateStatus> conditionsToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. Simple2 and combination1 must be evaluated.
+ EXPECT_TRUE(determineConditionUpdateStatus(newConfig, 0, oldConditionTrackerMap,
+ oldConditionTrackers, newConditionTrackerMap,
+ replacedMatchers, conditionsToUpdate, cycleTracker));
+ EXPECT_EQ(conditionsToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(conditionsToUpdate[1], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateConditions) {
+ StatsdConfig config;
+
+ // Add atom matchers. These are mostly needed for initStatsdConfig
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ AtomMatcher matcher6 = CreateBatterySaverModeStopAtomMatcher();
+ int64_t matcher6Id = matcher6.id();
+ *config.add_atom_matcher() = matcher6;
+
+ // Add the predicates.
+ // Will be preserved.
+ Predicate simple1 = CreateScreenIsOnPredicate();
+ int64_t simple1Id = simple1.id();
+ *config.add_predicate() = simple1;
+
+ // Will be preserved.
+ Predicate simple2 = CreateScheduledJobPredicate();
+ int64_t simple2Id = simple2.id();
+ *config.add_predicate() = simple2;
+
+ // Will be replaced.
+ Predicate simple3 = CreateBatterySaverModePredicate();
+ int64_t simple3Id = simple3.id();
+ *config.add_predicate() = simple3;
+
+ // Will be preserved
+ Predicate combination1;
+ combination1.set_id(StringToId("COMBINATION1"));
+ combination1.mutable_combination()->set_operation(LogicalOperation::AND);
+ combination1.mutable_combination()->add_predicate(simple1Id);
+ combination1.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination1Id = combination1.id();
+ *config.add_predicate() = combination1;
+
+ // Will be replaced since simple3 will be replaced.
+ Predicate combination2;
+ combination2.set_id(StringToId("COMBINATION2"));
+ combination2.mutable_combination()->set_operation(LogicalOperation::OR);
+ combination2.mutable_combination()->add_predicate(simple1Id);
+ combination2.mutable_combination()->add_predicate(simple3Id);
+ int64_t combination2Id = combination2.id();
+ *config.add_predicate() = combination2;
+
+ // Will be removed.
+ Predicate combination3;
+ combination3.set_id(StringToId("COMBINATION3"));
+ combination3.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination3.mutable_combination()->add_predicate(simple2Id);
+ int64_t combination3Id = combination3.id();
+ *config.add_predicate() = combination3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Mark marcher 5 as replaced. Causes simple3, and therefore combination2 to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher6Id);
+
+ // Change the condition of simple1 to true.
+ ASSERT_EQ(oldConditionTrackers[0]->getConditionId(), simple1Id);
+ LogEvent event(/*uid=*/0, /*pid=*/0); // Empty event is fine since there are no dimensions.
+ // Mark the stop matcher as matched, condition should be false.
+ vector<MatchingState> eventMatcherValues(6, MatchingState::kNotMatched);
+ eventMatcherValues[1] = MatchingState::kMatched;
+ vector<ConditionState> tmpConditionCache(6, ConditionState::kNotEvaluated);
+ vector<bool> conditionChangeCache(6, false);
+ oldConditionTrackers[0]->evaluateCondition(event, eventMatcherValues, oldConditionTrackers,
+ tmpConditionCache, conditionChangeCache);
+ EXPECT_EQ(tmpConditionCache[0], ConditionState::kFalse);
+ EXPECT_EQ(conditionChangeCache[0], true);
+
+ // New combination matcher. Should have an initial condition of true since it is NOT(simple1).
+ Predicate combination4;
+ combination4.set_id(StringToId("COMBINATION4"));
+ combination4.mutable_combination()->set_operation(LogicalOperation::NOT);
+ combination4.mutable_combination()->add_predicate(simple1Id);
+ int64_t combination4Id = combination4.id();
+ *config.add_predicate() = combination4;
+
+ // Map the matchers in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher6Index = 0;
+ newAtomMatchingTrackerMap[matcher6Id] = 0;
+ const int matcher5Index = 1;
+ newAtomMatchingTrackerMap[matcher5Id] = 1;
+ const int matcher4Index = 2;
+ newAtomMatchingTrackerMap[matcher4Id] = 2;
+ const int matcher3Index = 3;
+ newAtomMatchingTrackerMap[matcher3Id] = 3;
+ const int matcher2Index = 4;
+ newAtomMatchingTrackerMap[matcher2Id] = 4;
+ const int matcher1Index = 5;
+ newAtomMatchingTrackerMap[matcher1Id] = 5;
+
+ StatsdConfig newConfig;
+ *newConfig.add_predicate() = simple3;
+ const int simple3Index = 0;
+ *newConfig.add_predicate() = combination2;
+ const int combination2Index = 1;
+ *newConfig.add_predicate() = combination4;
+ const int combination4Index = 2;
+ *newConfig.add_predicate() = simple2;
+ const int simple2Index = 3;
+ *newConfig.add_predicate() = combination1;
+ const int combination1Index = 4;
+ *newConfig.add_predicate() = simple1;
+ const int simple1Index = 5;
+
+ unordered_map<int64_t, int> newConditionTrackerMap;
+ vector<sp<ConditionTracker>> newConditionTrackers;
+ unordered_map<int, vector<int>> trackerToConditionMap;
+ std::vector<ConditionState> conditionCache;
+ std::set<int64_t> replacedConditions;
+ EXPECT_TRUE(updateConditions(key, newConfig, newAtomMatchingTrackerMap, replacedMatchers,
+ oldConditionTrackerMap, oldConditionTrackers,
+ newConditionTrackerMap, newConditionTrackers,
+ trackerToConditionMap, conditionCache, replacedConditions));
+
+ unordered_map<int64_t, int> expectedConditionTrackerMap = {
+ {simple1Id, simple1Index}, {simple2Id, simple2Index},
+ {simple3Id, simple3Index}, {combination1Id, combination1Index},
+ {combination2Id, combination2Index}, {combination4Id, combination4Index},
+ };
+ EXPECT_THAT(newConditionTrackerMap, ContainerEq(expectedConditionTrackerMap));
+
+ ASSERT_EQ(newConditionTrackers.size(), 6);
+ // Make sure all conditions are initialized:
+ for (const sp<ConditionTracker>& tracker : newConditionTrackers) {
+ EXPECT_TRUE(tracker->mInitialized);
+ }
+
+ // Make sure preserved conditions are the same.
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple1Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(simple2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple2Id)]);
+ EXPECT_EQ(oldConditionTrackers[oldConditionTrackerMap.at(combination1Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination1Id)]);
+
+ // Make sure replaced conditions are different and included in replacedConditions.
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(simple3Id)],
+ newConditionTrackers[newConditionTrackerMap.at(simple3Id)]);
+ EXPECT_NE(oldConditionTrackers[oldConditionTrackerMap.at(combination2Id)],
+ newConditionTrackers[newConditionTrackerMap.at(combination2Id)]);
+ EXPECT_THAT(replacedConditions, ContainerEq(set({simple3Id, combination2Id})));
+
+ // Verify the trackerToConditionMap
+ ASSERT_EQ(trackerToConditionMap.size(), 6);
+ const vector<int>& matcher1Conditions = trackerToConditionMap[matcher1Index];
+ EXPECT_THAT(matcher1Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher2Conditions = trackerToConditionMap[matcher2Index];
+ EXPECT_THAT(matcher2Conditions, UnorderedElementsAre(simple1Index, combination1Index,
+ combination2Index, combination4Index));
+ const vector<int>& matcher3Conditions = trackerToConditionMap[matcher3Index];
+ EXPECT_THAT(matcher3Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher4Conditions = trackerToConditionMap[matcher4Index];
+ EXPECT_THAT(matcher4Conditions, UnorderedElementsAre(simple2Index, combination1Index));
+ const vector<int>& matcher5Conditions = trackerToConditionMap[matcher5Index];
+ EXPECT_THAT(matcher5Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+ const vector<int>& matcher6Conditions = trackerToConditionMap[matcher6Index];
+ EXPECT_THAT(matcher6Conditions, UnorderedElementsAre(simple3Index, combination2Index));
+
+ // Verify the conditionCache. Specifically, simple1 is false and combination4 is true.
+ ASSERT_EQ(conditionCache.size(), 6);
+ EXPECT_EQ(conditionCache[simple1Index], ConditionState::kFalse);
+ EXPECT_EQ(conditionCache[simple2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[simple3Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination1Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination2Index], ConditionState::kUnknown);
+ EXPECT_EQ(conditionCache[combination4Index], ConditionState::kTrue);
+
+ // Verify tracker indices/ids are correct.
+ EXPECT_EQ(newConditionTrackers[simple1Index]->getConditionId(), simple1Id);
+ EXPECT_EQ(newConditionTrackers[simple1Index]->mIndex, simple1Index);
+ EXPECT_TRUE(newConditionTrackers[simple1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple2Index]->getConditionId(), simple2Id);
+ EXPECT_EQ(newConditionTrackers[simple2Index]->mIndex, simple2Index);
+ EXPECT_TRUE(newConditionTrackers[simple2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[simple3Index]->getConditionId(), simple3Id);
+ EXPECT_EQ(newConditionTrackers[simple3Index]->mIndex, simple3Index);
+ EXPECT_TRUE(newConditionTrackers[simple3Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination1Index]->getConditionId(), combination1Id);
+ EXPECT_EQ(newConditionTrackers[combination1Index]->mIndex, combination1Index);
+ EXPECT_FALSE(newConditionTrackers[combination1Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination2Index]->getConditionId(), combination2Id);
+ EXPECT_EQ(newConditionTrackers[combination2Index]->mIndex, combination2Index);
+ EXPECT_FALSE(newConditionTrackers[combination2Index]->IsSimpleCondition());
+ EXPECT_EQ(newConditionTrackers[combination4Index]->getConditionId(), combination4Id);
+ EXPECT_EQ(newConditionTrackers[combination4Index]->mIndex, combination4Index);
+ EXPECT_FALSE(newConditionTrackers[combination4Index]->IsSimpleCondition());
+
+ // Verify preserved trackers have indices updated.
+ SimpleConditionTracker* simpleTracker1 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple1Index].get());
+ EXPECT_EQ(simpleTracker1->mStartLogMatcherIndex, matcher1Index);
+ EXPECT_EQ(simpleTracker1->mStopLogMatcherIndex, matcher2Index);
+ EXPECT_EQ(simpleTracker1->mStopAllLogMatcherIndex, -1);
+
+ SimpleConditionTracker* simpleTracker2 =
+ static_cast<SimpleConditionTracker*>(newConditionTrackers[simple2Index].get());
+ EXPECT_EQ(simpleTracker2->mStartLogMatcherIndex, matcher3Index);
+ EXPECT_EQ(simpleTracker2->mStopLogMatcherIndex, matcher4Index);
+ EXPECT_EQ(simpleTracker2->mStopAllLogMatcherIndex, -1);
+
+ CombinationConditionTracker* combinationTracker1 = static_cast<CombinationConditionTracker*>(
+ newConditionTrackers[combination1Index].get());
+ EXPECT_THAT(combinationTracker1->mChildren, UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mUnSlicedChildren,
+ UnorderedElementsAre(simple1Index, simple2Index));
+ EXPECT_THAT(combinationTracker1->mSlicedChildren, IsEmpty());
+}
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
index d6db4c12ae4d..e6583c9686ec 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -384,8 +384,9 @@ TEST(MetricsManagerTest, TestInitialConditions) {
StatsdConfig config = buildConfigWithDifferentPredicates();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -400,9 +401,9 @@ TEST(MetricsManagerTest, TestInitialConditions) {
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(4u, allMetricProducers.size());
@@ -433,8 +434,9 @@ TEST(MetricsManagerTest, TestGoodConfig) {
StatsdConfig config = buildGoodConfig();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -449,9 +451,9 @@ TEST(MetricsManagerTest, TestGoodConfig) {
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
ASSERT_EQ(1u, allMetricProducers.size());
@@ -470,8 +472,9 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
StatsdConfig config = buildDimensionMetricsWithMultiTags();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -486,9 +489,9 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -501,8 +504,9 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
StatsdConfig config = buildCircleMatchers();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -517,9 +521,9 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -532,8 +536,9 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
StatsdConfig config = buildMissingMatchers();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -547,9 +552,9 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -562,8 +567,9 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
StatsdConfig config = buildMissingPredicate();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -577,9 +583,9 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -592,8 +598,9 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
StatsdConfig config = buildCirclePredicates();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -608,9 +615,9 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -623,8 +630,9 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
StatsdConfig config = buildAlertWithUnknownMetric();
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> allAtomMatchingTrackers;
- unordered_map<int64_t, int> logTrackerMap;
+ unordered_map<int64_t, int> atomMatchingTrackerMap;
vector<sp<ConditionTracker>> allConditionTrackers;
+ unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
@@ -639,9 +647,9 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, logTrackerMap,
- allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
- conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
+ allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
metricsWithActivation, noReportMetricIds));
}
@@ -649,6 +657,7 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
sp<UidMap> uidMap = new UidMap();
AtomMatcher matcher;
+ // Matcher has no contents_case (simple/combination), so it is invalid.
matcher.set_id(21);
EXPECT_EQ(createAtomMatchingTracker(matcher, 0, uidMap), nullptr);
}
@@ -699,6 +708,65 @@ TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerCombination) {
ASSERT_EQ(atomIds.size(), 0);
}
+TEST(MetricsManagerTest, TestCreateConditionTrackerInvalid) {
+ const ConfigKey key(123, 456);
+ // Predicate has no contents_case (simple/combination), so it is invalid.
+ Predicate predicate;
+ predicate.set_id(21);
+ unordered_map<int64_t, int> atomTrackerMap;
+ EXPECT_EQ(createConditionTracker(key, predicate, 0, atomTrackerMap), nullptr);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerSimple) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ int startMatcherIndex = 2, stopMatcherIndex = 0, stopAllMatcherIndex = 1;
+ int64_t startMatcherId = 246, stopMatcherId = 153, stopAllMatcherId = 975;
+
+ Predicate predicate;
+ predicate.set_id(id);
+ SimplePredicate* simplePredicate = predicate.mutable_simple_predicate();
+ simplePredicate->set_start(startMatcherId);
+ simplePredicate->set_stop(stopMatcherId);
+ simplePredicate->set_stop_all(stopAllMatcherId);
+
+ unordered_map<int64_t, int> atomTrackerMap;
+ atomTrackerMap[startMatcherId] = startMatcherIndex;
+ atomTrackerMap[stopMatcherId] = stopMatcherIndex;
+ atomTrackerMap[stopAllMatcherId] = stopAllMatcherIndex;
+
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_EQ(tracker->isSliced(), false);
+ EXPECT_TRUE(tracker->IsSimpleCondition());
+ const set<int>& interestedMatchers = tracker->getAtomMatchingTrackerIndex();
+ ASSERT_EQ(interestedMatchers.size(), 3);
+ ASSERT_EQ(interestedMatchers.count(startMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopMatcherIndex), 1);
+ ASSERT_EQ(interestedMatchers.count(stopAllMatcherIndex), 1);
+}
+
+TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
+ int index = 1;
+ int64_t id = 987;
+ const ConfigKey key(123, 456);
+
+ Predicate predicate;
+ predicate.set_id(id);
+ Predicate_Combination* combinationPredicate = predicate.mutable_combination();
+ combinationPredicate->set_operation(LogicalOperation::AND);
+ combinationPredicate->add_predicate(888);
+ combinationPredicate->add_predicate(777);
+
+ // Combination conditions must be initialized to set most state.
+ unordered_map<int64_t, int> atomTrackerMap;
+ sp<ConditionTracker> tracker = createConditionTracker(key, predicate, index, atomTrackerMap);
+ EXPECT_EQ(tracker->getConditionId(), id);
+ EXPECT_FALSE(tracker->IsSimpleCondition());
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 763ce6c6fd17..caca05a9e3b3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5418,12 +5418,13 @@ public final class ActivityThread extends ClientTransactionHandler {
final int prevState = r.getLifecycleState();
- if (prevState < ON_START || prevState > ON_STOP) {
- Log.w(TAG, "Activity state must be in [ON_START..ON_STOP] in order to be relaunched,"
+ if (prevState < ON_RESUME || prevState > ON_STOP) {
+ Log.w(TAG, "Activity state must be in [ON_RESUME..ON_STOP] in order to be relaunched,"
+ "current state is " + prevState);
return;
}
+
// Initialize a relaunch request.
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
r.createdConfig != null ? r.createdConfig : mConfiguration,
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index cee607fd7428..fef8d1005e29 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1924,10 +1924,8 @@ class ContextImpl extends Context {
@Override
public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
- // We may override this API from outer context.
- final boolean isUiContext = isUiContext() || isOuterUiContext();
// Check incorrect Context usage.
- if (isUiComponent(name) && !isUiContext) {
+ if (isUiComponent(name) && !isSelfOrOuterUiContext()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
@@ -1944,15 +1942,17 @@ class ContextImpl extends Context {
return SystemServiceRegistry.getSystemService(this, name);
}
- private boolean isOuterUiContext() {
- return getOuterContext() != null && getOuterContext().isUiContext();
- }
-
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
+ // TODO(b/149463653): check if we still need this method after migrating IMS to WindowContext.
+ private boolean isSelfOrOuterUiContext() {
+ // We may override outer context's isUiContext
+ return isUiContext() || getOuterContext() != null && getOuterContext().isUiContext();
+ }
+
/** @hide */
@Override
public boolean isUiContext() {
@@ -2413,7 +2413,7 @@ class ContextImpl extends Context {
context.setResources(createResources(mToken, mPackageInfo, mSplitName, overrideDisplayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
- context.mIsUiContext = isUiContext() || isOuterUiContext();
+ context.mIsUiContext = isSelfOrOuterUiContext();
return context;
}
@@ -2529,9 +2529,9 @@ class ContextImpl extends Context {
@Override
public Display getDisplay() {
- if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay) {
+ if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay && !isSelfOrOuterUiContext()) {
throw new UnsupportedOperationException("Tried to obtain display from a Context not "
- + "associated with one. Only visual Contexts (such as Activity or one created "
+ + "associated with one. Only visual Contexts (such as Activity or one created "
+ "with Context#createWindowContext) or ones created with "
+ "Context#createDisplayContext are associated with displays. Other types of "
+ "Contexts are typically related to background entities and may return an "
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c61426d5c172..98de85d9735d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9751,21 +9751,6 @@ public class DevicePolicyManager {
}
/**
- * @hide
- * Return if this user is a system-only user. An admin can manage a device from a system only
- * user by calling {@link #ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE}.
- * @param admin Which device owner this request is associated with.
- * @return if this user is a system-only user.
- */
- public boolean isSystemOnlyUser(@NonNull ComponentName admin) {
- try {
- return mService.isSystemOnlyUser(admin);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
* Called by device owner, or profile owner on organization-owned device, to get the MAC
* address of the Wi-Fi device.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9c6a274ccf8c..1c7b617e6d9a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -345,7 +345,6 @@ interface IDevicePolicyManager {
void setKeepUninstalledPackages(in ComponentName admin, in String callerPackage, in List<String> packageList);
List<String> getKeepUninstalledPackages(in ComponentName admin, in String callerPackage);
boolean isManagedProfile(in ComponentName admin);
- boolean isSystemOnlyUser(in ComponentName admin);
String getWifiMacAddress(in ComponentName admin);
void reboot(in ComponentName admin);
diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
index 56bf59b52f74..a34be5c3edc7 100644
--- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java
+++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java
@@ -185,9 +185,6 @@ public class TransactionExecutorHelper {
final ActivityLifecycleItem lifecycleItem;
switch (prevState) {
// TODO(lifecycler): Extend to support all possible states.
- case ON_START:
- lifecycleItem = StartActivityItem.obtain();
- break;
case ON_PAUSE:
lifecycleItem = PauseActivityItem.obtain();
break;
diff --git a/core/java/android/companion/TEST_MAPPING b/core/java/android/companion/TEST_MAPPING
new file mode 100644
index 000000000000..63f54fa35158
--- /dev/null
+++ b/core/java/android/companion/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index da8d15af92b8..d672c6ac6c2f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -788,7 +788,6 @@ public abstract class PackageManager {
INSTALL_ENABLE_ROLLBACK,
INSTALL_ALLOW_DOWNGRADE,
INSTALL_STAGED,
- INSTALL_DRY_RUN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -966,14 +965,6 @@ public abstract class PackageManager {
*/
public static final int INSTALL_STAGED = 0x00200000;
- /**
- * Flag parameter for {@link #installPackage} to indicate that package should only be verified
- * but not installed.
- *
- * @hide
- */
- public static final int INSTALL_DRY_RUN = 0x00800000;
-
/** @hide */
@IntDef(flag = true, value = {
DONT_KILL_APP,
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index bd909c7a3f59..192470e964e0 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -43,11 +43,11 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -793,7 +793,7 @@ public abstract class RegisteredServicesCache<V> {
@VisibleForTesting
protected List<UserInfo> getUsers() {
- return UserManager.get(mContext).getUsers(true);
+ return UserManager.get(mContext).getAliveUsers();
}
@VisibleForTesting
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 7250801eec81..55afefed734e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1210,15 +1210,19 @@ public class InputMethodService extends AbstractInputMethodService {
mWindow.getWindow().getAttributes().setFitInsetsIgnoringVisibility(true);
// IME layout should always be inset by navigation bar, no matter its current visibility,
- // unless automotive requests it, since automotive may hide the navigation bar.
+ // unless automotive requests it. Automotive devices may request the navigation bar to be
+ // hidden when the IME shows up (controlled via config_automotiveHideNavBarForKeyboard)
+ // in order to maximize the visible screen real estate. When this happens, the IME window
+ // should animate from the bottom of the screen to reduce the jank that happens from the
+ // lack of synchronization between the bottom system window and the IME window.
+ if (mIsAutomotive && mAutomotiveHideNavBarForKeyboard) {
+ mWindow.getWindow().setDecorFitsSystemWindows(false);
+ }
mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> v.onApplyWindowInsets(
new WindowInsets.Builder(insets).setInsets(
navigationBars(),
- mIsAutomotive && mAutomotiveHideNavBarForKeyboard
- ? android.graphics.Insets.NONE
- : insets.getInsetsIgnoringVisibility(navigationBars())
- )
+ insets.getInsetsIgnoringVisibility(navigationBars()))
.build()));
// For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
diff --git a/core/java/android/inputmethodservice/TEST_MAPPING b/core/java/android/inputmethodservice/TEST_MAPPING
new file mode 100644
index 000000000000..0ccd75dcbdce
--- /dev/null
+++ b/core/java/android/inputmethodservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/view/inputmethod"
+ }
+ ]
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 2465b0e41876..81ffefd05b19 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -43,7 +43,6 @@ import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo.UserInfoFlag;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -1294,7 +1293,7 @@ public class UserManager {
* in {@link UserManager} & {@link DevicePolicyManager}.
* Note: This is slightly different from the real set of user restrictions listed in {@link
* com.android.server.pm.UserRestrictionsUtils#USER_RESTRICTIONS}. For example
- * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a a legitimate
+ * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a legitimate
* value that can be passed into {@link #hasUserRestriction(String)}.
* @hide
*/
@@ -3174,28 +3173,55 @@ public class UserManager {
}
/**
- * Returns information for all users on this device, including ones marked for deletion.
- * To retrieve only users that are alive, use {@link #getUsers(boolean)}.
+ * Returns information for all fully-created users on this device, including ones marked for
+ * deletion.
+ *
+ * <p>To retrieve only users that are not marked for deletion, use {@link #getAliveUsers()}.
+ *
+ * <p>To retrieve *all* users (including partial and pre-created users), use
+ * {@link #getUsers(boolean, boolean, boolean)) getUsers(false, false, false)}.
+ *
+ * <p>To retrieve a more specific list of users, use
+ * {@link #getUsers(boolean, boolean, boolean)}.
+ *
+ * @return the list of users that were created.
*
- * @return the list of users that exist on the device.
* @hide
*/
@UnsupportedAppUsage
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public List<UserInfo> getUsers() {
- return getUsers(/* excludeDying= */ false);
+ return getUsers(/*excludePartial= */ true, /* excludeDying= */ false,
+ /* excludePreCreated= */ true);
}
/**
- * Returns information for all users on this device. Requires
- * {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Returns information for all "usable" users on this device (i.e, it excludes users that are
+ * marked for deletion, pre-created users, etc...).
+ *
+ * <p>To retrieve all fully-created users, use {@link #getUsers()}.
+ *
+ * <p>To retrieve a more specific list of users, use
+ * {@link #getUsers(boolean, boolean, boolean)}.
*
- * @param excludeDying specify if the list should exclude users being
- * removed.
* @return the list of users that were created.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public @NonNull List<UserInfo> getAliveUsers() {
+ return getUsers(/*excludePartial= */ true, /* excludeDying= */ true,
+ /* excludePreCreated= */ true);
+ }
+
+ /**
+ * @deprecated use {@link #getAliveUsers()} for {@code getUsers(true)}, or
+ * {@link #getUsers()} for @code getUsers(false)}.
+ *
+ * @hide
+ */
+ @Deprecated
@UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
return getUsers(/*excludePartial= */ true, excludeDying,
/* excludePreCreated= */ true);
@@ -3226,7 +3252,8 @@ public class UserManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @NonNull List<UserHandle> getUserHandles(boolean excludeDying) {
- List<UserInfo> users = getUsers(excludeDying);
+ List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
+ /* excludePreCreated= */ true);
List<UserHandle> result = new ArrayList<>(users.size());
for (UserInfo user : users) {
result.add(user.getUserHandle());
@@ -3244,7 +3271,8 @@ public class UserManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public long[] getSerialNumbersOfUsers(boolean excludeDying) {
- List<UserInfo> users = getUsers(excludeDying);
+ List<UserInfo> users = getUsers(/* excludePartial= */ true, excludeDying,
+ /* excludePreCreated= */ true);
long[] result = new long[users.size()];
for (int i = 0; i < result.length; i++) {
result[i] = users.get(i).serialNumber;
@@ -3310,7 +3338,7 @@ public class UserManager {
public boolean canAddMoreUsers() {
// TODO(b/142482943): UMS has different logic, excluding Demo and Profile from counting. Why
// not here? The logic is inconsistent. See UMS.canAddMoreManagedProfiles
- final List<UserInfo> users = getUsers(true);
+ final List<UserInfo> users = getAliveUsers();
final int totalUserCount = users.size();
int aliveUserCount = 0;
for (int i = 0; i < totalUserCount; i++) {
@@ -4118,7 +4146,7 @@ public class UserManager {
/** Returns whether there are any users (other than the current user) to which to switch. */
private boolean areThereUsersToWhichToSwitch() {
- final List<UserInfo> users = getUsers(true);
+ final List<UserInfo> users = getAliveUsers();
if (users == null) {
return false;
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 276f16216b4d..c3b6d8e2cfe3 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -870,7 +870,7 @@ public class CallLog {
// Otherwise, insert to all other users that are running and unlocked.
- final List<UserInfo> users = userManager.getUsers(true);
+ final List<UserInfo> users = userManager.getAliveUsers();
final int count = users.size();
for (int i = 0; i < count; i++) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 327bca268a7b..d55fc511fc77 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -218,8 +218,15 @@ public abstract class DocumentsProvider extends ContentProvider {
}
/** {@hide} */
- private void enforceTree(Uri documentUri) {
- if (isTreeUri(documentUri)) {
+ private void enforceTreeForExtraUris(Bundle extras) {
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI));
+ enforceTree(extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI));
+ }
+
+ /** {@hide} */
+ private void enforceTree(@Nullable Uri documentUri) {
+ if (documentUri != null && isTreeUri(documentUri)) {
final String parent = getTreeDocumentId(documentUri);
final String child = getDocumentId(documentUri);
if (Objects.equals(parent, child)) {
@@ -1076,6 +1083,9 @@ public abstract class DocumentsProvider extends ContentProvider {
final Context context = getContext();
final Bundle out = new Bundle();
+ // If the URI is a tree URI performs some validation.
+ enforceTreeForExtraUris(extras);
+
if (METHOD_EJECT_ROOT.equals(method)) {
// Given that certain system apps can hold MOUNT_UNMOUNT permission, but only apps
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
@@ -1099,9 +1109,6 @@ public abstract class DocumentsProvider extends ContentProvider {
"Requested authority " + authority + " doesn't match provider " + mAuthority);
}
- // If the URI is a tree URI performs some validation.
- enforceTree(documentUri);
-
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
enforceReadPermissionInner(documentUri, getCallingPackage(),
getCallingAttributionTag(), null);
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index b80718018652..cbc304b3293a 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -950,10 +950,6 @@ public class PhoneStateListener {
* This method will be called when an emergency call is placed on any subscription (including
* the no-SIM case), regardless of which subscription this listener was registered on.
*
- * This method is deprecated. Both this method and the new
- * {@link #onOutgoingEmergencyCall(EmergencyNumber, int)} will be called when an outgoing
- * emergency call is placed.
- *
* @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
*
* @deprecated Use {@link #onOutgoingEmergencyCall(EmergencyNumber, int)}.
@@ -972,22 +968,24 @@ public class PhoneStateListener {
* This method will be called when an emergency call is placed on any subscription (including
* the no-SIM case), regardless of which subscription this listener was registered on.
*
- * Both this method and the deprecated {@link #onOutgoingEmergencyCall(EmergencyNumber)} will be
- * called when an outgoing emergency call is placed. You should only implement one of these
- * methods.
+ * The default implementation of this method calls
+ * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes. Do
+ * not call {@code super(...)} from within your implementation unless you want
+ * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well.
*
* @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
* @param subscriptionId The subscription ID used to place the emergency call. If the
* emergency call was placed without a valid subscription (e.g. when there
* are no SIM cards in the device), this will be equal to
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
- *
* @hide
*/
@SystemApi
@TestApi
public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
int subscriptionId) {
+ // Default implementation for backwards compatibility
+ onOutgoingEmergencyCall(placedEmergencyNumber);
}
/**
@@ -1375,10 +1373,6 @@ public class PhoneStateListener {
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
- () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber)));
-
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
() -> psl.onOutgoingEmergencyCall(placedEmergencyNumber,
subscriptionId)));
}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 054dff726ca1..32cc30be8de4 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -250,8 +250,11 @@ public final class FrameMetrics {
Index.INTENDED_VSYNC, Index.FRAME_COMPLETED,
};
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
- /* package */ final long[] mTimingData;
+ public final long[] mTimingData;
/**
* Constructs a FrameMetrics object as a copy.
@@ -270,7 +273,7 @@ public final class FrameMetrics {
/**
* @hide
*/
- FrameMetrics() {
+ public FrameMetrics() {
mTimingData = new long[Index.FRAME_STATS_COUNT];
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 6136a80978b7..0c3d61f31dfb 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -456,8 +456,8 @@ public class NotificationHeaderView extends ViewGroup {
case MotionEvent.ACTION_UP:
if (mTrackGesture) {
if (mFeedbackIcon.isVisibleToUser()
- && (mFeedbackRect.contains((int) x, (int) y))
- || mFeedbackRect.contains((int) mDownX, (int) mDownY)) {
+ && (mFeedbackRect.contains((int) x, (int) y)
+ || mFeedbackRect.contains((int) mDownX, (int) mDownY))) {
mFeedbackIcon.performClick();
return true;
}
diff --git a/core/java/android/view/inputmethod/TEST_MAPPING b/core/java/android/view/inputmethod/TEST_MAPPING
new file mode 100644
index 000000000000..4b2ea1a096c8
--- /dev/null
+++ b/core/java/android/view/inputmethod/TEST_MAPPING
@@ -0,0 +1,18 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.inline"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.AppModeFull"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 92fa80e40caf..12b16ff6645c 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -60,5 +60,6 @@ interface ITaskOrganizerController {
* Requests that the given task organizer is notified when back is pressed on the root activity
* of one of its controlled tasks.
*/
- void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer, boolean interceptBackPressed);
+ void setInterceptBackPressedOnTaskRoot(in WindowContainerToken task,
+ boolean interceptBackPressed);
}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 7ec4f99ce959..38fb023a0822 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -149,9 +149,10 @@ public class TaskOrganizer extends WindowOrganizer {
* of one of its controlled tasks.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
+ public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task,
+ boolean interceptBackPressed) {
try {
- getController().setInterceptBackPressedOnTaskRoot(mInterface, interceptBackPressed);
+ getController().setInterceptBackPressedOnTaskRoot(task, interceptBackPressed);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java
index 46c72f88e14b..eb9dfed7f644 100644
--- a/core/java/android/window/TaskOrganizerTaskEmbedder.java
+++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java
@@ -74,7 +74,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
// windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
// infrastructure is ready.
// mTaskOrganizer.registerOrganizer();
- mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
+ // mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
return super.onInitialize();
}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
new file mode 100644
index 000000000000..f9a2ecc10dc8
--- /dev/null
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import android.annotation.NonNull;
+import android.graphics.HardwareRendererObserver;
+import android.os.Handler;
+import android.os.Trace;
+import android.util.Log;
+import android.view.FrameMetrics;
+import android.view.ThreadedRenderer;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+/**
+ * @hide
+ */
+public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
+ private static final String TAG = FrameTracker.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ //TODO (163431584): need also consider other refresh rates.
+ private static final long CRITERIA = 1000000000 / 60;
+ @VisibleForTesting
+ public static final long UNKNOWN_TIMESTAMP = -1;
+
+ @VisibleForTesting
+ public long mBeginTime = UNKNOWN_TIMESTAMP;
+ @VisibleForTesting
+ public long mEndTime = UNKNOWN_TIMESTAMP;
+ public boolean mShouldTriggerTrace;
+ public HardwareRendererObserver mObserver;
+ public ThreadedRendererWrapper mRendererWrapper;
+ public FrameMetricsWrapper mMetricsWrapper;
+
+ private Session mSession;
+
+ public FrameTracker(@NonNull Session session,
+ @NonNull Handler handler, @NonNull ThreadedRenderer renderer) {
+ mSession = session;
+ mRendererWrapper = new ThreadedRendererWrapper(renderer);
+ mMetricsWrapper = new FrameMetricsWrapper();
+ mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
+ }
+
+ /**
+ * This constructor is only for unit tests.
+ * @param session a trace session.
+ * @param renderer a test double for ThreadedRenderer
+ * @param metrics a test double for FrameMetrics
+ */
+ @VisibleForTesting
+ public FrameTracker(@NonNull Session session, Handler handler,
+ @NonNull ThreadedRendererWrapper renderer, @NonNull FrameMetricsWrapper metrics) {
+ mSession = session;
+ mRendererWrapper = renderer;
+ mMetricsWrapper = metrics;
+ mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
+ }
+
+ /**
+ * Begin a trace session of the CUJ.
+ */
+ public void begin() {
+ long timestamp = System.nanoTime();
+ if (DEBUG) {
+ Log.d(TAG, "begin: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
+ + ", end(ns)=" + mEndTime + ", session=" + mSession);
+ }
+ if (mBeginTime != UNKNOWN_TIMESTAMP && mEndTime == UNKNOWN_TIMESTAMP) {
+ // We have an ongoing tracing already, skip subsequent calls.
+ return;
+ }
+ mBeginTime = timestamp;
+ mEndTime = UNKNOWN_TIMESTAMP;
+ Trace.beginAsyncSection(mSession.getName(), (int) mBeginTime);
+ mRendererWrapper.addObserver(mObserver);
+ }
+
+ /**
+ * End the trace session of the CUJ.
+ */
+ public void end() {
+ long timestamp = System.nanoTime();
+ if (DEBUG) {
+ Log.d(TAG, "end: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
+ + ", end(ns)=" + mEndTime + ", session=" + mSession);
+ }
+ if (mBeginTime == UNKNOWN_TIMESTAMP || mEndTime != UNKNOWN_TIMESTAMP) {
+ // We haven't started a trace yet.
+ return;
+ }
+ mEndTime = timestamp;
+ Trace.endAsyncSection(mSession.getName(), (int) mBeginTime);
+ }
+
+ /**
+ * Check if we had a janky frame according to the metrics.
+ * @param metrics frame metrics
+ * @return true if it is a janky frame
+ */
+ @VisibleForTesting
+ public boolean isJankyFrame(FrameMetricsWrapper metrics) {
+ long totalDurationMs = metrics.getMetric(FrameMetrics.TOTAL_DURATION);
+ boolean isFirstFrame = metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
+ boolean isJanky = !isFirstFrame && totalDurationMs - CRITERIA > 0;
+
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(isJanky).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.ANIMATION_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.DRAW_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.SYNC_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.SWAP_BUFFERS_DURATION)).append(",");
+ sb.append(totalDurationMs).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)).append(",");
+ sb.append(metrics.getMetric(FrameMetrics.VSYNC_TIMESTAMP)).append(",");
+ Log.v(TAG, "metrics=" + sb.toString());
+ }
+
+ return isJanky;
+ }
+
+ @Override
+ public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
+ // Since this callback might come a little bit late after the end() call.
+ // We should keep tracking the begin / end timestamp.
+ // Then compare with vsync timestamp to check if the frame is in the duration of the CUJ.
+
+ if (mBeginTime == UNKNOWN_TIMESTAMP) return; // We haven't started tracing yet.
+ long vsyncTimestamp = mMetricsWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ if (vsyncTimestamp < mBeginTime) return; // The tracing has been started.
+
+ // If the end time has not been set, we are still in the tracing.
+ if (mEndTime != UNKNOWN_TIMESTAMP && vsyncTimestamp > mEndTime) {
+ // The tracing has been ended, remove the observer, see if need to trigger perfetto.
+ mRendererWrapper.removeObserver(mObserver);
+ // Trigger perfetto if necessary.
+ if (mShouldTriggerTrace) {
+ if (DEBUG) {
+ Log.v(TAG, "Found janky frame, triggering perfetto.");
+ }
+ triggerPerfetto();
+ }
+ return;
+ }
+
+ // The frame is in the duration of the CUJ, check if it catches the deadline.
+ if (isJankyFrame(mMetricsWrapper)) {
+ mShouldTriggerTrace = true;
+ }
+ }
+
+ /**
+ * Trigger the prefetto daemon.
+ */
+ @VisibleForTesting
+ public void triggerPerfetto() {
+ InteractionJankMonitor.trigger();
+ }
+
+ /**
+ * A wrapper class that we can spy FrameMetrics (a final class) in unit tests.
+ */
+ public static class FrameMetricsWrapper {
+ private FrameMetrics mFrameMetrics;
+
+ public FrameMetricsWrapper() {
+ mFrameMetrics = new FrameMetrics();
+ }
+
+ /**
+ * Wrapper method.
+ * @return timing data of the metrics
+ */
+ public long[] getTiming() {
+ return mFrameMetrics.mTimingData;
+ }
+
+ /**
+ * Wrapper method.
+ * @param index specific index of the timing data
+ * @return the timing data of the specified index
+ */
+ public long getMetric(int index) {
+ return mFrameMetrics.getMetric(index);
+ }
+ }
+
+ /**
+ * A wrapper class that we can spy ThreadedRenderer (a final class) in unit tests.
+ */
+ public static class ThreadedRendererWrapper {
+ private ThreadedRenderer mRenderer;
+
+ public ThreadedRendererWrapper(ThreadedRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ /**
+ * Wrapper method.
+ * @param observer observer
+ */
+ public void addObserver(HardwareRendererObserver observer) {
+ mRenderer.addObserver(observer);
+ }
+
+ /**
+ * Wrapper method.
+ * @param observer observer
+ */
+ public void removeObserver(HardwareRendererObserver observer) {
+ mRenderer.removeObserver(observer);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
new file mode 100644
index 000000000000..6bfb178bc102
--- /dev/null
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.HandlerThread;
+import android.view.ThreadedRenderer;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class let users to begin and end the always on tracing mechanism.
+ * @hide
+ */
+public class InteractionJankMonitor {
+ private static final String TAG = InteractionJankMonitor.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final Object LOCK = new Object();
+ public static final int CUJ_NOTIFICATION_SHADE_MOTION = 0;
+ public static final int CUJ_NOTIFICATION_SHADE_GESTURE = 1;
+
+ private static ThreadedRenderer sRenderer;
+ private static Map<String, FrameTracker> sRunningTracker;
+ private static HandlerThread sWorker;
+ private static boolean sInitialized;
+
+ /** @hide */
+ @IntDef({
+ CUJ_NOTIFICATION_SHADE_MOTION,
+ CUJ_NOTIFICATION_SHADE_GESTURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CujType {}
+
+ /**
+ * @param view Any view in the view tree to get context and ThreadedRenderer.
+ */
+ public static void init(@NonNull View view) {
+ init(view, null, null, null);
+ }
+
+ /**
+ * Should be only invoked internally or from unit tests.
+ */
+ @VisibleForTesting
+ public static void init(@NonNull View view, @NonNull ThreadedRenderer renderer,
+ @NonNull Map<String, FrameTracker> map, @NonNull HandlerThread worker) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ synchronized (LOCK) {
+ if (!sInitialized) {
+ if (!view.isAttachedToWindow()) {
+ throw new IllegalStateException("View is not attached!");
+ }
+ sRenderer = renderer == null ? view.getThreadedRenderer() : renderer;
+ sRunningTracker = map == null ? new HashMap<>() : map;
+ sWorker = worker == null ? new HandlerThread("Aot-Worker") : worker;
+ sWorker.start();
+ sInitialized = true;
+ }
+ }
+ }
+
+ /**
+ * Must invoke init() before invoking this method.
+ */
+ public static void begin(@NonNull @CujType int cujType) {
+ begin(cujType, null);
+ }
+
+ /**
+ * Should be only invoked internally or from unit tests.
+ */
+ @VisibleForTesting
+ public static void begin(@NonNull @CujType int cujType, FrameTracker tracker) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ //TODO (163510843): Remove synchronized, add @UiThread if only invoked from ui threads.
+ synchronized (LOCK) {
+ checkInitStateLocked();
+ Session session = new Session(cujType);
+ FrameTracker currentTracker = getTracker(session.getName());
+ if (currentTracker != null) return;
+ if (tracker == null) {
+ tracker = new FrameTracker(session, sWorker.getThreadHandler(), sRenderer);
+ }
+ sRunningTracker.put(session.getName(), tracker);
+ tracker.begin();
+ }
+ }
+
+ /**
+ * Must invoke init() before invoking this method.
+ */
+ public static void end(@NonNull @CujType int cujType) {
+ //TODO (163505250): This should be no-op if not in droid food rom.
+ //TODO (163510843): Remove synchronized, add @UiThread if only invoked from ui threads.
+ synchronized (LOCK) {
+ checkInitStateLocked();
+ Session session = new Session(cujType);
+ FrameTracker tracker = getTracker(session.getName());
+ if (tracker != null) {
+ tracker.end();
+ sRunningTracker.remove(session.getName());
+ }
+ }
+ }
+
+ private static void checkInitStateLocked() {
+ if (!sInitialized) {
+ throw new IllegalStateException("InteractionJankMonitor not initialized!");
+ }
+ }
+
+ /**
+ * Should be only invoked from unit tests.
+ */
+ @VisibleForTesting
+ public static void reset() {
+ sInitialized = false;
+ sRenderer = null;
+ sRunningTracker = null;
+ if (sWorker != null) {
+ sWorker.quit();
+ sWorker = null;
+ }
+ }
+
+ private static FrameTracker getTracker(String sessionName) {
+ synchronized (LOCK) {
+ return sRunningTracker.get(sessionName);
+ }
+ }
+
+ /**
+ * Trigger the perfetto daemon to collect and upload data.
+ */
+ public static void trigger() {
+ sWorker.getThreadHandler().post(
+ () -> PerfettoTrigger.trigger(PerfettoTrigger.TRIGGER_TYPE_JANK));
+ }
+
+ /**
+ * A class to represent a session.
+ */
+ public static class Session {
+ private @CujType int mId;
+
+ public Session(@CujType int session) {
+ mId = session;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public String getName() {
+ return "CujType<" + mId + ">";
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/jank/PerfettoTrigger.java b/core/java/com/android/internal/jank/PerfettoTrigger.java
new file mode 100644
index 000000000000..6c8d3cdcf5ae
--- /dev/null
+++ b/core/java/com/android/internal/jank/PerfettoTrigger.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+//TODO (165884885): Make PerfettoTrigger more generic and move it to another package.
+package com.android.internal.jank;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A trigger implementation with perfetto backend.
+ * @hide
+ */
+public class PerfettoTrigger {
+ private static final String TAG = PerfettoTrigger.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto";
+ private static final String[] TRIGGER_TYPE_NAMES = new String[] { "jank-tracker" };
+ public static final int TRIGGER_TYPE_JANK = 0;
+
+ /** @hide */
+ @IntDef({
+ TRIGGER_TYPE_JANK
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TriggerType {}
+
+ /**
+ * @param type the trigger type
+ */
+ public static void trigger(@NonNull @TriggerType int type) {
+ try {
+ Token token = new Token(type, TRIGGER_TYPE_NAMES[type]);
+ ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, token.getName());
+ if (DEBUG) {
+ StringBuilder sb = new StringBuilder();
+ for (String arg : pb.command()) {
+ sb.append(arg).append(" ");
+ }
+ Log.d(TAG, "Triggering " + sb.toString());
+ }
+ Process process = pb.start();
+ if (DEBUG) {
+ readConsoleOutput(process);
+ }
+ } catch (IOException | InterruptedException e) {
+ Log.w(TAG, "Failed to trigger " + type, e);
+ }
+ }
+
+ private static void readConsoleOutput(@NonNull Process process)
+ throws IOException, InterruptedException {
+ process.waitFor();
+ try (BufferedReader errReader =
+ new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
+ StringBuilder errLine = new StringBuilder();
+ String line;
+ while ((line = errReader.readLine()) != null) {
+ errLine.append(line).append("\n");
+ }
+ errLine.append(", code=").append(process.exitValue());
+ Log.d(TAG, "err message=" + errLine.toString());
+ }
+ }
+
+ /**
+ * Token which is used to trigger perfetto.
+ */
+ public static class Token {
+ private int mType;
+ private String mName;
+
+ Token(@TriggerType int type, String name) {
+ mType = type;
+ mName = name;
+ }
+
+ /**
+ * Get trigger type.
+ * @return trigger type, should be @TriggerType
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Get name of this token as the argument while triggering perfetto.
+ * @return name
+ */
+ public String getName() {
+ return mName;
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
index 9f100bd6440f..a92e978b2fc1 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java
@@ -26,6 +26,36 @@ interface ScrollCaptureViewHelper<V extends View> {
int DOWN = 1;
/**
+ * Contains the result of a scroll request.
+ */
+ class ScrollResult {
+ /**
+ * The area requested in pixels, within {@link #onComputeScrollBounds scroll bounds}, with
+ * top/bottom relative to the scroll position at the start of capture.
+ */
+ public Rect requestedArea;
+ /**
+ * The area, in pixels of the request which is visible and available for capture. In the
+ * same coordinate space as {@link #requestedArea}.
+ */
+ public Rect availableArea;
+ /**
+ * The updated scroll delta (the relative distance, in pixels that the scroll position has
+ * moved from the starting position since capture started).
+ */
+ public int scrollDelta; // visible top offset from start
+
+ @Override
+ public String toString() {
+ return "ScrollResult{"
+ + "requestedArea=" + requestedArea
+ + ", availableArea=" + availableArea
+ + ", scrollDelta=" + scrollDelta
+ + '}';
+ }
+ }
+
+ /**
* Verifies that the view is still visible and scrollable. If true is returned here, expect a
* call to {@link #onComputeScrollBounds(View)} to follow.
*
@@ -48,6 +78,7 @@ interface ScrollCaptureViewHelper<V extends View> {
view.getWidth() - view.getPaddingRight(),
view.getHeight() - view.getPaddingBottom());
}
+
/**
* Adjust the target for capture.
* <p>
@@ -67,14 +98,14 @@ interface ScrollCaptureViewHelper<V extends View> {
* needed and return the resulting rectangle describing the position and bounds of the area
* which is visible.
*
+ * @param view the view being captured
* @param scrollBounds the area in which scrolling content moves, local to the {@code containing
* view}
* @param requestRect the area relative to {@code scrollBounds} which describes the location of
* content to capture for the request
- * @return the visible area within scrollBounds of the requested rectangle, return {@code null}
- * in the case of an unrecoverable error condition, to abort the capture process
+ * @return the result of the request as a {@link ScrollResult}
*/
- Rect onScrollRequested(@NonNull V view, Rect scrollBounds, Rect requestRect);
+ ScrollResult onScrollRequested(@NonNull V view, Rect scrollBounds, Rect requestRect);
/**
* Restore the target after capture.
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 4087eda944e0..7b4f73ffde2b 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -30,21 +30,24 @@ import android.view.ScrollCaptureSession;
import android.view.Surface;
import android.view.View;
+import com.android.internal.view.ScrollCaptureViewHelper.ScrollResult;
+
import java.lang.ref.WeakReference;
import java.util.function.Consumer;
/**
- * Provides a ScrollCaptureCallback implementation for to handle arbitrary View-based scrolling
- * containers.
- * <p>
- * To use this class, supply the target view and an implementation of {@ScrollCaptureViewHelper}
- * to the callback.
+ * Provides a base ScrollCaptureCallback implementation to handle arbitrary View-based scrolling
+ * containers. This class handles the bookkeeping aspects of {@link ScrollCaptureCallback}
+ * including rendering output using HWUI. Adaptable to any {@link View} using
+ * {@link ScrollCaptureViewHelper}.
*
* @param <V> the specific View subclass handled
- * @hide
+ * @see ScrollCaptureViewHelper
*/
public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCallback {
+ private static final String TAG = "ScrollCaptureViewSupport";
+
private final WeakReference<V> mWeakView;
private final ScrollCaptureViewHelper<V> mViewHelper;
private ViewRenderer mRenderer;
@@ -52,11 +55,6 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
private boolean mStarted;
private boolean mEnded;
- static <V extends View> ScrollCaptureCallback createCallback(V view,
- ScrollCaptureViewHelper<V> impl) {
- return new ScrollCaptureViewSupport<>(view, impl);
- }
-
ScrollCaptureViewSupport(V containingView, ScrollCaptureViewHelper<V> viewHelper) {
mWeakView = new WeakReference<>(containingView);
mRenderer = new ViewRenderer();
@@ -82,6 +80,7 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
@Override
public final void onScrollCaptureStart(ScrollCaptureSession session, Runnable onReady) {
V view = mWeakView.get();
+
mEnded = false;
mStarted = true;
@@ -103,21 +102,30 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
session.notifyBufferSent(0, null);
return;
}
- Rect captureArea = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
+ // Ask the view to scroll as needed to bring this area into view.
+ ScrollResult scrollResult = mViewHelper.onScrollRequested(view, session.getScrollBounds(),
requestRect);
- mRenderer.renderFrame(view, captureArea, mUiHandler,
- () -> session.notifyBufferSent(0, captureArea));
+ view.invalidate(); // don't wait for vsync
+
+ // For image capture, shift back by scrollDelta to arrive at the location within the view
+ // where the requested content will be drawn
+ Rect viewCaptureArea = new Rect(scrollResult.availableArea);
+ viewCaptureArea.offset(0, -scrollResult.scrollDelta);
+
+ mRenderer.renderView(view, viewCaptureArea, mUiHandler,
+ (frameNumber) -> session.notifyBufferSent(frameNumber, scrollResult.availableArea));
}
@Override
public final void onScrollCaptureEnd(Runnable onReady) {
V view = mWeakView.get();
if (mStarted && !mEnded) {
- mViewHelper.onPrepareForEnd(view);
- /* empty */
+ if (view != null) {
+ mViewHelper.onPrepareForEnd(view);
+ view.invalidate();
+ }
mEnded = true;
- mRenderer.trimMemory();
- mRenderer.setSurface(null);
+ mRenderer.destroy();
}
onReady.run();
}
@@ -142,7 +150,7 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
private static final String TAG = "ViewRenderer";
private HardwareRenderer mRenderer;
- private RenderNode mRootRenderNode;
+ private RenderNode mCaptureRenderNode;
private final RectF mTempRectF = new RectF();
private final Rect mSourceRect = new Rect();
private final Rect mTempRect = new Rect();
@@ -151,10 +159,14 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
private long mLastRenderedSourceDrawingId = -1;
+ public interface FrameCompleteListener {
+ void onFrameComplete(long frameNumber);
+ }
+
ViewRenderer() {
mRenderer = new HardwareRenderer();
- mRootRenderNode = new RenderNode("ScrollCaptureRoot");
- mRenderer.setContentRoot(mRootRenderNode);
+ mCaptureRenderNode = new RenderNode("ScrollCaptureRoot");
+ mRenderer.setContentRoot(mCaptureRenderNode);
// TODO: Figure out a way to flip this on when we are sure the source window is opaque
mRenderer.setOpaque(false);
@@ -193,18 +205,36 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
// Enable shadows for elevation/Z
mRenderer.setLightSourceGeometry(lightX, lightY, lightZ, lightRadius);
mRenderer.setLightSourceAlpha(AMBIENT_SHADOW_ALPHA, SPOT_SHADOW_ALPHA);
+ }
+
+ private void updateRootNode(View source, Rect localSourceRect) {
+ final View rootView = source.getRootView();
+ transformToRoot(source, localSourceRect, mTempRect);
+
+ mCaptureRenderNode.setPosition(0, 0, mTempRect.width(), mTempRect.height());
+ RecordingCanvas canvas = mCaptureRenderNode.beginRecording();
+ canvas.enableZ();
+ canvas.translate(-mTempRect.left, -mTempRect.top);
+ RenderNode rootViewRenderNode = rootView.updateDisplayListIfDirty();
+ if (rootViewRenderNode.hasDisplayList()) {
+ canvas.drawRenderNode(rootViewRenderNode);
+ }
+ mCaptureRenderNode.endRecording();
}
- public void renderFrame(View localReference, Rect sourceRect, Handler handler,
- Runnable onFrameCommitted) {
- if (updateForView(localReference)) {
- setupLighting(localReference);
+ public void renderView(View view, Rect sourceRect, Handler handler,
+ FrameCompleteListener frameListener) {
+ if (updateForView(view)) {
+ setupLighting(view);
}
- buildRootDisplayList(localReference, sourceRect);
+ view.invalidate();
+ updateRootNode(view, sourceRect);
HardwareRenderer.FrameRenderRequest request = mRenderer.createRenderRequest();
request.setVsyncTime(SystemClock.elapsedRealtimeNanos());
- request.setFrameCommitCallback(handler::post, onFrameCommitted);
+ // private API b/c request.setFrameCommitCallback does not provide access to frameNumber
+ mRenderer.setFrameCompleteCallback(
+ frameNr -> handler.post(() -> frameListener.onFrameComplete(frameNr)));
request.setWaitForPresent(true);
request.syncAndDraw();
}
@@ -225,15 +255,5 @@ public class ScrollCaptureViewSupport<V extends View> implements ScrollCaptureCa
mTempRectF.round(outRect);
}
- private void buildRootDisplayList(View source, Rect localSourceRect) {
- final View captureSource = source.getRootView();
- transformToRoot(source, localSourceRect, mTempRect);
- mRootRenderNode.setPosition(0, 0, mTempRect.width(), mTempRect.height());
- RecordingCanvas canvas = mRootRenderNode.beginRecording(mTempRect.width(),
- mTempRect.height());
- canvas.translate(-mTempRect.left, -mTempRect.top);
- canvas.drawRenderNode(captureSource.updateDisplayListIfDirty());
- mRootRenderNode.endRecording();
- }
}
}
diff --git a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
index 12bd461f810b..1514b9a285dd 100644
--- a/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/ScrollViewCaptureHelper.java
@@ -35,13 +35,14 @@ import android.view.ViewParent;
* <li>correctly implements {@link ViewParent#requestChildRectangleOnScreen(View,
* Rect, boolean)}
* </ul>
+ *
+ * @see ScrollCaptureViewSupport
*/
public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGroup> {
private int mStartScrollY;
private boolean mScrollBarEnabled;
private int mOverScrollMode;
- /** @see ScrollCaptureViewHelper#onPrepareForStart(View, Rect) */
public void onPrepareForStart(@NonNull ViewGroup view, Rect scrollBounds) {
mStartScrollY = view.getScrollY();
mOverScrollMode = view.getOverScrollMode();
@@ -54,8 +55,8 @@ public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGrou
}
}
- /** @see ScrollCaptureViewHelper#onScrollRequested(View, Rect, Rect) */
- public Rect onScrollRequested(@NonNull ViewGroup view, Rect scrollBounds, Rect requestRect) {
+ public ScrollResult onScrollRequested(@NonNull ViewGroup view, Rect scrollBounds,
+ Rect requestRect) {
final View contentView = view.getChildAt(0); // returns null, does not throw IOOBE
if (contentView == null) {
return null;
@@ -87,6 +88,9 @@ public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGrou
\__ Requested Bounds[0,300 - 200,400] (200x100)
*/
+ ScrollResult result = new ScrollResult();
+ result.requestedArea = new Rect(requestRect);
+
// 0) adjust the requestRect to account for scroll change since start
//
// Scroll Bounds[50,50 - 250,250] (w=200,h=200)
@@ -117,8 +121,6 @@ public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGrou
view.getScrollX() - contentView.getLeft(),
view.getScrollY() - contentView.getTop());
-
-
// requestRect is now local to contentView as requestedContentBounds
// contentView (and each parent in turn if possible) will be scrolled
// (if necessary) to make all of requestedContent visible, (if possible!)
@@ -126,35 +128,37 @@ public class ScrollViewCaptureHelper implements ScrollCaptureViewHelper<ViewGrou
// update new offset between starting and current scroll position
scrollDelta = view.getScrollY() - mStartScrollY;
+ result.scrollDelta = scrollDelta;
-
- // TODO: adjust to avoid occlusions/minimize scroll changes
+ // TODO: crop capture area to avoid occlusions/minimize scroll changes
Point offset = new Point();
- final Rect capturedRect = new Rect(requestedContentBounds); // empty
- if (!view.getChildVisibleRect(contentView, capturedRect, offset)) {
- capturedRect.setEmpty();
- return capturedRect;
+ final Rect available = new Rect(requestedContentBounds); // empty
+ if (!view.getChildVisibleRect(contentView, available, offset)) {
+ available.setEmpty();
+ result.availableArea = available;
+ return result;
}
// Transform back from global to content-view local
- capturedRect.offset(-offset.x, -offset.y);
+ available.offset(-offset.x, -offset.y);
// Then back to container view
- capturedRect.offset(
+ available.offset(
contentView.getLeft() - view.getScrollX(),
contentView.getTop() - view.getScrollY());
// And back to relative to scrollBounds
- capturedRect.offset(-scrollBounds.left, -scrollBounds.top);
+ available.offset(-scrollBounds.left, -scrollBounds.top);
- // Apply scrollDelta again to return to make capturedRect relative to scrollBounds at
+ // Apply scrollDelta again to return to make `available` relative to `scrollBounds` at
// the scroll position at start of capture.
- capturedRect.offset(0, scrollDelta);
- return capturedRect;
+ available.offset(0, scrollDelta);
+
+ result.availableArea = new Rect(available);
+ return result;
}
- /** @see ScrollCaptureViewHelper#onPrepareForEnd(View) */
public void onPrepareForEnd(@NonNull ViewGroup view) {
view.scrollTo(0, mStartScrollY);
if (mOverScrollMode != View.OVER_SCROLL_NEVER) {
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 5c045b65be22..7a5c38385f32 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -20,6 +20,7 @@
#include "android_media_AudioTrack.h"
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
#include <utils/Log.h>
@@ -251,7 +252,7 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
jint audioFormat, jint buffSizeInBytes, jint memoryMode,
jintArray jSession, jlong nativeAudioTrack,
jboolean offload, jint encapsulationMode,
- jobject tunerConfiguration) {
+ jobject tunerConfiguration, jstring opPackageName) {
ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
" nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
@@ -337,7 +338,8 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
}
// create the native AudioTrack object
- lpTrack = new AudioTrack();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ lpTrack = new AudioTrack(opPackageNameStr.c_str());
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -371,23 +373,24 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
status_t status = NO_ERROR;
switch (memoryMode) {
case MODE_STREAM:
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- offload ? 0 : frameCount,
- offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- 0,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
- offload ? &offloadInfo : NULL,
- -1, -1, // default uid, pid values
- paa.get());
-
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, offload ? 0 : frameCount,
+ offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
+ : AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ 0, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
+ : AudioTrack::TRANSFER_SYNC,
+ offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values
+ paa.get());
break;
case MODE_STATIC:
@@ -398,22 +401,22 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
goto native_init_failure;
}
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- lpJniStorage->mMemBase,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- AudioTrack::TRANSFER_SHARED,
- NULL, // default offloadInfo
- -1, -1, // default uid, pid values
- paa.get());
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, frameCount, AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ lpJniStorage->mMemBase, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ AudioTrack::TRANSFER_SHARED,
+ NULL, // default offloadInfo
+ -1, -1, // default uid, pid values
+ paa.get());
break;
default:
@@ -1428,7 +1431,8 @@ static const JNINativeMethod gMethods[] = {
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;)I",
+ {"native_setup",
+ "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 57c1fcf7bfb4..cdcb24b6a247 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3094,7 +3094,8 @@
android:protectionLevel="signature" />
<!-- Allows an application to be the status bar. Currently used only by SystemUI.apk
- @hide -->
+ @hide
+ @SystemApi -->
<permission android:name="android.permission.STATUS_BAR_SERVICE"
android:protectionLevel="signature" />
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 34e6efb2bf78..fcf9b837cfa1 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1261,7 +1261,7 @@
<string name="volume_ringtone" msgid="134784084629229029">"Hlasitost vyzvánění"</string>
<string name="volume_music" msgid="7727274216734955095">"Hlasitost médií"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="2614142915948898228">"Přehrávání pomocí rozhraní Bluetooth"</string>
- <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzváněcí tón"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzvánění"</string>
<string name="volume_call" msgid="7625321655265747433">"Hlasitost hovoru"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Hlasitost příchozích hovorů při připojení Bluetooth"</string>
<string name="volume_alarm" msgid="4486241060751798448">"Hlasitost budíku"</string>
@@ -1272,10 +1272,10 @@
<string name="volume_icon_description_incall" msgid="4491255105381227919">"Hlasitost hovoru"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"Hlasitost médií"</string>
<string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string>
- <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzváněcí tón"</string>
+ <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string>
- <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzváněcí tóny"</string>
+ <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string>
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string>
<string name="ringtone_unknown" msgid="5059495249862816475">"Neznámé"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 117fecb0ffd0..0b7e396839ef 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -657,7 +657,7 @@
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"observer netværksforhold"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"skift kalibrering for inputenheden"</string>
- <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for touchskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"få adgang til DRM-certifikater"</string>
<string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"Tillader, at en applikation provisionerer og anvender DRM-certifikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"modtag status for Android Beam-overførsler"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index ecce980c613f..c93dbbfda5ef 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -484,8 +484,8 @@
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Telefonoaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"bilatu gailuko kontuak"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dituzun aplikazioek sortutako kontuak egon litezke."</string>
- <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dauzkazun aplikazioek sortutako kontuak egon litezke."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"ikusi sareko konexioak"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"izan sarerako sarbide osoa"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f9e3e2fa97e7..f4fb83deba39 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -2035,7 +2035,7 @@
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Aplikasi ini tidak diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Beranda"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"Kembali"</string>
- <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi yang Baru Dipakai"</string>
+ <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi Terbaru"</string>
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Notifikasi"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Setelan Cepat"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dialog Daya"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index bb79c2193a36..ee0362e4a184 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -304,13 +304,13 @@
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"फाइल र मिडिया"</string>
- <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा तस्बिर, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
+ <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा फोटो, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफोन"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"अडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"शारीरिक क्रियाकलाप"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"आफ्नो शारीरिक क्रियाकलापको डेटामाथि पहुँच राख्नु"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"क्यामेरा"</string>
- <string name="permgroupdesc_camera" msgid="7585150538459320326">"तस्बिर खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
+ <string name="permgroupdesc_camera" msgid="7585150538459320326">"फोटो खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कलका लगहरू"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"फोन कलको लग पढ्नुहोस् र लेख्नुहोस्"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
@@ -437,10 +437,10 @@
<string name="permdesc_sim_communication" msgid="4179799296415957960">"SIM लाई आदेश पठाउन एपलाई अनुमति दिन्छ। यो निकै खतरनाक हुन्छ।"</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"शारीरिक गतिविधि पहिचान गर्नुहोस्‌"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"यो अनुप्रयोगले तपाईंको शारीरिक गतिविधिको पहिचान गर्न सक्छ।"</string>
- <string name="permlab_camera" msgid="6320282492904119413">"तस्बिरहरू र भिडियोहरू लिनुहोस्।"</string>
- <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
- <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई तस्बिर र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
- <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"फोटोहरू र भिडियोहरू लिनुहोस्।"</string>
+ <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
+ <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई फोटो र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
+ <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"कुनै एप वा सेवालाई खोलिँदै वा बन्द गरिँदै गरेका क्यामेरा यन्त्रहरूका बारेमा कलब्याक प्राप्त गर्ने अनुमति दिनुहोस्।"</string>
<string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"कुनै क्यामेरा यन्त्र खोलिँदा (कुन अनुप्रयोगले खोलेको भन्ने बारेमा) वा बन्द गरिँदा यो अनुप्रयोगले कलब्याक प्राप्त गर्न सक्छ।"</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
@@ -1347,7 +1347,7 @@
<string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेटअप गर्न ट्याप गर्नुहोस्"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"तपाईंले यो यन्त्र पुनः फर्म्याट गर्नु पर्ने हुन सक्छ। यो यन्त्र हटाउन ट्याप गर्नुहोस्।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"तस्बिरहरू र मिडिया स्थानान्तरणका लागि"</string>
+ <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फोटोहरू र मिडिया स्थानान्तरणका लागि"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> मा समस्या देखियो"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"समस्या समाधान गर्न ट्याप गर्नुहोस्"</string>
@@ -1914,7 +1914,7 @@
<string name="app_category_game" msgid="4534216074910244790">"खेलहरू"</string>
<string name="app_category_audio" msgid="8296029904794676222">"सङ्गीत तथा अडियो"</string>
<string name="app_category_video" msgid="2590183854839565814">"चलचित्र तथा भिडियो"</string>
- <string name="app_category_image" msgid="7307840291864213007">"तस्बिर तथा छविहरू"</string>
+ <string name="app_category_image" msgid="7307840291864213007">"फोटो तथा छविहरू"</string>
<string name="app_category_social" msgid="2278269325488344054">"सामाजिक तथा सञ्चार"</string>
<string name="app_category_news" msgid="1172762719574964544">"समाचार तथा पत्रिकाहरू"</string>
<string name="app_category_maps" msgid="6395725487922533156">"नक्सा तथा नेभिगेसन"</string>
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
new file mode 100644
index 000000000000..7480a200ee4e
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_GESTURE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.view.FrameMetrics;
+import android.view.View;
+import android.view.ViewAttachTestActivity;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+public class FrameTrackerTest {
+ private ViewAttachTestActivity mActivity;
+
+ @Rule
+ public ActivityTestRule<ViewAttachTestActivity> mRule =
+ new ActivityTestRule<>(ViewAttachTestActivity.class);
+
+ private FrameTracker mTracker;
+ private ThreadedRendererWrapper mRenderer;
+ private FrameMetricsWrapper mWrapper;
+
+ @Before
+ public void setup() {
+ // Prepare an activity for getting ThreadedRenderer later.
+ mActivity = mRule.getActivity();
+ View view = mActivity.getWindow().getDecorView();
+ assertThat(view.isAttachedToWindow()).isTrue();
+
+ Handler handler = mRule.getActivity().getMainThreadHandler();
+ mWrapper = Mockito.spy(new FrameMetricsWrapper());
+ mRenderer = Mockito.spy(new ThreadedRendererWrapper(view.getThreadedRenderer()));
+ doNothing().when(mRenderer).addObserver(any());
+ doNothing().when(mRenderer).removeObserver(any());
+
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ mTracker = Mockito.spy(new FrameTracker(session, handler, mRenderer, mWrapper));
+ doNothing().when(mTracker).triggerPerfetto();
+ }
+
+ @Test
+ public void testIsJankyFrame() {
+ // We skip the first frame.
+ doReturn(1L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+
+ // Should exceed the criteria.
+ doReturn(0L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isTrue();
+
+ // Should be safe.
+ doReturn(TimeUnit.MILLISECONDS.toNanos(10L))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+ }
+
+ @Test
+ public void testBeginEnd() {
+ // assert the initial values
+ assertThat(mTracker.mBeginTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+
+ // Observer should be only added once in continuous calls.
+ mTracker.begin();
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // assert the values after begin call.
+ assertThat(mTracker.mBeginTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+
+ // simulate the callback during trace session
+ // assert the isJankyFrame should be invoked as well.
+ doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ doReturn(true).when(mTracker).isJankyFrame(any());
+ mTracker.onFrameMetricsAvailable(0);
+ verify(mTracker).isJankyFrame(any());
+
+ // end the trace session, simulate a callback came after the end call.
+ // assert the end time should be set, the observer should be removed.
+ // triggerPerfetto should be invoked as well.
+ mTracker.end();
+ doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
+ assertThat(mTracker.mEndTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ mTracker.onFrameMetricsAvailable(0);
+ verify(mRenderer).removeObserver(any());
+ verify(mTracker).triggerPerfetto();
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
new file mode 100644
index 000000000000..5c0b0c94f6d0
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_GESTURE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.view.View;
+import android.view.ViewAttachTestActivity;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
+import com.android.internal.jank.InteractionJankMonitor.Session;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.testng.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SmallTest
+public class InteractionJankMonitorTest {
+ private ViewAttachTestActivity mActivity;
+ private View mView;
+ private FrameTracker mTracker;
+
+ @Rule
+ public ActivityTestRule<ViewAttachTestActivity> mRule =
+ new ActivityTestRule<>(ViewAttachTestActivity.class);
+
+ @Before
+ public void setup() {
+ // Prepare an activity for getting ThreadedRenderer later.
+ mActivity = mRule.getActivity();
+ mView = mActivity.getWindow().getDecorView();
+ assertThat(mView.isAttachedToWindow()).isTrue();
+
+ InteractionJankMonitor.reset();
+
+ // Prepare a FrameTracker to inject.
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ FrameMetricsWrapper wrapper = Mockito.spy(new FrameTracker.FrameMetricsWrapper());
+ ThreadedRendererWrapper renderer =
+ Mockito.spy(new ThreadedRendererWrapper(mView.getThreadedRenderer()));
+ Handler handler = mActivity.getMainThreadHandler();
+ mTracker = Mockito.spy(new FrameTracker(session, handler, renderer, wrapper));
+ }
+
+ @Test
+ public void testBeginEnd() {
+ // Should throw exception if the view is not attached.
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.init(new View(mActivity)));
+
+ // Verify we init InteractionJankMonitor correctly.
+ Map<String, FrameTracker> map = new HashMap<>();
+ HandlerThread worker = Mockito.spy(new HandlerThread("Aot-test"));
+ doNothing().when(worker).start();
+ InteractionJankMonitor.init(mView, mView.getThreadedRenderer(), map, worker);
+ verify(worker).start();
+
+ // Simulate a trace session and see if begin / end are invoked.
+ Session session = new Session(CUJ_NOTIFICATION_SHADE_GESTURE);
+ assertThat(map.get(session.getName())).isNull();
+ InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE, mTracker);
+ verify(mTracker).begin();
+ assertThat(map.get(session.getName())).isEqualTo(mTracker);
+ InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE);
+ verify(mTracker).end();
+ assertThat(map.get(session.getName())).isNull();
+ }
+
+ @Test
+ public void testCheckInitState() {
+ // Should throw exception if invoking begin / end without init invocation.
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE));
+ Assert.assertThrows(IllegalStateException.class,
+ () -> InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE));
+
+ // Everything should be fine if invoking init first.
+ boolean thrown = false;
+ try {
+ InteractionJankMonitor.init(mActivity.getWindow().getDecorView());
+ InteractionJankMonitor.begin(CUJ_NOTIFICATION_SHADE_GESTURE);
+ InteractionJankMonitor.end(CUJ_NOTIFICATION_SHADE_GESTURE);
+ } catch (Exception ex) {
+ thrown = true;
+ } finally {
+ assertThat(thrown).isFalse();
+ }
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java b/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
index 63a68e99b788..ab13fd7d81e0 100644
--- a/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/view/ScrollViewCaptureHelperTest.java
@@ -21,12 +21,11 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import static androidx.test.InstrumentationRegistry.getContext;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -40,10 +39,12 @@ import android.widget.ScrollView;
import android.widget.TextView;
import androidx.test.annotation.UiThreadTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.view.ScrollCaptureViewHelper.ScrollResult;
import org.junit.After;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Random;
@@ -67,28 +68,27 @@ public class ScrollViewCaptureHelperTest {
private Random mRandom;
- private static float sDensity;
-
- @BeforeClass
- public static void setUpClass() {
- sDensity = getContext().getResources().getDisplayMetrics().density;
- }
+ private Context mContext;
+ private float mDensity;
@Before
@UiThreadTest
public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mDensity = mContext.getResources().getDisplayMetrics().density;
+
mRandom = new Random();
- mParent = new FrameLayout(getContext());
+ mParent = new FrameLayout(mContext);
- mTarget = new ScrollView(getContext());
+ mTarget = new ScrollView(mContext);
mParent.addView(mTarget, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- mContent = new LinearLayout(getContext());
+ mContent = new LinearLayout(mContext);
mContent.setOrientation(LinearLayout.VERTICAL);
mTarget.addView(mContent, new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
for (int i = 0; i < CHILD_VIEWS; i++) {
- TextView view = new TextView(getContext());
+ TextView view = new TextView(mContext);
view.setText("Child #" + i);
view.setTextColor(Color.WHITE);
view.setTextSize(30f);
@@ -99,7 +99,7 @@ public class ScrollViewCaptureHelperTest {
// Window -> Parent -> Target -> Content
- mWm = getContext().getSystemService(WindowManager.class);
+ mWm = mContext.getSystemService(WindowManager.class);
// Setup the window that we are going to use
mWindowLayoutParams = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT,
@@ -123,58 +123,6 @@ public class ScrollViewCaptureHelperTest {
svc.onPrepareForStart(mTarget, scrollBounds);
}
- static void assertEmpty(Rect r) {
- if (r != null && !r.isEmpty()) {
- fail("Not true that " + r + " is empty");
- }
- }
-
- static void assertContains(Rect parent, Rect child) {
- if (!parent.contains(child)) {
- fail("Not true that " + parent + " contains " + child);
- }
- }
-
- static void assertRectEquals(Rect parent, Rect child) {
- if (!parent.equals(child)) {
- fail("Not true that " + parent + " is equal to " + child);
- }
- }
-
- static Rect getVisibleRect(View v) {
- Rect r = new Rect(0, 0, v.getWidth(), v.getHeight());
- v.getLocalVisibleRect(r);
- return r;
- }
-
-
- static int assertScrollToY(View v, int scrollY) {
- v.scrollTo(0, scrollY);
- int dest = v.getScrollY();
- assertEquals(scrollY, dest);
- return scrollY;
- }
-
-
- static void assertCapturedAreaCompletelyVisible(int startScrollY, Rect requestRect,
- Rect localVisibleNow) {
- Rect captured = new Rect(localVisibleNow);
- captured.offset(0, -startScrollY); // make relative
-
- if (!captured.contains(requestRect)) {
- fail("Not true that all of " + requestRect + " is contained by " + captured);
- }
- }
- static void assertCapturedAreaPartiallyVisible(int startScrollY, Rect requestRect,
- Rect localVisibleNow) {
- Rect captured = new Rect(localVisibleNow);
- captured.offset(0, -startScrollY); // make relative
-
- if (!Rect.intersects(captured, requestRect)) {
- fail("Not true that any of " + requestRect + " intersects " + captured);
- }
- }
-
@Test
@UiThreadTest
public void onScrollRequested_up_fromTop() {
@@ -188,12 +136,13 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget,
+ scrollBounds, request);
// The result is an empty rectangle and no scrolling, since it
// is not possible to physically scroll further up to make the
// requested area visible at all (it doesn't exist).
- assertEmpty(result);
+ assertEmpty(scrollResult.availableArea);
}
@Test
@@ -201,7 +150,6 @@ public class ScrollViewCaptureHelperTest {
public void onScrollRequested_down_fromTop() {
final int startScrollY = assertScrollToY(mTarget, 0);
-
ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
Rect scrollBounds = svc.onComputeScrollBounds(mTarget);
svc.onPrepareForStart(mTarget, scrollBounds);
@@ -212,13 +160,13 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
WINDOW_HEIGHT + CAPTURE_HEIGHT);
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(CAPTURE_HEIGHT, scrollResult.scrollDelta);
}
-
@Test
@UiThreadTest
public void onScrollRequested_up_fromMiddle() {
@@ -230,12 +178,11 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
-
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
-
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(-CAPTURE_HEIGHT, scrollResult.scrollDelta);
}
@Test
@@ -250,10 +197,12 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
WINDOW_HEIGHT + CAPTURE_HEIGHT);
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(CAPTURE_HEIGHT, scrollResult.scrollDelta);
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
}
@Test
@@ -267,10 +216,11 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, -CAPTURE_HEIGHT, scrollBounds.width(), 0);
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
- assertRectEquals(request, result);
-
- assertCapturedAreaCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+ assertRectEquals(request, scrollResult.availableArea);
+ assertRequestedRectCompletelyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(-CAPTURE_HEIGHT, scrollResult.scrollDelta);
}
@Test
@@ -285,12 +235,14 @@ public class ScrollViewCaptureHelperTest {
Rect request = new Rect(0, WINDOW_HEIGHT, scrollBounds.width(),
WINDOW_HEIGHT + CAPTURE_HEIGHT);
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
// The result is an empty rectangle and no scrolling, since it
// is not possible to physically scroll further down to make the
// requested area visible at all (it doesn't exist).
- assertEmpty(result);
+ assertEmpty(scrollResult.availableArea);
+ assertEquals(0, scrollResult.scrollDelta);
}
@Test
@@ -309,12 +261,16 @@ public class ScrollViewCaptureHelperTest {
0, top - (CAPTURE_HEIGHT / 2),
scrollBounds.width(), top + (CAPTURE_HEIGHT / 2));
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
+ ScrollResult scrollResult = svc.onScrollRequested(mTarget, scrollBounds, request);
+ assertRectEquals(request, scrollResult.requestedArea);
+
+ ScrollResult result = svc.onScrollRequested(mTarget, scrollBounds, request);
// The result is a partial result
Rect expectedResult = new Rect(request);
expectedResult.top += 300; // top half clipped
- assertRectEquals(expectedResult, result);
- assertCapturedAreaPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertRectEquals(expectedResult, result.availableArea);
+ assertRequestedRectPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(0, scrollResult.scrollDelta);
}
@Test
@@ -334,13 +290,13 @@ public class ScrollViewCaptureHelperTest {
0, bottom - (CAPTURE_HEIGHT / 2),
scrollBounds.width(), bottom + (CAPTURE_HEIGHT / 2));
- Rect result = svc.onScrollRequested(mTarget, scrollBounds, request);
+ ScrollResult result = svc.onScrollRequested(mTarget, scrollBounds, request);
Rect expectedResult = new Rect(request);
expectedResult.bottom -= 300; // bottom half clipped
- assertRectEquals(expectedResult, result);
- assertCapturedAreaPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
-
+ assertRectEquals(expectedResult, result.availableArea);
+ assertRequestedRectPartiallyVisible(startScrollY, request, getVisibleRect(mContent));
+ assertEquals(0, result.scrollDelta);
}
@Test
@@ -349,4 +305,56 @@ public class ScrollViewCaptureHelperTest {
ScrollViewCaptureHelper svc = new ScrollViewCaptureHelper();
svc.onPrepareForEnd(mTarget);
}
+
+
+ static void assertEmpty(Rect r) {
+ if (r != null && !r.isEmpty()) {
+ fail("Not true that " + r + " is empty");
+ }
+ }
+
+ static void assertContains(Rect parent, Rect child) {
+ if (!parent.contains(child)) {
+ fail("Not true that " + parent + " contains " + child);
+ }
+ }
+
+ static void assertRectEquals(Rect parent, Rect child) {
+ if (!parent.equals(child)) {
+ fail("Not true that " + parent + " is equal to " + child);
+ }
+ }
+
+ static Rect getVisibleRect(View v) {
+ Rect r = new Rect(0, 0, v.getWidth(), v.getHeight());
+ v.getLocalVisibleRect(r);
+ return r;
+ }
+
+
+ static int assertScrollToY(View v, int scrollY) {
+ v.scrollTo(0, scrollY);
+ int dest = v.getScrollY();
+ assertEquals(scrollY, dest);
+ return scrollY;
+ }
+
+ static void assertRequestedRectCompletelyVisible(int startScrollY, Rect requestRect,
+ Rect localVisibleNow) {
+ Rect captured = new Rect(localVisibleNow);
+ captured.offset(0, -startScrollY); // make relative
+
+ if (!captured.contains(requestRect)) {
+ fail("Not true that all of " + requestRect + " is contained by " + captured);
+ }
+ }
+ static void assertRequestedRectPartiallyVisible(int startScrollY, Rect requestRect,
+ Rect localVisibleNow) {
+ Rect captured = new Rect(localVisibleNow);
+ captured.offset(0, -startScrollY); // make relative
+
+ if (!Rect.intersects(captured, requestRect)) {
+ fail("Not true that any of " + requestRect + " intersects " + captured);
+ }
+ }
}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index b63a19187b05..1cdc75aa1f40 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -23,8 +23,6 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -32,11 +30,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
@@ -56,7 +50,6 @@ import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
-import android.testing.PollingCheck;
import android.view.WindowManagerGlobal;
import androidx.test.annotation.UiThreadTest;
@@ -70,8 +63,6 @@ import org.mockito.Mockito;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
-import java.util.concurrent.TimeUnit;
-
/**
* Test for verifying {@link android.app.ActivityThread} class.
*
@@ -85,7 +76,6 @@ import java.util.concurrent.TimeUnit;
@MediumTest
@Presubmit
public class ActivityThreadClientTest {
- private static final long WAIT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2);
@Test
@UiThreadTest
@@ -162,63 +152,6 @@ public class ActivityThreadClientTest {
}
}
- @Test
- public void testLifecycleOfRelaunch() throws Exception {
- try (ClientMockSession clientSession = new ClientMockSession()) {
- ActivityThread activityThread = clientSession.mockThread();
- ActivityClientRecord r = clientSession.stubActivityRecord();
- final TestActivity[] activity = new TestActivity[1];
-
- // Verify for ON_CREATE state. Activity should not be relaunched.
- getInstrumentation().runOnMainSync(() -> {
- activity[0] = (TestActivity) clientSession.launchActivity(r);
- });
- recreateAndVerifyNoRelaunch(activityThread, activity[0]);
-
- // Verify for ON_START state. Activity should be relaunched.
- getInstrumentation().runOnMainSync(() -> clientSession.startActivity(r));
- recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_START);
-
- // Verify for ON_RESUME state. Activity should be relaunched.
- getInstrumentation().runOnMainSync(() -> clientSession.resumeActivity(r));
- recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_RESUME);
-
- // Verify for ON_PAUSE state. Activity should be relaunched.
- getInstrumentation().runOnMainSync(() -> clientSession.pauseActivity(r));
- recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_PAUSE);
-
- // Verify for ON_STOP state. Activity should be relaunched.
- getInstrumentation().runOnMainSync(() -> clientSession.stopActivity(r));
- recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_STOP);
-
- // Verify for ON_DESTROY state. Activity should not be relaunched.
- getInstrumentation().runOnMainSync(() -> clientSession.destroyActivity(r));
- recreateAndVerifyNoRelaunch(activityThread, activity[0]);
- }
- }
-
- private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) {
- clearInvocations(activityThread);
- getInstrumentation().runOnMainSync(() -> activity.recreate());
-
- verify(activityThread, after(WAIT_TIMEOUT_MS).never())
- .handleRelaunchActivity(any(), any());
- }
-
- private void recreateAndVerifyRelaunched(ActivityThread activityThread, TestActivity activity,
- ActivityClientRecord r, int expectedState) throws Exception {
- clearInvocations(activityThread);
- getInstrumentation().runOnMainSync(() -> activity.recreate());
-
- verify(activityThread, timeout(WAIT_TIMEOUT_MS)).handleRelaunchActivity(any(), any());
-
- // Wait for the relaunch to complete.
- PollingCheck.check("Waiting for the expected state " + expectedState + " timeout",
- WAIT_TIMEOUT_MS,
- () -> expectedState == r.getLifecycleState());
- assertEquals(expectedState, r.getLifecycleState());
- }
-
private class ClientMockSession implements AutoCloseable {
private MockitoSession mMockSession;
private ActivityThread mThread;
@@ -267,11 +200,6 @@ public class ActivityThreadClientTest {
false /* getNonConfigInstance */, "test");
}
- private ActivityThread mockThread() {
- spyOn(mThread);
- return mThread;
- }
-
private ActivityClientRecord stubActivityRecord() {
ComponentName component = new ComponentName(
InstrumentationRegistry.getInstrumentation().getContext(), TestActivity.class);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1c0a526f536c..de2a7b2c15e3 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -807,7 +807,8 @@ public class AudioTrack extends PlayerBase
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
- offload, encapsulationMode, tunerConfiguration);
+ offload, encapsulationMode, tunerConfiguration,
+ getCurrentOpPackageName());
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -893,7 +894,8 @@ public class AudioTrack extends PlayerBase
nativeTrackInJavaObj,
false /*offload*/,
ENCAPSULATION_MODE_NONE,
- null /* tunerConfiguration */);
+ null /* tunerConfiguration */,
+ "" /* opPackagename */);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -4062,7 +4064,8 @@ public class AudioTrack extends PlayerBase
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack,
- boolean offload, int encapsulationMode, Object tunerConfiguration);
+ boolean offload, int encapsulationMode, Object tunerConfiguration,
+ @NonNull String opPackageName);
private native final void native_finalize();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 49e416080041..36ae3ec75a99 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -672,7 +672,8 @@ public class MediaPlayer extends PlayerBase
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
- native_setup(new WeakReference<MediaPlayer>(this));
+ native_setup(new WeakReference<MediaPlayer>(this),
+ getCurrentOpPackageName());
baseRegisterPlayer();
}
@@ -2378,7 +2379,7 @@ public class MediaPlayer extends PlayerBase
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
- private native final void native_setup(Object mediaplayer_this);
+ private native void native_setup(Object mediaplayerThis, @NonNull String opPackageName);
private native final void native_finalize();
/**
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index ee8f1b3eec77..df5e85edbc30 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -27,6 +27,7 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -622,4 +623,8 @@ public abstract class PlayerBase {
Log.w(className, "See the documentation of " + opName + " for what to use instead with " +
"android.media.AudioAttributes to qualify your playback use case");
}
+
+ protected String getCurrentOpPackageName() {
+ return TextUtils.emptyIfNull(ActivityThread.currentOpPackageName());
+ }
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 55aac09b0f65..bd8d2e9f77a4 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -33,6 +33,7 @@
#include <utils/threads.h>
#include "jni.h"
#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
#include "android_runtime/Log.h"
@@ -944,10 +945,12 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
}
static void
-android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
+ jstring opPackageName)
{
ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ sp<MediaPlayer> mp = new MediaPlayer(opPackageNameStr.c_str());
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1403,7 +1406,7 @@ static const JNINativeMethod gMethods[] = {
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
- {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
diff --git a/media/packages/BluetoothMidiService/Android.bp b/media/packages/BluetoothMidiService/Android.bp
index 48fc329276bd..25c34c3631dc 100644
--- a/media/packages/BluetoothMidiService/Android.bp
+++ b/media/packages/BluetoothMidiService/Android.bp
@@ -29,6 +29,5 @@ android_app {
"src/**/*.java",
],
platform_apis: true,
- certificate: "platform",
manifest: "AndroidManifest.xml",
}
diff --git a/media/packages/BluetoothMidiService/AndroidManifest.xml b/media/packages/BluetoothMidiService/AndroidManifest.xml
index b88bf2a0b2b7..fc96fd926e2d 100644
--- a/media/packages/BluetoothMidiService/AndroidManifest.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifest.xml
@@ -19,8 +19,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.bluetoothmidiservice"
- android:versionCode="1"
- android:versionName="R-initial"
>
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
diff --git a/media/packages/BluetoothMidiService/AndroidManifestBase.xml b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
index ebe62b039434..bfb05469adb9 100644
--- a/media/packages/BluetoothMidiService/AndroidManifestBase.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifestBase.xml
@@ -18,8 +18,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.bluetoothmidiservice"
- android:versionCode="1"
- android:versionName="R-initial"
>
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<application
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index d1264dfdd36d..7cce0f2f4b3e 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -219,6 +219,7 @@ package android {
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+ field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
index 90396717de9f..1a6fdfa9c996 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
@@ -16,7 +16,6 @@
package com.android.systemui;
-import com.android.systemui.dagger.DependencyBinder;
import com.android.systemui.dagger.DependencyProvider;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.SysUISingleton;
@@ -32,7 +31,6 @@ import dagger.Subcomponent;
@Subcomponent(modules = {
CarComponentBinder.class,
DependencyProvider.class,
- DependencyBinder.class,
PipModule.class,
SystemUIModule.class,
CarSystemUIModule.class,
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 3eea5132da1d..51fda965dcd0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -52,10 +52,10 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -92,7 +92,7 @@ abstract class CarSystemUIModule {
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
index a2ba880facfe..fef032414bb9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
@@ -16,20 +16,19 @@
package com.android.systemui.car;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.car.settings.CarSettings;
-import android.content.ContentResolver;
-import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
-import android.provider.Settings;
-import com.android.systemui.Dependency;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -40,30 +39,33 @@ import javax.inject.Inject;
@SysUISingleton
public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControllerImpl implements
CarDeviceProvisionedController {
- private static final Uri USER_SETUP_IN_PROGRESS_URI = Settings.Secure.getUriFor(
- CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS);
- private final ContentObserver mCarSettingsObserver = new ContentObserver(
- Dependency.get(Dependency.MAIN_HANDLER)) {
-
- @Override
- public void onChange(boolean selfChange, Uri uri, int flags) {
- if (USER_SETUP_IN_PROGRESS_URI.equals(uri)) {
- notifyUserSetupInProgressChanged();
- }
- }
- };
- private final ContentResolver mContentResolver;
+ private final Uri mUserSetupInProgressUri;
+ private final ContentObserver mCarSettingsObserver;
+ private final Handler mMainHandler;
+ private final SecureSettings mSecureSettings;
@Inject
- public CarDeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
- BroadcastDispatcher broadcastDispatcher) {
- super(context, mainHandler, broadcastDispatcher);
- mContentResolver = context.getContentResolver();
+ public CarDeviceProvisionedControllerImpl(@Main Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSetting,
+ SecureSettings secureSettings) {
+ super(mainHandler, broadcastDispatcher, globalSetting, secureSettings);
+ mMainHandler = mainHandler;
+ mSecureSettings = secureSettings;
+ mUserSetupInProgressUri = mSecureSettings.getUriFor(
+ CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS);
+ mCarSettingsObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int flags) {
+ if (mUserSetupInProgressUri.equals(uri)) {
+ notifyUserSetupInProgressChanged();
+ }
+ }
+ };
}
@Override
public boolean isUserSetupInProgress(int user) {
- return Settings.Secure.getIntForUser(mContentResolver,
+ return mSecureSettings.getIntForUser(
CarSettings.Secure.KEY_SETUP_WIZARD_IN_PROGRESS, /* def= */ 0, user) != 0;
}
@@ -73,7 +75,7 @@ public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControl
}
@Override
- public void addCallback(DeviceProvisionedListener listener) {
+ public void addCallback(@NonNull DeviceProvisionedListener listener) {
super.addCallback(listener);
if (listener instanceof CarDeviceProvisionedListener) {
((CarDeviceProvisionedListener) listener).onUserSetupInProgressChanged();
@@ -82,9 +84,9 @@ public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControl
@Override
protected void startListening(int user) {
- mContentResolver.registerContentObserver(
- USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
- user);
+ mSecureSettings.registerContentObserverForUser(
+ mUserSetupInProgressUri, /* notifyForDescendants= */ true,
+ mCarSettingsObserver, user);
// The SUW Flag observer is registered before super.startListening() so that the observer is
// in place before DeviceProvisionedController starts to track user switches which avoids
// an edge case where our observer gets registered twice.
@@ -94,16 +96,16 @@ public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControl
@Override
protected void stopListening() {
super.stopListening();
- mContentResolver.unregisterContentObserver(mCarSettingsObserver);
+ mSecureSettings.unregisterContentObserver(mCarSettingsObserver);
}
@Override
public void onUserSwitched(int newUserId) {
super.onUserSwitched(newUserId);
- mContentResolver.unregisterContentObserver(mCarSettingsObserver);
- mContentResolver.registerContentObserver(
- USER_SETUP_IN_PROGRESS_URI, /* notifyForDescendants= */ true, mCarSettingsObserver,
- newUserId);
+ mSecureSettings.unregisterContentObserver(mCarSettingsObserver);
+ mSecureSettings.registerContentObserverForUser(
+ mUserSetupInProgressUri, /* notifyForDescendants= */ true,
+ mCarSettingsObserver, newUserId);
}
private void notifyUserSetupInProgressChanged() {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
index 276ddfbc2b4f..dadbc22760b9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -18,7 +18,6 @@ package com.android.systemui.car.keyguard;
import android.car.Car;
import android.car.user.CarUserManager;
-import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@@ -28,20 +27,17 @@ import android.view.ViewRootImpl;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -63,18 +59,14 @@ public class CarKeyguardViewController extends OverlayViewController implements
private static final String TAG = "CarKeyguardViewController";
private static final boolean DEBUG = true;
- private final Context mContext;
private final Handler mHandler;
private final CarServiceProvider mCarServiceProvider;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
- private final LockPatternUtils mLockPatternUtils;
- private final FalsingManager mFalsingManager;
- private final Lazy<KeyguardBypassController> mKeyguardBypassControllerLazy;
- private final DismissCallbackRegistry mDismissCallbackRegistry;
private final ViewMediatorCallback mViewMediatorCallback;
private final CarNavigationBarController mCarNavigationBarController;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
// Needed to instantiate mBouncer.
private final KeyguardBouncer.BouncerExpansionCallback
mExpansionCallback = new KeyguardBouncer.BouncerExpansionCallback() {
@@ -107,7 +99,6 @@ public class CarKeyguardViewController extends OverlayViewController implements
@Inject
public CarKeyguardViewController(
- Context context,
@Main Handler mainHandler,
CarServiceProvider carServiceProvider,
OverlayViewGlobalStateController overlayViewGlobalStateController,
@@ -116,26 +107,18 @@ public class CarKeyguardViewController extends OverlayViewController implements
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
ViewMediatorCallback viewMediatorCallback,
CarNavigationBarController carNavigationBarController,
- /* The params below are only used to reuse KeyguardBouncer */
- LockPatternUtils lockPatternUtils,
- DismissCallbackRegistry dismissCallbackRegistry,
- FalsingManager falsingManager,
- Lazy<KeyguardBypassController> keyguardBypassControllerLazy) {
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
super(R.id.keyguard_stub, overlayViewGlobalStateController);
- mContext = context;
mHandler = mainHandler;
mCarServiceProvider = carServiceProvider;
mKeyguardStateController = keyguardStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
- mLockPatternUtils = lockPatternUtils;
- mFalsingManager = falsingManager;
- mKeyguardBypassControllerLazy = keyguardBypassControllerLazy;
- mDismissCallbackRegistry = dismissCallbackRegistry;
mViewMediatorCallback = viewMediatorCallback;
mCarNavigationBarController = carNavigationBarController;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
registerUserSwitchedListener();
}
@@ -147,11 +130,9 @@ public class CarKeyguardViewController extends OverlayViewController implements
@Override
public void onFinishInflate() {
- mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
- mViewMediatorCallback, mLockPatternUtils,
- getLayout().findViewById(R.id.keyguard_container), mDismissCallbackRegistry,
- mExpansionCallback, mKeyguardStateController, mFalsingManager,
- mKeyguardBypassControllerLazy.get());
+ mBouncer = mKeyguardBouncerComponentFactory
+ .build(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback)
+ .createKeyguardBouncer();
mBiometricUnlockControllerLazy.get().setKeyguardViewController(this);
}
@@ -359,9 +340,8 @@ public class CarKeyguardViewController extends OverlayViewController implements
public void registerStatusBar(StatusBar statusBar, ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry, ViewGroup lockIconContainer,
- View notificationContainer, KeyguardBypassController bypassController,
- FalsingManager falsingManager) {
+ ViewGroup lockIconContainer,
+ View notificationContainer, KeyguardBypassController bypassController) {
// no-op
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index 38e1a48ab3a7..fe4cba8e73cd 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -91,7 +91,6 @@ public class NotificationPanelViewController extends OverlayPanelViewController
private RecyclerView mNotificationList;
private NotificationViewController mNotificationViewController;
- private boolean mIsTracking;
private boolean mNotificationListAtEnd;
private float mFirstTouchDownOnGlassPane;
private boolean mNotificationListAtEndAtTimeOfTouch;
@@ -306,7 +305,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
mFirstTouchDownOnGlassPane = event.getRawX();
mNotificationListAtEndAtTimeOfTouch = mNotificationListAtEnd;
// Reset the tracker when there is a touch down on the glass pane.
- mIsTracking = false;
+ setIsTracking(false);
// Pass the down event to gesture detector so that it knows where the touch event
// started.
closeGestureDetector.onTouchEvent(event);
@@ -341,15 +340,15 @@ public class NotificationPanelViewController extends OverlayPanelViewController
// If the card is swiping we should not allow the notification shade to close.
// Hence setting mNotificationListAtEndAtTimeOfTouch to false will stop that
- // for us. We are also checking for mIsTracking because while swiping the
+ // for us. We are also checking for isTracking() because while swiping the
// notification shade to close if the user goes a bit horizontal while swiping
// upwards then also this should close.
- if (mIsNotificationCardSwiping && !mIsTracking) {
+ if (mIsNotificationCardSwiping && !isTracking()) {
mNotificationListAtEndAtTimeOfTouch = false;
}
boolean handled = closeGestureDetector.onTouchEvent(event);
- boolean isTracking = mIsTracking;
+ boolean isTracking = isTracking();
Rect rect = getLayout().getClipBounds();
float clippedHeight = 0;
if (rect != null) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
index 5bd8797c5349..023b5b4f5f30 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
@@ -131,7 +131,7 @@ public class UserGridRecyclerView extends RecyclerView {
}
private List<UserInfo> getUsersForUserGrid() {
- return mUserManager.getUsers(/* excludeDying= */ true)
+ return mUserManager.getAliveUsers()
.stream()
.filter(UserInfo::supportsSwitchToByUser)
.collect(Collectors.toList());
@@ -338,7 +338,7 @@ public class UserGridRecyclerView extends RecyclerView {
maxSupportedUsers -= 1;
}
- List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */ true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
// Count all users that are managed profiles of another user.
int managedProfilesCount = 0;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
index bde31f18d8fd..1b00c6301011 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
@@ -297,14 +297,17 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
float from = getCurrentStartPosition(rect);
if (from != to) {
animate(from, to, velocity, isClosing);
- return;
}
+
+ // If we swipe down the notification panel all the way to the bottom of the screen
+ // (i.e. from == to), then we have finished animating the panel.
+ return;
}
// We will only be here if the shade is being opened programmatically or via button when
// height of the layout was not calculated.
- ViewTreeObserver notificationTreeObserver = getLayout().getViewTreeObserver();
- notificationTreeObserver.addOnGlobalLayoutListener(
+ ViewTreeObserver panelTreeObserver = getLayout().getViewTreeObserver();
+ panelTreeObserver.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
@@ -507,6 +510,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
return mIsTracking;
}
+ /** Sets whether the panel is currently tracking or not. */
+ protected final void setIsTracking(boolean isTracking) {
+ mIsTracking = isTracking;
+ }
+
/** Returns {@code true} if the panel is currently animating. */
protected final boolean isAnimating() {
return mIsAnimating;
@@ -545,7 +553,7 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
}
setPanelVisible(true);
- // clips the view for the notification shade when the user scrolls to open.
+ // clips the view for the panel when the user scrolls to open.
setViewClipBounds((int) event2.getRawY());
// Initially the scroll starts with height being zero. This checks protects from divide
@@ -600,11 +608,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
boolean isInClosingDirection = mAnimateDirection * distanceY > 0;
// This check is to figure out if onScroll was called while swiping the card at
- // bottom of the list. At that time we should not allow notification shade to
+ // bottom of the panel. At that time we should not allow panel to
// close. We are also checking for the upwards swipe gesture here because it is
- // possible if a user is closing the notification shade and while swiping starts
+ // possible if a user is closing the panel and while swiping starts
// to open again but does not fling. At that time we should allow the
- // notification shade to close fully or else it would stuck in between.
+ // panel to close fully or else it would stuck in between.
if (Math.abs(getLayout().getHeight() - y)
> SWIPE_DOWN_MIN_DISTANCE && isInClosingDirection) {
setViewClipBounds((int) y);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
index 62dc23624520..63d4004fb640 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -35,20 +34,17 @@ import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
-import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.CarSystemUiTest;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -58,31 +54,36 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import dagger.Lazy;
-
@CarSystemUiTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class CarKeyguardViewControllerTest extends SysuiTestCase {
- private TestableCarKeyguardViewController mCarKeyguardViewController;
+ private CarKeyguardViewController mCarKeyguardViewController;
@Mock
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
@Mock
- private KeyguardBouncer mBouncer;
+ private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener;
@Mock
- private CarNavigationBarController mCarNavigationBarController;
+ private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
@Mock
- private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener;
+ private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ @Mock
+ private KeyguardBouncer mBouncer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mCarKeyguardViewController = new TestableCarKeyguardViewController(
- mContext,
+ when(mKeyguardBouncerComponentFactory.build(
+ any(ViewGroup.class),
+ any(KeyguardBouncer.BouncerExpansionCallback.class)))
+ .thenReturn(mKeyguardBouncerComponent);
+ when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+
+ mCarKeyguardViewController = new CarKeyguardViewController(
Handler.getMain(),
mock(CarServiceProvider.class),
mOverlayViewGlobalStateController,
@@ -91,10 +92,7 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
() -> mock(BiometricUnlockController.class),
mock(ViewMediatorCallback.class),
mock(CarNavigationBarController.class),
- mock(LockPatternUtils.class),
- mock(DismissCallbackRegistry.class),
- mock(FalsingManager.class),
- () -> mock(KeyguardBypassController.class)
+ mKeyguardBouncerComponentFactory
);
mCarKeyguardViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.sysui_overlay_window, /* root= */ null));
@@ -202,33 +200,4 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
verify(mBouncer).hide(/* destroyView= */ true);
}
-
- private class TestableCarKeyguardViewController extends CarKeyguardViewController {
-
- TestableCarKeyguardViewController(Context context,
- Handler mainHandler,
- CarServiceProvider carServiceProvider,
- OverlayViewGlobalStateController overlayViewGlobalStateController,
- KeyguardStateController keyguardStateController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- ViewMediatorCallback viewMediatorCallback,
- CarNavigationBarController carNavigationBarController,
- LockPatternUtils lockPatternUtils,
- DismissCallbackRegistry dismissCallbackRegistry,
- FalsingManager falsingManager,
- Lazy<KeyguardBypassController> keyguardBypassControllerLazy) {
- super(context, mainHandler, carServiceProvider, overlayViewGlobalStateController,
- keyguardStateController, keyguardUpdateMonitor, biometricUnlockControllerLazy,
- viewMediatorCallback, carNavigationBarController, lockPatternUtils,
- dismissCallbackRegistry, falsingManager, keyguardBypassControllerLazy);
- }
-
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- setKeyguardBouncer(CarKeyguardViewControllerTest.this.mBouncer);
- }
- }
-
}
diff --git a/packages/CompanionDeviceManager/TEST_MAPPING b/packages/CompanionDeviceManager/TEST_MAPPING
new file mode 100644
index 000000000000..63f54fa35158
--- /dev/null
+++ b/packages/CompanionDeviceManager/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml
new file mode 100644
index 000000000000..16e91903084f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="25.50"
+ android:viewportHeight="25.50">
+ <group
+ android:translateX="0.77"
+ android:translateY="0.23" >
+ <path
+ android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M22.71,15.67l-1.83,1.83l1.83,1.83c0.38,0.38 0.38,1 0,1.38v0c-0.38,0.38 -1,0.39 -1.38,0l-1.83,-1.83l-1.83,1.83c-0.38,0.38 -1,0.38 -1.38,0l-0.01,-0.01c-0.38,-0.38 -0.38,-1 0,-1.38l1.83,-1.83l-1.82,-1.82c-0.38,-0.38 -0.38,-1 0,-1.38l0.01,-0.01c0.38,-0.38 1,-0.38 1.38,0l1.82,1.82l1.82,-1.82c0.38,-0.38 1,-0.38 1.38,0l0,0C23.09,14.67 23.09,15.29 22.71,15.67z"
+ android:fillColor="#FFFFFF"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml
new file mode 100644
index 000000000000..4c338c968194
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2.01C7.25,2.01 2.97,4.09 0,7.4L7.582,16.625C7.582,16.627 7.58,16.629 7.58,16.631L11.99,22L12,22L13,20.789L13,17.641L13,13.119C12.68,13.039 12.34,13 12,13C10.601,13 9.351,13.64 8.531,14.639L2.699,7.539C5.269,5.279 8.58,4.01 12,4.01C15.42,4.01 18.731,5.279 21.301,7.539L16.811,13L19.4,13L24,7.4C21.03,4.09 16.75,2.01 12,2.01z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml
new file mode 100644
index 000000000000..79037dbccf2d
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L12,22L13,20.779L13,17.631L13,13L16.801,13L18,13L19.391,13L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C14.747,4 17.423,4.819 19.701,6.313C20.259,6.678 20.795,7.085 21.301,7.529L17.389,12.287C16.029,10.868 14.119,9.99 12,9.99C9.88,9.99 7.969,10.869 6.609,12.289L2.699,7.529C5.269,5.269 8.58,4 12,4z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml
new file mode 100644
index 000000000000..21ad128f81ff
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L3.301,11.41L12,22L13,20.779L13,17.631L13,13L16.801,13L19.391,13L20.699,11.41C20.699,11.409 20.698,11.409 20.697,11.408L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C15.42,4 18.731,5.269 21.301,7.529L19.35,9.9C17.43,8.1 14.86,6.99 12,6.99C9.14,6.99 6.57,8.1 4.65,9.9C4.65,9.901 4.649,9.902 4.648,9.902L2.699,7.529C5.269,5.269 8.58,4 12,4z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml
new file mode 100644
index 000000000000..2ec5ba30cdc3
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2020 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.08 0,7.39L12,22l1,-1.22V13h6.39L24,7.39C21.03,4.08 16.75,2 12,2z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index a43412e116c8..b2808061586b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -49,11 +49,19 @@ public class Utils {
private static String sSharedSystemSharedLibPackageName;
static final int[] WIFI_PIE = {
- com.android.internal.R.drawable.ic_wifi_signal_0,
- com.android.internal.R.drawable.ic_wifi_signal_1,
- com.android.internal.R.drawable.ic_wifi_signal_2,
- com.android.internal.R.drawable.ic_wifi_signal_3,
- com.android.internal.R.drawable.ic_wifi_signal_4
+ com.android.internal.R.drawable.ic_wifi_signal_0,
+ com.android.internal.R.drawable.ic_wifi_signal_1,
+ com.android.internal.R.drawable.ic_wifi_signal_2,
+ com.android.internal.R.drawable.ic_wifi_signal_3,
+ com.android.internal.R.drawable.ic_wifi_signal_4
+ };
+
+ static final int[] SHOW_X_WIFI_PIE = {
+ R.drawable.ic_show_x_wifi_signal_0,
+ R.drawable.ic_show_x_wifi_signal_1,
+ R.drawable.ic_show_x_wifi_signal_2,
+ R.drawable.ic_show_x_wifi_signal_3,
+ R.drawable.ic_show_x_wifi_signal_4
};
public static void updateLocationEnabled(Context context, boolean enabled, int userId,
@@ -353,10 +361,22 @@ public class Utils {
* @throws IllegalArgumentException if an invalid RSSI level is given.
*/
public static int getWifiIconResource(int level) {
+ return getWifiIconResource(false /* showX */, level);
+ }
+
+ /**
+ * Returns the Wifi icon resource for a given RSSI level.
+ *
+ * @param showX True if a connected Wi-Fi network has the problem which should show Pie+x
+ * signal icon to users.
+ * @param level The number of bars to show (0-4)
+ * @throws IllegalArgumentException if an invalid RSSI level is given.
+ */
+ public static int getWifiIconResource(boolean showX, int level) {
if (level < 0 || level >= WIFI_PIE.length) {
throw new IllegalArgumentException("No Wifi icon found for level: " + level);
}
- return WIFI_PIE[level];
+ return showX ? SHOW_X_WIFI_PIE[level] : WIFI_PIE[level];
}
public static int getDefaultStorageManagerDaysToRetain(Resources resources) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
index a53bc9f966d2..bba69f29a290 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
@@ -35,6 +35,7 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.R;
import com.android.settingslib.Utils;
import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
/**
* Preference to display a WifiEntry in a wifi picker.
@@ -64,6 +65,7 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
private final IconInjector mIconInjector;
private WifiEntry mWifiEntry;
private int mLevel = -1;
+ private boolean mShowX; // Shows the Wi-Fi signl icon of Pie+x when it's true.
private CharSequence mContentDescription;
private OnButtonClickListener mOnButtonClickListener;
@@ -136,9 +138,15 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
public void refresh() {
setTitle(mWifiEntry.getTitle());
final int level = mWifiEntry.getLevel();
- if (level != mLevel) {
+ final ConnectedInfo connectedInfo = mWifiEntry.getConnectedInfo();
+ boolean showX = false;
+ if (connectedInfo != null) {
+ showX = !connectedInfo.isDefaultNetwork || !connectedInfo.isValidated;
+ }
+ if (level != mLevel || showX != mShowX) {
mLevel = level;
- updateIcon(mLevel);
+ mShowX = showX;
+ updateIcon(mShowX, mLevel);
notifyChanged();
}
@@ -184,13 +192,13 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
}
- private void updateIcon(int level) {
+ private void updateIcon(boolean showX, int level) {
if (level == -1) {
setIcon(null);
return;
}
- final Drawable drawable = mIconInjector.getIcon(level);
+ final Drawable drawable = mIconInjector.getIcon(showX, level);
if (drawable != null) {
drawable.setTintList(Utils.getColorAttr(getContext(),
android.R.attr.colorControlNormal));
@@ -260,8 +268,8 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
mContext = context;
}
- public Drawable getIcon(int level) {
- return mContext.getDrawable(Utils.getWifiIconResource(level));
+ public Drawable getIcon(boolean showX, int level) {
+ return mContext.getDrawable(Utils.getWifiIconResource(showX, level));
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index bc58bfc97718..c57d4ad962bd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -13,6 +13,7 @@ package com.android.settingslib.wifi;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import android.content.Context;
import android.content.Intent;
@@ -250,6 +251,10 @@ public class WifiStatusTracker {
statusLabel = mContext.getString(R.string.wifi_status_no_internet);
}
return;
+ } else if (!isDefaultNetwork && mDefaultNetworkCapabilities != null
+ && mDefaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ statusLabel = mContext.getString(R.string.wifi_connected_low_quality);
+ return;
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
index 46e699d3bed5..40af7dc797b3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
@@ -17,6 +17,7 @@ package com.android.settingslib.wifi;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -29,6 +30,7 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.R;
import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
import org.junit.Before;
import org.junit.Test;
@@ -62,6 +64,17 @@ public class WifiEntryPreferenceTest {
@Mock
private Drawable mMockDrawable4;
+ @Mock
+ private Drawable mMockShowXDrawable0;
+ @Mock
+ private Drawable mMockShowXDrawable1;
+ @Mock
+ private Drawable mMockShowXDrawable2;
+ @Mock
+ private Drawable mMockShowXDrawable3;
+ @Mock
+ private Drawable mMockShowXDrawable4;
+
private static final String MOCK_TITLE = "title";
private static final String MOCK_SUMMARY = "summary";
private static final String FAKE_URI_STRING = "fakeuri";
@@ -75,11 +88,22 @@ public class WifiEntryPreferenceTest {
when(mMockWifiEntry.getTitle()).thenReturn(MOCK_TITLE);
when(mMockWifiEntry.getSummary(false /* concise */)).thenReturn(MOCK_SUMMARY);
- when(mMockIconInjector.getIcon(0)).thenReturn(mMockDrawable0);
- when(mMockIconInjector.getIcon(1)).thenReturn(mMockDrawable1);
- when(mMockIconInjector.getIcon(2)).thenReturn(mMockDrawable2);
- when(mMockIconInjector.getIcon(3)).thenReturn(mMockDrawable3);
- when(mMockIconInjector.getIcon(4)).thenReturn(mMockDrawable4);
+ when(mMockIconInjector.getIcon(false /* showX */, 0)).thenReturn(mMockDrawable0);
+ when(mMockIconInjector.getIcon(false /* showX */, 1)).thenReturn(mMockDrawable1);
+ when(mMockIconInjector.getIcon(false /* showX */, 2)).thenReturn(mMockDrawable2);
+ when(mMockIconInjector.getIcon(false /* showX */, 3)).thenReturn(mMockDrawable3);
+ when(mMockIconInjector.getIcon(false /* showX */, 4)).thenReturn(mMockDrawable4);
+
+ when(mMockIconInjector.getIcon(true /* showX */, 0))
+ .thenReturn(mMockShowXDrawable0);
+ when(mMockIconInjector.getIcon(true /* showX */, 1))
+ .thenReturn(mMockShowXDrawable1);
+ when(mMockIconInjector.getIcon(true /* showX */, 2))
+ .thenReturn(mMockShowXDrawable2);
+ when(mMockIconInjector.getIcon(true /* showX */, 3))
+ .thenReturn(mMockShowXDrawable3);
+ when(mMockIconInjector.getIcon(true /* showX */, 4))
+ .thenReturn(mMockShowXDrawable4);
}
@Test
@@ -155,6 +179,70 @@ public class WifiEntryPreferenceTest {
}
@Test
+ public void levelChanged_notDefaultWifiRefresh_shouldUpdateLevelIcon() {
+ final List<Drawable> iconList = new ArrayList<>();
+ final ConnectedInfo mockConnectedInfo = mock(ConnectedInfo.class);
+ mockConnectedInfo.isDefaultNetwork = false;
+ when(mMockWifiEntry.getConnectedInfo()).thenReturn(mockConnectedInfo);
+ final WifiEntryPreference pref =
+ new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+ when(mMockWifiEntry.getLevel()).thenReturn(0);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(2);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(3);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(4);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(-1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+
+ assertThat(iconList).containsExactly(mMockShowXDrawable0, mMockShowXDrawable1,
+ mMockShowXDrawable2, mMockShowXDrawable3, mMockShowXDrawable4, null);
+ }
+
+ @Test
+ public void levelChanged_notValidatedWifiRefresh_shouldUpdateLevelIcon() {
+ final List<Drawable> iconList = new ArrayList<>();
+ final ConnectedInfo mockConnectedInfo = mock(ConnectedInfo.class);
+ mockConnectedInfo.isValidated = false;
+ when(mMockWifiEntry.getConnectedInfo()).thenReturn(mockConnectedInfo);
+ final WifiEntryPreference pref =
+ new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+ when(mMockWifiEntry.getLevel()).thenReturn(0);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(2);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(3);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(4);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(-1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+
+ assertThat(iconList).containsExactly(mMockShowXDrawable0, mMockShowXDrawable1,
+ mMockShowXDrawable2, mMockShowXDrawable3, mMockShowXDrawable4, null);
+ }
+
+ @Test
public void notNull_whenGetHelpUriString_shouldSetImageButtonVisible() {
when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
final WifiEntryPreference pref =
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 807fbed7d8fd..9c92b464dfbb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2576,7 +2576,7 @@ public class SettingsProvider extends ContentProvider {
public void syncSsaidTableOnStart() {
synchronized (mLock) {
// Verify that each user's packages and ssaid's are in sync.
- for (UserInfo user : mUserManager.getUsers(true)) {
+ for (UserInfo user : mUserManager.getAliveUsers()) {
// Get all uids for the user's packages.
final List<PackageInfo> packages;
try {
@@ -3007,7 +3007,7 @@ public class SettingsProvider extends ContentProvider {
final long identity = Binder.clearCallingIdentity();
try {
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
@@ -3244,7 +3244,7 @@ public class SettingsProvider extends ContentProvider {
// is a singleton generation entry for the global settings which
// is already incremented be the caller.
final Uri uri = getNotificationUriFor(key, name);
- final List<UserInfo> users = mUserManager.getUsers(/*excludeDying*/ true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
for (int i = 0; i < users.size(); i++) {
final int userId = users.get(i).id;
if (mUserManager.isUserRunning(UserHandle.of(userId))) {
@@ -3255,7 +3255,7 @@ public class SettingsProvider extends ContentProvider {
}
private void notifyLocationChangeForRunningUsers() {
- final List<UserInfo> users = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
for (int i = 0; i < users.size(); i++) {
final int userId = users.get(i).id;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b0483339d14e..05172279c4ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -796,16 +796,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
securityMode != SecurityMode.None && newView.needsInput());
}
- private KeyguardSecurityViewFlipper getFlipper() {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof KeyguardSecurityViewFlipper) {
- return (KeyguardSecurityViewFlipper) child;
- }
- }
- return null;
- }
-
private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
public void userActivity() {
if (mSecurityCallback != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index 6a90d00c1e75..9766ee128f7c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -21,9 +21,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -180,22 +178,18 @@ public interface KeyguardViewController {
/**
* Registers the StatusBar to which this Keyguard View is mounted.
- *
* @param statusBar
* @param container
* @param notificationPanelViewController
* @param biometricUnlockController
- * @param dismissCallbackRegistry
* @param lockIconContainer
* @param notificationContainer
* @param bypassController
- * @param falsingManager
*/
void registerStatusBar(StatusBar statusBar,
ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager);
+ KeyguardBypassController bypassController);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
new file mode 100644
index 000000000000..e65f19db5ac2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface ContainerView {
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
new file mode 100644
index 000000000000..84deaca096aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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.keyguard.dagger;
+
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for the {@link KeyguardBouncer}.
+ */
+@Subcomponent
+@KeyguardBouncerScope
+public interface KeyguardBouncerComponent {
+ /** Simple factory for {@link KeyguardBouncerComponent}. */
+ @Subcomponent.Factory
+ interface Factory {
+ KeyguardBouncerComponent build(
+ @BindsInstance @ContainerView ViewGroup container,
+ @BindsInstance KeyguardBouncer.BouncerExpansionCallback bouncerExpansionCallback);
+ }
+
+ /** */
+ KeyguardBouncer createKeyguardBouncer();
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
new file mode 100644
index 000000000000..207ac2852f2f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerScope.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.keyguard.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the StatusBarComponent.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface KeyguardBouncerScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 27809b50d746..ed78c94d45f9 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -77,6 +77,7 @@ import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.NotificationFilter;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
@@ -88,7 +89,6 @@ import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -276,7 +276,7 @@ public class Dependency {
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
@Inject Lazy<NotificationGroupAlertTransferHelper> mNotificationGroupAlertTransferHelper;
- @Inject Lazy<NotificationGroupManager> mNotificationGroupManager;
+ @Inject Lazy<NotificationGroupManagerLegacy> mNotificationGroupManager;
@Inject Lazy<VisualStabilityManager> mVisualStabilityManager;
@Inject Lazy<NotificationGutsManager> mNotificationGutsManager;
@Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
@@ -468,7 +468,7 @@ public class Dependency {
mProviders.put(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager::get);
mProviders.put(VisualStabilityManager.class, mVisualStabilityManager::get);
- mProviders.put(NotificationGroupManager.class, mNotificationGroupManager::get);
+ mProviders.put(NotificationGroupManagerLegacy.class, mNotificationGroupManager::get);
mProviders.put(NotificationGroupAlertTransferHelper.class,
mNotificationGroupAlertTransferHelper::get);
mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index f5c364947a2f..f15949977754 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -19,25 +19,16 @@ package com.android.systemui;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
-import android.os.Looper;
import android.util.Log;
-import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.dagger.DaggerGlobalRootComponent;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.WMComponent;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
-import com.android.systemui.statusbar.phone.KeyguardBouncer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
/**
@@ -83,11 +74,16 @@ public class SystemUIFactory {
public SystemUIFactory() {}
- private void init(Context context) {
+ private void init(Context context) throws ExecutionException, InterruptedException {
mRootComponent = buildGlobalRootComponent(context);
+ // Stand up WMComponent
mWMComponent = mRootComponent.getWMComponentBuilder().build();
- // TODO: use WMComponent to pass APIs into the SysUIComponent.
- mSysUIComponent = mRootComponent.getSysUIComponent().build();
+
+ // And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
+ // TODO: StubAPIClass is just a placeholder.
+ mSysUIComponent = mRootComponent.getSysUIComponent()
+ .setStubAPIClass(mWMComponent.createStubAPIClass())
+ .build();
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
@@ -101,10 +97,15 @@ public class SystemUIFactory {
.build();
}
+
public GlobalRootComponent getRootComponent() {
return mRootComponent;
}
+ public WMComponent getWMComponent() {
+ return mWMComponent;
+ }
+
public SysUIComponent getSysUIComponent() {
return mSysUIComponent;
}
@@ -129,17 +130,4 @@ public class SystemUIFactory {
Handler uiHandler) {
return new ScreenshotNotificationSmartActionsProvider();
}
-
- public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, ViewGroup container,
- DismissCallbackRegistry dismissCallbackRegistry,
- KeyguardBouncer.BouncerExpansionCallback expansionCallback,
- KeyguardStateController keyguardStateController, FalsingManager falsingManager,
- KeyguardBypassController bypassController) {
- return new KeyguardBouncer(context, callback, lockPatternUtils, container,
- dismissCallbackRegistry, falsingManager,
- expansionCallback, keyguardStateController,
- Dependency.get(KeyguardUpdateMonitor.class), bypassController,
- new Handler(Looper.getMainLooper()));
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/dagger/AppOpsModule.java b/packages/SystemUI/src/com/android/systemui/appops/dagger/AppOpsModule.java
new file mode 100644
index 000000000000..d4cc3f37b8dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/appops/dagger/AppOpsModule.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.appops.dagger;
+
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.appops.AppOpsControllerImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+/** Dagger Module for code in the appops package. */
+@Module
+public interface AppOpsModule {
+ /** */
+ @Binds
+ AppOpsController provideAppOpsController(AppOpsControllerImpl controllerImpl);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 9e9d85a7cd1c..c81b7cefbbd7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -104,11 +104,11 @@ import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -164,7 +164,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private final BubbleTaskStackListener mTaskStackListener;
private BubbleExpandListener mExpandListener;
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
- private final NotificationGroupManager mNotificationGroupManager;
+ private final NotificationGroupManagerLegacy mNotificationGroupManager;
private final ShadeController mShadeController;
private final FloatingContentCoordinator mFloatingContentCoordinator;
private final BubbleDataRepository mDataRepository;
@@ -355,7 +355,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
@@ -588,11 +588,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
});
- mNotificationGroupManager.addOnGroupChangeListener(
- new NotificationGroupManager.OnGroupChangeListener() {
+ mNotificationGroupManager.registerGroupChangeListener(
+ new NotificationGroupManagerLegacy.OnGroupChangeListener() {
@Override
public void onGroupSuppressionChanged(
- NotificationGroupManager.NotificationGroup group,
+ NotificationGroupManagerLegacy.NotificationGroup group,
boolean suppressed) {
// More notifications could be added causing summary to no longer
// be suppressed -- in this case need to remove the key.
@@ -650,8 +650,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// 3. User removes all bubbles
// 4. We expect all the removed bubbles AND the summary (note: the summary was
// never added to the suppressedSummary list in BubbleData, so we add this check)
- NotificationEntry summary =
- mNotificationGroupManager.getLogicalGroupSummary(entry.getSbn());
+ NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(entry);
if (summary != null) {
ArrayList<NotificationEntry> summaryChildren =
mNotificationGroupManager.getLogicalChildren(summary.getSbn());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
index eecc41c697b3..9efc3c20f55a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
@@ -34,8 +34,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -62,7 +62,7 @@ public interface BubbleModule {
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
deleted file mode 100644
index e2a6d6c51d4d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dagger;
-
-import com.android.systemui.ActivityStarterDelegate;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.appops.AppOpsControllerImpl;
-import com.android.systemui.classifier.FalsingManagerProxy;
-import com.android.systemui.controls.dagger.ControlsModule;
-import com.android.systemui.globalactions.GlobalActionsComponent;
-import com.android.systemui.globalactions.GlobalActionsImpl;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.GlobalActions;
-import com.android.systemui.plugins.VolumeDialogController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.PowerNotificationWarnings;
-import com.android.systemui.power.PowerUI;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QSTileHost;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
-import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.CastControllerImpl;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationControllerImpl;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.SecurityControllerImpl;
-import com.android.systemui.statusbar.policy.SensorPrivacyController;
-import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerServiceImpl;
-import com.android.systemui.util.RingerModeTracker;
-import com.android.systemui.util.RingerModeTrackerImpl;
-import com.android.systemui.volume.VolumeComponent;
-import com.android.systemui.volume.VolumeDialogComponent;
-import com.android.systemui.volume.VolumeDialogControllerImpl;
-
-import dagger.Binds;
-import dagger.Module;
-
-/**
- * Maps interfaces to implementations for use with Dagger.
- */
-@Module(includes = {ControlsModule.class})
-public abstract class DependencyBinder {
-
- /**
- */
- @Binds
- public abstract ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate);
-
- /**
- */
- @Binds
- public abstract BluetoothController provideBluetoothController(
- BluetoothControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract GlobalActions.GlobalActionsManager provideGlobalActionsManager(
- GlobalActionsComponent controllerImpl);
-
- /**
- */
- @Binds
- public abstract LocationController provideLocationController(
- LocationControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract RotationLockController provideRotationLockController(
- RotationLockControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract NetworkController provideNetworkController(
- NetworkControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract ZenModeController provideZenModeController(
- ZenModeControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract HotspotController provideHotspotController(
- HotspotControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract AppOpsController provideAppOpsController(
- AppOpsControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract NotificationRemoteInputManager.Callback provideNotificationRemoteInputManager(
- StatusBarRemoteInputCallback callbackImpl);
-
- /**
- */
- @Binds
- public abstract CastController provideCastController(CastControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract FlashlightController provideFlashlightController(
- FlashlightControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract KeyguardStateController provideKeyguardMonitor(
- KeyguardStateControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract UserInfoController provideUserInfoContrller(
- UserInfoControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract ManagedProfileController provideManagedProfileController(
- ManagedProfileControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract NextAlarmController provideNextAlarmController(
- NextAlarmControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract SecurityController provideSecurityController(
- SecurityControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract TunerService provideTunerService(TunerServiceImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract DarkIconDispatcher provideDarkIconDispatcher(
- DarkIconDispatcherImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract StatusBarStateController provideStatusBarStateController(
- StatusBarStateControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract SysuiStatusBarStateController providesSysuiStatusBarStateController(
- StatusBarStateControllerImpl statusBarStateControllerImpl);
-
- /**
- */
- @Binds
- public abstract StatusBarIconController provideStatusBarIconController(
- StatusBarIconControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract ExtensionController provideExtensionController(
- ExtensionControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract VolumeDialogController provideVolumeDialogController(
- VolumeDialogControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract PowerUI.WarningsUI provideWarningsUi(PowerNotificationWarnings controllerImpl);
-
- /**
- */
- @Binds
- public abstract SensorPrivacyController provideSensorPrivacyControllerImpl(
- SensorPrivacyControllerImpl controllerImpl);
-
- /**
- */
- @Binds
- public abstract QSHost provideQsHost(QSTileHost controllerImpl);
-
- /**
- */
- @Binds
- public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
-
- /**
- */
- @Binds
- public abstract VolumeComponent provideVolumeComponent(
- VolumeDialogComponent volumeDialogComponent);
-
- /**
- */
- @Binds
- public abstract RingerModeTracker provideRingerModeTracker(
- RingerModeTrackerImpl ringerModeTrackerImpl);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
index fd4a4093110f..c5dc8cccfdf4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
@@ -16,6 +16,8 @@
package com.android.systemui.dagger;
+import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
+
import dagger.Module;
/**
@@ -33,6 +35,8 @@ import dagger.Module;
*
* Please use discretion when adding things to the global scope.
*/
-@Module(includes = {FrameworkServicesModule.class})
+@Module(includes = {
+ FrameworkServicesModule.class,
+ GlobalConcurrencyModule.class})
public class GlobalModule {
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index 36fd3373290d..00fdf55b28e0 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -18,6 +18,8 @@ package com.android.systemui.dagger;
import android.content.Context;
+import com.android.systemui.util.concurrency.ThreadFactory;
+
import javax.inject.Singleton;
import dagger.BindsInstance;
@@ -53,4 +55,9 @@ public interface GlobalRootComponent {
* Builder for a SysuiComponent.
*/
SysUIComponent.Builder getSysUIComponent();
+
+ /**
+ * Build a {@link ThreadFactory}.
+ */
+ ThreadFactory createThreadFactory();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
new file mode 100644
index 000000000000..406981d0c4ad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 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.dagger;
+
+import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.classifier.FalsingManagerProxy;
+import com.android.systemui.globalactions.GlobalActionsComponent;
+import com.android.systemui.globalactions.GlobalActionsImpl;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.GlobalActions;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.volume.VolumeDialogControllerImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+/**
+ * Module for binding Plugin implementations.
+ *
+ * TODO(b/166258224): Many of these should be moved closer to their implementations.
+ */
+@Module
+public interface PluginModule {
+
+ /** */
+ @Binds
+ ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate);
+
+ /** */
+ @Binds
+ DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
+
+ /** */
+ @Binds
+ FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+
+ /** */
+ @Binds
+ GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
+
+ /** */
+ @Binds
+ GlobalActions.GlobalActionsManager provideGlobalActionsManager(
+ GlobalActionsComponent controllerImpl);
+
+ /** */
+ @Binds
+ StatusBarStateController provideStatusBarStateController(
+ StatusBarStateControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ VolumeDialogController provideVolumeDialogController(VolumeDialogControllerImpl controllerImpl);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index e4e3d7aacdf0..2622593880ba 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -26,6 +26,7 @@ import com.android.systemui.pip.phone.dagger.PipModule;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
+import dagger.BindsInstance;
import dagger.Subcomponent;
/**
@@ -35,7 +36,6 @@ import dagger.Subcomponent;
@Subcomponent(modules = {
DefaultComponentBinder.class,
DependencyProvider.class,
- DependencyBinder.class,
PipModule.class,
SystemUIBinder.class,
SystemUIModule.class,
@@ -47,6 +47,9 @@ public interface SysUIComponent {
*/
@Subcomponent.Builder
interface Builder {
+ @BindsInstance
+ Builder setStubAPIClass(WMComponent.StubAPIClass stubAPIClass);
+
SysUIComponent build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index a021114c138b..2c0b04fed810 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -46,11 +46,11 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
@@ -143,7 +143,7 @@ public abstract class SystemUIDefaultModule {
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index e985e3d7ef90..8f4e738e5a5f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -16,14 +16,18 @@
package com.android.systemui.dagger;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCacheImpl;
+import com.android.systemui.appops.dagger.AppOpsModule;
import com.android.systemui.assist.AssistModule;
+import com.android.systemui.controls.dagger.ControlsModule;
import com.android.systemui.demomode.dagger.DemoModeModule;
import com.android.systemui.doze.dagger.DozeComponent;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.power.dagger.PowerModule;
import com.android.systemui.recents.Recents;
import com.android.systemui.screenshot.dagger.ScreenshotModule;
import com.android.systemui.settings.dagger.SettingsModule;
@@ -37,11 +41,15 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.util.concurrency.ConcurrencyModule;
+import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule;
+import com.android.systemui.tuner.dagger.TunerModule;
+import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
+import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
import com.android.systemui.util.time.SystemClockImpl;
+import com.android.systemui.volume.dagger.VolumeModule;
import dagger.Binds;
import dagger.BindsOptionalOf;
@@ -53,20 +61,29 @@ import dagger.Provides;
* implementation.
*/
@Module(includes = {
+ AppOpsModule.class,
AssistModule.class,
- ConcurrencyModule.class,
+ ControlsModule.class,
DemoModeModule.class,
LogModule.class,
PeopleHubModule.class,
+ PowerModule.class,
+ PluginModule.class,
ScreenshotModule.class,
SensorModule.class,
SettingsModule.class,
- SettingsUtilModule.class
+ SettingsUtilModule.class,
+ StatusBarPolicyModule.class,
+ SysUIConcurrencyModule.class,
+ TunerModule.class,
+ UtilModule.class,
+ VolumeModule.class
},
subcomponents = {StatusBarComponent.class,
NotificationRowComponent.class,
DozeComponent.class,
ExpandableNotificationRowComponent.class,
+ KeyguardBouncerComponent.class,
NotificationShelfComponent.class,
FragmentService.FragmentCreator.class})
public abstract class SystemUIModule {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index 929b61a3421c..ad90eff3c969 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -16,6 +16,8 @@
package com.android.systemui.dagger;
+import javax.inject.Inject;
+
import dagger.Subcomponent;
/**
@@ -32,4 +34,19 @@ public interface WMComponent {
interface Builder {
WMComponent build();
}
+
+
+ /**
+ * Example class used for passing an API to SysUI from WMShell.
+ *
+ * TODO: Remove this once real WM classes are ready to go.
+ **/
+ @WMSingleton
+ class StubAPIClass {
+ @Inject
+ StubAPIClass() {}
+ }
+
+ /** Create a StubAPIClass. */
+ StubAPIClass createStubAPIClass();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 342818de3d1e..d9f971731f29 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -30,6 +30,8 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.view.Display;
+import androidx.annotation.Nullable;
+
import com.android.systemui.doze.dagger.BrightnessSensor;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
@@ -75,7 +77,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
@Inject
public DozeScreenBrightness(Context context, @WrappedService DozeMachine.Service service,
- AsyncSensorManager sensorManager, @BrightnessSensor Sensor lightSensor,
+ AsyncSensorManager sensorManager, @Nullable @BrightnessSensor Sensor lightSensor,
DozeHost host, Handler handler, AlwaysOnDisplayPolicy alwaysOnDisplayPolicy) {
mContext = context;
mDozeService = service;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
index 04f7c368fdc4..b89946028aeb 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java
@@ -20,6 +20,8 @@ import android.content.Context;
import android.hardware.Sensor;
import android.os.Handler;
+import androidx.annotation.Nullable;
+
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeAuthRemover;
@@ -91,6 +93,7 @@ public abstract class DozeModule {
@Provides
@BrightnessSensor
+ @Nullable
static Sensor providesBrightnessSensor(AsyncSensorManager sensorManager, Context context) {
return DozeSensors.findSensorWithType(sensorManager,
context.getString(R.string.doze_brightness_sensor_type));
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 33407918f938..2705f07069bf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2184,8 +2184,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
View notificationContainer, KeyguardBypassController bypassController) {
mKeyguardViewControllerLazy.get().registerStatusBar(statusBar, container, panelView,
- biometricUnlockController, mDismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController, mFalsingManager);
+ biometricUnlockController, lockIconContainer,
+ notificationContainer, bypassController);
return mKeyguardViewControllerLazy.get();
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index a003d8365810..e5a9ac10389f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -172,7 +172,6 @@ class MediaCarouselController @Inject constructor(
// This view is inactive, let's remove this! This happens e.g when dismissing /
// timing out a view. We still have the data around because resumption could
// be on, but we should save the resources and release this.
- oldKey?.let { MediaPlayerData.removeMediaPlayer(it) }
onMediaDataRemoved(key)
} else {
addOrUpdatePlayer(key, oldKey, data)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index aec3543de4eb..c7e78174f474 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -662,7 +662,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
mOrientationParams.setTitle("SecondaryHomeHandle" + mContext.getDisplayId());
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
index 0354c727c92c..8ef9b092bc00 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -158,7 +158,9 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Du
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
mDisplaySize.x, mTutorialAreaHeight, 0, 0,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.TOP | Gravity.LEFT;
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
new file mode 100644
index 000000000000..8b8941a9112d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.power.dagger;
+
+import com.android.systemui.power.PowerNotificationWarnings;
+import com.android.systemui.power.PowerUI;
+
+import dagger.Binds;
+import dagger.Module;
+
+
+/** Dagger Module for code in the power package. */
+@Module
+public interface PowerModule {
+ /** */
+ @Binds
+ PowerUI.WarningsUI provideWarningsUi(PowerNotificationWarnings controllerImpl);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 8740581240b5..8ff96c8a4a37 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -22,6 +22,7 @@ import android.os.Handler;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.qs.AutoAddTracker;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.ManagedProfileController;
@@ -29,6 +30,7 @@ import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -56,4 +58,9 @@ public interface QSModule {
manager.init();
return manager;
}
+
+
+ /** */
+ @Binds
+ QSHost provideQsHost(QSTileHost controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e24fbc6cca9d..7dd4edd233bd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -573,7 +573,12 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
- dismissScreenshot("new screenshot requested", true);
+ if (mScreenshotLayout.isAttachedToWindow()) {
+ if (!mDismissAnimation.isRunning()) { // if we didn't already dismiss for another reason
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
+ }
+ dismissScreenshot("new screenshot requested", true);
+ }
mScreenBitmap = screenshot;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 6b42f2e07bc3..74e0229c4992 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -59,7 +59,9 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "screenshot interaction timed out")
SCREENSHOT_INTERACTION_TIMEOUT(310),
@UiEvent(doc = "screenshot explicitly dismissed")
- SCREENSHOT_EXPLICIT_DISMISSAL(311);
+ SCREENSHOT_EXPLICIT_DISMISSAL(311),
+ @UiEvent(doc = "screenshot reentered for new screenshot")
+ SCREENSHOT_REENTERED(640);
private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 852c05547e32..38c7e5c50f63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -36,12 +36,12 @@ import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.Assert;
import java.util.ArrayList;
@@ -72,7 +72,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
// Dependencies:
private final DynamicChildBindController mDynamicChildBindController;
protected final NotificationLockscreenUserManager mLockscreenUserManager;
- protected final NotificationGroupManager mGroupManager;
+ protected final NotificationGroupManagerLegacy mGroupManager;
protected final VisualStabilityManager mVisualStabilityManager;
private final SysuiStatusBarStateController mStatusBarStateController;
private final NotificationEntryManager mEntryManager;
@@ -107,7 +107,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
Context context,
@Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
NotificationEntryManager notificationEntryManager,
@@ -187,13 +187,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
ent.setSensitive(sensitive, deviceSensitive);
ent.getRow().setNeedsRedaction(needsRedaction);
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
- boolean isChildInGroup = mGroupManager.isChildInGroupWithSummary(ent.getSbn());
+ boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
boolean groupChangesAllowed =
mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs
|| !ent.hasFinishedInitialization(); // notif recently added
- NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
+ NotificationEntry parent = mGroupManager.getGroupSummary(ent);
if (!groupChangesAllowed) {
// We don't to change groups while the user is looking at them
boolean wasChildInGroup = ent.isChildInGroup();
@@ -431,8 +431,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
while(!stack.isEmpty()) {
ExpandableNotificationRow row = stack.pop();
NotificationEntry entry = row.getEntry();
- boolean isChildNotification =
- mGroupManager.isChildInGroupWithSummary(entry.getSbn());
+ boolean isChildNotification = mGroupManager.isChildInGroup(entry);
if (!onKeyguard) {
// If mAlwaysExpandNonGroupedNotification is false, then only expand the
@@ -448,9 +447,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
if (!showOnKeyguard) {
// min priority notifications should show if their summary is showing
- if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) {
- NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
- entry.getSbn());
+ if (mGroupManager.isChildInGroup(entry)) {
+ NotificationEntry summary = mGroupManager.getLogicalGroupSummary(entry);
if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
showOnKeyguard = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index 44550b72e521..d15b8476b3c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -37,21 +37,29 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import dagger.Binds;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -136,6 +144,12 @@ public interface StatusBarDependenciesModule {
return new SmartReplyController(entryManager, statusBarService, clickNotifier);
}
+
+ /** */
+ @Binds
+ NotificationRemoteInputManager.Callback provideNotificationRemoteInputManagerCallback(
+ StatusBarRemoteInputCallback callbackImpl);
+
/** */
@SysUISingleton
@Provides
@@ -143,7 +157,7 @@ public interface StatusBarDependenciesModule {
Context context,
@Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
NotificationEntryManager notificationEntryManager,
@@ -179,4 +193,22 @@ public interface StatusBarDependenciesModule {
static CommandQueue provideCommandQueue(Context context, ProtoTracer protoTracer) {
return new CommandQueue(context, protoTracer);
}
+
+ /**
+ */
+ @Binds
+ ManagedProfileController provideManagedProfileController(
+ ManagedProfileControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ SysuiStatusBarStateController providesSysuiStatusBarStateController(
+ StatusBarStateControllerImpl statusBarStateControllerImpl);
+
+ /**
+ */
+ @Binds
+ StatusBarIconController provideStatusBarIconController(
+ StatusBarIconControllerImpl controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index c68625c9d9ee..433c8b0d361d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -30,7 +30,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationContentView
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@@ -64,7 +64,7 @@ class ConversationNotificationProcessor @Inject constructor(
@SysUISingleton
class ConversationNotificationManager @Inject constructor(
private val notificationEntryManager: NotificationEntryManager,
- private val notificationGroupManager: NotificationGroupManager,
+ private val notificationGroupManager: NotificationGroupManagerLegacy,
private val context: Context,
@Main private val mainHandler: Handler
) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index b5f1c7ff9b62..e1e77b0723a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -48,13 +48,13 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.leak.LeakDetector;
@@ -139,7 +139,7 @@ public class NotificationEntryManager implements
private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
private final KeyguardEnvironment mKeyguardEnvironment;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupManager;
private final NotificationRankingManager mRankingManager;
private final FeatureFlags mFeatureFlags;
private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
@@ -199,7 +199,7 @@ public class NotificationEntryManager implements
*/
public NotificationEntryManager(
NotificationEntryManagerLogger logger,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationRankingManager rankingManager,
KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 590ccf830a78..73c7fd1b64a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -34,7 +34,6 @@ import com.android.systemui.media.MediaFeatureFlag;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import javax.inject.Inject;
@@ -46,8 +45,6 @@ import javax.inject.Inject;
@SysUISingleton
public class NotificationFilter {
- private final NotificationGroupManager mGroupManager = Dependency.get(
- NotificationGroupManager.class);
private final StatusBarStateController mStatusBarStateController;
private final Boolean mIsMediaFlagEnabled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8ce9d944b865..789e78e33671 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -60,6 +60,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
@@ -69,7 +70,6 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.stack.PriorityBucket;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import java.util.ArrayList;
import java.util.List;
@@ -430,7 +430,7 @@ public final class NotificationEntry extends ListEntry {
* Get the children that are actually attached to this notification's row.
*
* TODO: Seems like most callers here should probably be using
- * {@link NotificationGroupManager#getChildren}
+ * {@link NotificationGroupManagerLegacy#getChildren}
*/
public @Nullable List<NotificationEntry> getAttachedNotifChildren() {
if (row == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index bab2686c5c9c..fb42c424f603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -33,7 +33,7 @@ import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVI
import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
import com.android.systemui.statusbar.notification.stack.PriorityBucket
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.policy.HeadsUpManager
import dagger.Lazy
import java.util.Objects
@@ -52,7 +52,7 @@ private const val TAG = "NotifRankingManager"
*/
open class NotificationRankingManager @Inject constructor(
private val mediaManagerLazy: Lazy<NotificationMediaManager>,
- private val groupManager: NotificationGroupManager,
+ private val groupManager: NotificationGroupManagerLegacy,
private val headsUpManager: HeadsUpManager,
private val notifFilter: NotificationFilter,
private val logger: NotificationEntryManagerLogger,
@@ -191,7 +191,7 @@ open class NotificationRankingManager @Inject constructor(
private fun NotificationEntry.isConversation() = getPeopleNotificationType() != TYPE_NON_PERSON
private fun NotificationEntry.getPeopleNotificationType() =
- peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ peopleNotificationIdentifier.getPeopleNotificationType(this)
private fun NotificationEntry.isHighPriority() =
highPriorityProvider.isHighPriority(this)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index dea11626a3f8..3aaa9acdb897 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -53,8 +53,7 @@ class ConversationCoordinator @Inject constructor(
}
private fun isConversation(entry: NotificationEntry): Boolean =
- peopleNotificationIdentifier.getPeopleNotificationType(entry.sbn, entry.ranking) !=
- TYPE_NON_PERSON
+ peopleNotificationIdentifier.getPeopleNotificationType(entry) != TYPE_NON_PERSON
companion object {
private const val TAG = "ConversationCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
index 6089aa26fe71..aec26474cf7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java
@@ -20,10 +20,10 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import javax.inject.Inject;
@@ -34,13 +34,13 @@ import javax.inject.Inject;
@SysUISingleton
public class LowPriorityInflationHelper {
private final FeatureFlags mFeatureFlags;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupManager;
private final RowContentBindStage mRowContentBindStage;
@Inject
LowPriorityInflationHelper(
FeatureFlags featureFlags,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
RowContentBindStage rowContentBindStage) {
mFeatureFlags = featureFlags;
mGroupManager = groupManager;
@@ -78,7 +78,7 @@ public class LowPriorityInflationHelper {
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
isGroupChild = (entry.getParent() != GroupEntry.ROOT_ENTRY);
} else {
- isGroupChild = mGroupManager.isChildInGroupWithSummary(entry.getSbn());
+ isGroupChild = mGroupManager.isChildInGroup(entry);
}
return entry.isAmbient() && !isGroupChild;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index c44c59c02810..21d54c85160b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -11,10 +11,10 @@
* 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
+ * limitations under the License.
*/
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.notification.collection.legacy;
import android.annotation.Nullable;
import android.service.notification.StatusBarNotification;
@@ -22,14 +22,17 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -37,6 +40,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -46,13 +50,19 @@ import dagger.Lazy;
/**
* A class to handle notifications and their corresponding groups.
+ * This includes:
+ * 1. Determining whether an entry is a member of a group and whether it is a summary or a child
+ * 2. Tracking group expansion states
*/
@SysUISingleton
-public class NotificationGroupManager implements OnHeadsUpChangedListener, StateListener {
+public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener,
+ GroupMembershipManager, GroupExpansionManager, Dumpable {
private static final String TAG = "NotificationGroupManager";
private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
- private final ArraySet<OnGroupChangeListener> mListeners = new ArraySet<>();
+ private final ArraySet<OnGroupExpansionChangeListener> mExpansionChangeListeners =
+ new ArraySet<>();
+ private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
private int mBarState = -1;
private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
@@ -61,7 +71,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
@Nullable private BubbleController mBubbleController = null;
@Inject
- public NotificationGroupManager(
+ public NotificationGroupManagerLegacy(
StatusBarStateController statusBarStateController,
Lazy<PeopleNotificationIdentifier> peopleNotificationIdentifier) {
statusBarStateController.addCallback(this);
@@ -77,15 +87,19 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
/**
* Add a listener for changes to groups.
- *
- * @param listener listener to add
*/
- public void addOnGroupChangeListener(OnGroupChangeListener listener) {
- mListeners.add(listener);
+ public void registerGroupChangeListener(OnGroupChangeListener listener) {
+ mGroupChangeListeners.add(listener);
}
- public boolean isGroupExpanded(StatusBarNotification sbn) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) {
+ mExpansionChangeListeners.add(listener);
+ }
+
+ @Override
+ public boolean isGroupExpanded(NotificationEntry entry) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return false;
}
@@ -103,8 +117,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return group.expanded;
}
- public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public void setGroupExpanded(NotificationEntry entry, boolean expanded) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return;
}
@@ -114,12 +129,15 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
private void setGroupExpanded(NotificationGroup group, boolean expanded) {
group.expanded = expanded;
if (group.summary != null) {
- for (OnGroupChangeListener listener : mListeners) {
- listener.onGroupExpansionChanged(group.summary.getRow(), expanded);
+ for (OnGroupExpansionChangeListener listener : mExpansionChangeListeners) {
+ listener.onGroupExpansionChange(group.summary.getRow(), expanded);
}
}
}
+ /**
+ * When we want to remove an entry from being tracked for grouping
+ */
public void onEntryRemoved(NotificationEntry removed) {
onEntryRemovedInternal(removed, removed.getSbn());
mIsolatedEntries.remove(removed.getKey());
@@ -158,7 +176,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
if (group.children.isEmpty()) {
if (group.summary == null) {
mGroupMap.remove(groupKey);
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupRemoved(group, groupKey);
}
}
@@ -184,7 +202,8 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
if (group == null) {
group = new NotificationGroup();
mGroupMap.put(groupKey, group);
- for (OnGroupChangeListener listener : mListeners) {
+
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupCreated(group, groupKey);
}
}
@@ -195,9 +214,8 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
+ "existing removed: " + existing.isRowRemoved()
+ (existingThrowable != null
- ? Log.getStackTraceString(existingThrowable) + "\n": "")
- + " added removed" + added.isRowRemoved()
- , new Throwable());
+ ? Log.getStackTraceString(existingThrowable) + "\n" : "")
+ + " added removed" + added.isRowRemoved(), new Throwable());
}
group.children.put(added.getKey(), added);
updateSuppression(group);
@@ -206,12 +224,12 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
group.expanded = added.areChildrenExpanded();
updateSuppression(group);
if (!group.children.isEmpty()) {
- ArrayList<NotificationEntry> childrenCopy
- = new ArrayList<>(group.children.values());
+ ArrayList<NotificationEntry> childrenCopy =
+ new ArrayList<>(group.children.values());
for (NotificationEntry child : childrenCopy) {
onEntryBecomingChild(child);
}
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupCreatedFromChildren(group);
}
}
@@ -243,7 +261,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
&& group.summary.getSbn().getNotification().isGroupSummary()
&& (hasIsolatedChildren(group) || hasBubbles)));
if (prevSuppressed != group.suppressed) {
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
if (!mIsUpdatingUnchangedGroup) {
listener.onGroupSuppressionChanged(group, group.suppressed);
listener.onGroupsChanged();
@@ -306,6 +324,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
}
+ /**
+ * Whether the given notification is the summary of a group that is being suppressed
+ */
public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) {
return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
}
@@ -315,13 +336,14 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
&& getTotalNumberOfChildren(sbn) == 1;
}
- public boolean isOnlyChildInGroup(StatusBarNotification sbn) {
+ @Override
+ public boolean isOnlyChildInGroup(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isOnlyChild(sbn)) {
return false;
}
- NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn);
- return logicalGroupSummary != null
- && !logicalGroupSummary.getSbn().equals(sbn);
+ NotificationEntry logicalGroupSummary = getLogicalGroupSummary(entry);
+ return logicalGroupSummary != null && !logicalGroupSummary.getSbn().equals(sbn);
}
private int getTotalNumberOfChildren(StatusBarNotification sbn) {
@@ -339,11 +361,12 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
private void setStatusBarState(int newState) {
mBarState = newState;
if (mBarState == StatusBarState.KEYGUARD) {
- collapseAllGroups();
+ collapseGroups();
}
}
- public void collapseAllGroups() {
+ @Override
+ public void collapseGroups() {
// Because notifications can become isolated when the group becomes suppressed it can
// lead to concurrent modifications while looping. We need to make a copy.
ArrayList<NotificationGroup> groupCopy = new ArrayList<>(mGroupMap.values());
@@ -357,10 +380,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
}
- /**
- * @return whether a given notification is a child in a group which has a summary
- */
- public boolean isChildInGroupWithSummary(StatusBarNotification sbn) {
+ @Override
+ public boolean isChildInGroup(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isGroupChild(sbn)) {
return false;
}
@@ -377,10 +399,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return true;
}
- /**
- * @return whether a given notification is a summary in a group which has children
- */
- public boolean isSummaryOfGroup(StatusBarNotification sbn) {
+ @Override
+ public boolean isGroupSummary(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
if (!isGroupSummary(sbn)) {
return false;
}
@@ -391,21 +412,14 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn);
}
- /**
- * Get the summary of a specified status bar notification. For isolated notification this return
- * itself.
- */
- public NotificationEntry getGroupSummary(StatusBarNotification sbn) {
- return getGroupSummary(getGroupKey(sbn));
+ @Override
+ public NotificationEntry getGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(getGroupKey(entry.getSbn()));
}
- /**
- * Similar to {@link #getGroupSummary(StatusBarNotification)} but doesn't get the visual summary
- * but the logical summary, i.e when a child is isolated, it still returns the summary as if
- * it wasn't isolated.
- */
- public NotificationEntry getLogicalGroupSummary(StatusBarNotification sbn) {
- return getGroupSummary(sbn.getGroupKey());
+ @Override
+ public NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry.getSbn().getGroupKey());
}
@Nullable
@@ -436,14 +450,10 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return children;
}
- /**
- * Get the children that are in the summary's group, not including those isolated.
- *
- * @param summary summary of a group
- * @return list of the children
- */
- public @Nullable ArrayList<NotificationEntry> getChildren(StatusBarNotification summary) {
- NotificationGroup group = mGroupMap.get(summary.getGroupKey());
+ @Override
+ public @Nullable List<NotificationEntry> getChildren(ListEntry listEntrySummary) {
+ NotificationEntry summary = listEntrySummary.getRepresentativeEntry();
+ NotificationGroup group = mGroupMap.get(summary.getSbn().getGroupKey());
if (group == null) {
return null;
}
@@ -479,9 +489,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
return groupKey;
}
- /** @return group expansion state after toggling. */
- public boolean toggleGroupExpansion(StatusBarNotification sbn) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ @Override
+ public boolean toggleGroupExpansion(NotificationEntry entry) {
+ NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
if (group == null) {
return false;
}
@@ -494,10 +504,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
}
/**
- * Whether a notification is visually a group summary.
- *
- * @param sbn notification to check
- * @return true if it is visually a group summary
+ * Is this notification the summary of a group?
*/
public boolean isGroupSummary(StatusBarNotification sbn) {
if (isIsolated(sbn.getKey())) {
@@ -536,14 +543,13 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* @param entry the notification to check
* @return true if the entry should be isolated
*/
-
private boolean shouldIsolate(NotificationEntry entry) {
StatusBarNotification sbn = entry.getSbn();
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
return false;
}
- int peopleNotificationType = mPeopleNotificationIdentifier.get().getPeopleNotificationType(
- entry.getSbn(), entry.getRanking());
+ int peopleNotificationType =
+ mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry);
if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) {
return true;
}
@@ -576,7 +582,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
// When the notification gets added afterwards it is already isolated and therefore
// it doesn't lead to an update.
updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupsChanged();
}
}
@@ -607,7 +613,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
onEntryRemovedInternal(entry, entry.getSbn());
mIsolatedEntries.remove(sbn.getKey());
onEntryAddedInternal(entry);
- for (OnGroupChangeListener listener : mListeners) {
+ for (OnGroupChangeListener listener : mGroupChangeListeners) {
listener.onGroupsChanged();
}
}
@@ -618,12 +624,16 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
|| notificationGroup.summary.isGroupNotFullyVisible();
}
+ /**
+ * Directly set the heads up manager to avoid circular dependencies
+ */
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
mHeadsUpManager = headsUpManager;
}
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("GroupManager state:");
+ pw.println("GroupManagerLegacy state:");
pw.println(" number of groups: " + mGroupMap.size());
for (Map.Entry<String, NotificationGroup> entry : mGroupMap.entrySet()) {
pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue());
@@ -640,6 +650,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
setStatusBarState(newState);
}
+ /**
+ * Represents a notification group in the notification shade.
+ */
public static class NotificationGroup {
public final HashMap<String, NotificationEntry> children = new HashMap<>();
public NotificationEntry summary;
@@ -659,24 +672,29 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
result += "\n children size: " + children.size();
for (NotificationEntry child : children.values()) {
result += "\n " + child.getSbn()
- + (child.getDebugThrowable() != null
- ? Log.getStackTraceString(child.getDebugThrowable())
- : "");
+ + (child.getDebugThrowable() != null
+ ? Log.getStackTraceString(child.getDebugThrowable())
+ : "");
}
result += "\n summary suppressed: " + suppressed;
return result;
}
}
+ /**
+ * Listener for group changes not including group expansion changes which are handled by
+ * {@link OnGroupExpansionChangeListener}.
+ */
public interface OnGroupChangeListener {
-
/**
* A new group has been created.
*
* @param group the group that was created
* @param groupKey the group's key
*/
- default void onGroupCreated(NotificationGroup group, String groupKey) {}
+ default void onGroupCreated(
+ NotificationGroup group,
+ String groupKey) {}
/**
* A group has been removed.
@@ -684,7 +702,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* @param group the group that was removed
* @param groupKey the group's key
*/
- default void onGroupRemoved(NotificationGroup group, String groupKey) {}
+ default void onGroupRemoved(
+ NotificationGroup group,
+ String groupKey) {}
/**
* The suppression of a group has changed.
@@ -692,16 +712,9 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
* @param group the group that has changed
* @param suppressed true if the group is now suppressed, false o/w
*/
- default void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {}
-
- /**
- * The expansion of a group has changed.
- *
- * @param changedRow the row for which the expansion has changed, which is also the summary
- * @param expanded a boolean indicating the new expanded state
- */
- default void onGroupExpansionChanged(ExpandableNotificationRow changedRow,
- boolean expanded) {}
+ default void onGroupSuppressionChanged(
+ NotificationGroup group,
+ boolean suppressed) {}
/**
* A group of children just received a summary notification and should therefore become
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index 8b803b517f14..18806effc545 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -20,11 +20,10 @@ import android.app.Notification;
import android.app.NotificationManager;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import java.util.List;
@@ -39,14 +38,14 @@ import javax.inject.Inject;
@SysUISingleton
public class HighPriorityProvider {
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
@Inject
public HighPriorityProvider(
PeopleNotificationIdentifier peopleNotificationIdentifier,
- NotificationGroupManager groupManager) {
+ GroupMembershipManager groupManager) {
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupManager;
}
/**
@@ -81,20 +80,15 @@ public class HighPriorityProvider {
private boolean hasHighPriorityChild(ListEntry entry) {
- List<NotificationEntry> children = null;
-
- if (entry instanceof GroupEntry) {
- // New notification pipeline
- children = ((GroupEntry) entry).getChildren();
- } else if (entry.getRepresentativeEntry() != null
- && mGroupManager.isGroupSummary(entry.getRepresentativeEntry().getSbn())) {
- // Old notification pipeline
- children = mGroupManager.getChildren(entry.getRepresentativeEntry().getSbn());
+ if (entry instanceof NotificationEntry
+ && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) {
+ return false;
}
+ List<NotificationEntry> children = mGroupMembershipManager.getChildren(entry);
if (children != null) {
for (NotificationEntry child : children) {
- if (isHighPriority(child)) {
+ if (child != entry && isHighPriority(child)) {
return true;
}
}
@@ -122,8 +116,8 @@ public class HighPriorityProvider {
}
private boolean isPeopleNotification(NotificationEntry entry) {
- return mPeopleNotificationIdentifier.getPeopleNotificationType(
- entry.getSbn(), entry.getRanking()) != PeopleNotificationIdentifier.TYPE_NON_PERSON;
+ return mPeopleNotificationIdentifier.getPeopleNotificationType(entry)
+ != PeopleNotificationIdentifier.TYPE_NON_PERSON;
}
private boolean hasUserSetImportance(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java
new file mode 100644
index 000000000000..d2df07ed7864
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 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.statusbar.notification.collection.render;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Tracks expanded notification states for groups. This expanded state should not be confused by the
+ * expanded/collapsed state of a single notification which is tracked within each
+ * ExpandableNotificationRow.
+ */
+public interface GroupExpansionManager extends Dumpable {
+
+ /**
+ * Register a listener for group expansion changes
+ */
+ void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener);
+
+ /**
+ * Whether the group associated with this notification is expanded.
+ * If this notification is not part of a group, it will always return false.
+ */
+ boolean isGroupExpanded(NotificationEntry entry);
+
+ /**
+ * Set whether the group associated with this notification is expanded or not.
+ */
+ void setGroupExpanded(NotificationEntry entry, boolean expanded);
+
+ /** @return group expansion state after toggling. */
+ boolean toggleGroupExpansion(NotificationEntry entry);
+
+ /**
+ * Set expanded=false for all groups
+ */
+ void collapseGroups();
+
+ /**
+ * Listener for group expansion changes.
+ */
+ interface OnGroupExpansionChangeListener {
+ /**
+ * The expansion of a group has changed.
+ *
+ * @param changedRow the row for which the expansion has changed, which is also the summary
+ * @param expanded a boolean indicating the new expanded state
+ */
+ void onGroupExpansionChange(ExpandableNotificationRow changedRow, boolean expanded);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
new file mode 100644
index 000000000000..b9aa26f75c9b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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.statusbar.notification.collection.render;
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.Coordinator;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Provides grouping information for notification entries including information about a group's
+ * expanded state.
+ */
+public class GroupExpansionManagerImpl implements GroupExpansionManager, Coordinator {
+ private final GroupMembershipManager mGroupMembershipManager;
+ private final Set<OnGroupExpansionChangeListener> mOnGroupChangeListeners = new HashSet<>();
+
+ // Set of summary keys whose groups are expanded
+ private final Set<NotificationEntry> mExpandedGroups = new HashSet<>();
+
+ public GroupExpansionManagerImpl(GroupMembershipManager groupMembershipManager) {
+ mGroupMembershipManager = groupMembershipManager;
+ }
+
+ /**
+ * Cleanup entries from mExpandedGroups that no longer exist in the pipeline.
+ */
+ private final OnBeforeRenderListListener mNotifTracker = (entries) -> {
+ final Set<NotificationEntry> renderingSummaries = new HashSet<>();
+ for (ListEntry entry : entries) {
+ if (entry instanceof GroupEntry) {
+ renderingSummaries.add(entry.getRepresentativeEntry());
+ }
+ }
+ mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup));
+ };
+
+ @Override
+ public void attach(NotifPipeline pipeline) {
+ pipeline.addOnBeforeRenderListListener(mNotifTracker);
+ }
+
+ @Override
+ public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) {
+ mOnGroupChangeListeners.add(listener);
+ }
+
+ @Override
+ public boolean isGroupExpanded(NotificationEntry entry) {
+ return mExpandedGroups.contains(mGroupMembershipManager.getGroupSummary(entry));
+ }
+
+ @Override
+ public void setGroupExpanded(NotificationEntry entry, boolean expanded) {
+ final NotificationEntry groupSummary = mGroupMembershipManager.getGroupSummary(entry);
+ if (expanded) {
+ mExpandedGroups.add(groupSummary);
+ } else {
+ mExpandedGroups.remove(groupSummary);
+ }
+
+ sendOnGroupExpandedChange(entry, expanded);
+ }
+
+ @Override
+ public boolean toggleGroupExpansion(NotificationEntry entry) {
+ setGroupExpanded(entry, !isGroupExpanded(entry));
+ return isGroupExpanded(entry);
+ }
+
+ @Override
+ public void collapseGroups() {
+ for (NotificationEntry entry : mExpandedGroups) {
+ setGroupExpanded(entry, false);
+ }
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NotificationEntryExpansion state:");
+ pw.println(" # expanded groups: " + mExpandedGroups.size());
+ for (NotificationEntry entry : mExpandedGroups) {
+ pw.println(" summary key of expanded group: " + entry.getKey());
+ }
+ }
+
+ private void sendOnGroupExpandedChange(NotificationEntry entry, boolean expanded) {
+ for (OnGroupExpansionChangeListener listener : mOnGroupChangeListeners) {
+ listener.onGroupExpansionChange(entry.getRow(), expanded);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
new file mode 100644
index 000000000000..196cb8f26b22
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.statusbar.notification.collection.render;
+
+import android.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.List;
+
+/**
+ * Helper that determines the group states (parent, summary, children) of a notification.
+ */
+public interface GroupMembershipManager {
+ /**
+ * @return whether a given notification is a top level entry or is the summary in a group which
+ * has children
+ */
+ boolean isGroupSummary(NotificationEntry entry);
+
+ /**
+ * Get the summary of a specified status bar notification. For an isolated notification this
+ * returns itself.
+ */
+ NotificationEntry getGroupSummary(NotificationEntry entry);
+
+ /**
+ * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary
+ * but the logical summary, i.e when a child is isolated, it still returns the summary as if
+ * it wasn't isolated.
+ * TODO: remove this when migrating to the new pipeline, this is taken care of in the
+ * dismissal logic built into NotifCollection
+ */
+ default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry);
+ }
+
+ /**
+ * @return whether a given notification is a child in a group
+ */
+ boolean isChildInGroup(NotificationEntry entry);
+
+ /**
+ * Whether this is the only child in a group
+ * TODO: remove this when migrating to the new pipeline, this is taken care of in the
+ * dismissal logic built into NotifCollection
+ */
+ boolean isOnlyChildInGroup(NotificationEntry entry);
+
+ /**
+ * Get the children that are in the summary's group, not including those isolated.
+ *
+ * @param summary summary of a group
+ * @return list of the children
+ */
+ @Nullable
+ List<NotificationEntry> getChildren(ListEntry summary);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
new file mode 100644
index 000000000000..c1f468a3072f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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.statusbar.notification.collection.render;
+
+import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.List;
+
+/**
+ * ShadeListBuilder groups notifications from system server. This manager translates
+ * ShadeListBuilder's method of grouping to be used within SystemUI.
+ */
+public class GroupMembershipManagerImpl implements GroupMembershipManager {
+ @Override
+ public boolean isGroupSummary(NotificationEntry entry) {
+ return getGroupSummary(entry) == entry;
+ }
+
+ @Override
+ public NotificationEntry getGroupSummary(NotificationEntry entry) {
+ if (isEntryTopLevel(entry) || entry.getParent() == null) {
+ return null;
+ }
+
+ return entry.getParent().getRepresentativeEntry();
+ }
+
+ @Override
+ public boolean isChildInGroup(NotificationEntry entry) {
+ return !isEntryTopLevel(entry);
+ }
+
+ @Override
+ public boolean isOnlyChildInGroup(NotificationEntry entry) {
+ if (entry.getParent() == null) {
+ return false;
+ }
+
+ return entry.getParent().getChildren().size() == 1;
+ }
+
+ @Nullable
+ @Override
+ public List<NotificationEntry> getChildren(ListEntry entry) {
+ if (entry instanceof GroupEntry) {
+ return ((GroupEntry) entry).getChildren();
+ }
+
+ if (isGroupSummary(entry.getRepresentativeEntry())) {
+ // maybe we were actually passed the summary
+ return entry.getRepresentativeEntry().getParent().getChildren();
+ }
+
+ return null;
+ }
+
+ private boolean isEntryTopLevel(NotificationEntry entry) {
+ return entry.getParent() == ROOT_ENTRY;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 3c35b7bd8472..5243854ea412 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -24,7 +24,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.NotificationIconAreaController
-import java.lang.RuntimeException
import javax.inject.Inject
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index f3ed95bd2d76..e2aae64ce220 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -50,10 +50,15 @@ import com.android.systemui.statusbar.notification.collection.coordinator.Visual
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
@@ -67,7 +72,6 @@ import com.android.systemui.statusbar.notification.row.NotificationBlockingHelpe
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -91,7 +95,7 @@ public interface NotificationsModule {
@Provides
static NotificationEntryManager provideNotificationEntryManager(
NotificationEntryManagerLogger logger,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationRankingManager rankingManager,
NotificationEntryManager.KeyguardEnvironment keyguardEnvironment,
FeatureFlags featureFlags,
@@ -206,6 +210,29 @@ public interface NotificationsModule {
context, notificationGutsManager, notificationEntryManager, metricsLogger);
}
+ /** Provides an instance of {@link GroupMembershipManager} */
+ @SysUISingleton
+ @Provides
+ static GroupMembershipManager provideGroupMembershipManager(
+ FeatureFlags featureFlags,
+ Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? new GroupMembershipManagerImpl()
+ : groupManagerLegacy.get();
+ }
+
+ /** Provides an instance of {@link GroupExpansionManager} */
+ @SysUISingleton
+ @Provides
+ static GroupExpansionManager provideGroupExpansionManager(
+ FeatureFlags featureFlags,
+ Lazy<GroupMembershipManager> groupMembershipManager,
+ Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? new GroupExpansionManagerImpl(groupMembershipManager.get())
+ : groupManagerLegacy.get();
+ }
+
/** Initializes the notification data pipeline (can be disabled via config). */
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 6460892952e7..9fb292878553 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -30,12 +30,12 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.notification.interruption.HeadsUpController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper
-import com.android.systemui.statusbar.phone.NotificationGroupManager
import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.HeadsUpManager
@@ -65,7 +65,7 @@ class NotificationsControllerImpl @Inject constructor(
private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
private val remoteInputUriController: RemoteInputUriController,
- private val groupManager: NotificationGroupManager,
+ private val groupManagerLegacy: Lazy<NotificationGroupManagerLegacy>,
private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper,
private val headsUpManager: HeadsUpManager,
private val headsUpController: HeadsUpController,
@@ -111,11 +111,11 @@ class NotificationsControllerImpl @Inject constructor(
} else {
targetSdkResolver.initialize(entryManager)
remoteInputUriController.attach(entryManager)
- groupAlertTransferHelper.bind(entryManager, groupManager)
- headsUpManager.addListener(groupManager)
+ groupAlertTransferHelper.bind(entryManager, groupManagerLegacy.get())
+ headsUpManager.addListener(groupManagerLegacy.get())
headsUpManager.addListener(groupAlertTransferHelper)
headsUpController.attach(entryManager, headsUpManager)
- groupManager.setHeadsUpManager(headsUpManager)
+ groupManagerLegacy.get().setHeadsUpManager(headsUpManager)
groupAlertTransferHelper.setHeadsUpManager(headsUpManager)
entryManager.attach(notificationListener)
@@ -131,7 +131,6 @@ class NotificationsControllerImpl @Inject constructor(
if (dumpTruck) {
entryManager.dump(pw, " ")
}
- groupManager.dump(fd, pw, args)
}
// TODO: Convert all functions below this line into listeners instead of public methods
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
index 743bf332fc9d..99b2fcc9d610 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
@@ -214,7 +214,7 @@ class PeopleHubDataSourceImpl @Inject constructor(
}
private fun NotificationEntry.extractPerson(): PersonModel? {
- val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
if (type == TYPE_NON_PERSON) {
return null
}
@@ -249,7 +249,7 @@ class PeopleHubDataSourceImpl @Inject constructor(
private fun NotificationEntry.extractPersonKey(): PersonKey? {
// TODO migrate to shortcut id when snoozing is conversation wide
- val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking)
+ val type = peopleNotificationIdentifier.getPeopleNotificationType(this)
return if (type != TYPE_NON_PERSON) key else null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index 1ac2cb5a36d5..0d92616767f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -20,12 +20,13 @@ import android.annotation.IntDef
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
-import com.android.systemui.statusbar.phone.NotificationGroupManager
import javax.inject.Inject
import kotlin.math.max
@@ -40,10 +41,12 @@ interface PeopleNotificationIdentifier {
* that users shortcuts.
*/
@PeopleNotificationType
- fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int
+ fun getPeopleNotificationType(entry: NotificationEntry): Int
- fun compareTo(@PeopleNotificationType a: Int,
- @PeopleNotificationType b: Int): Int
+ fun compareTo(
+ @PeopleNotificationType a: Int,
+ @PeopleNotificationType b: Int
+ ): Int
companion object {
@@ -62,24 +65,27 @@ interface PeopleNotificationIdentifier {
@SysUISingleton
class PeopleNotificationIdentifierImpl @Inject constructor(
private val personExtractor: NotificationPersonExtractor,
- private val groupManager: NotificationGroupManager
+ private val groupManager: GroupMembershipManager
) : PeopleNotificationIdentifier {
@PeopleNotificationType
- override fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int =
- when (val type = ranking.personTypeInfo) {
+ override fun getPeopleNotificationType(entry: NotificationEntry): Int =
+ when (val type = entry.ranking.personTypeInfo) {
TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
else -> {
- when (val type = upperBound(type, extractPersonTypeInfo(sbn))) {
+ when (val type = upperBound(type, extractPersonTypeInfo(entry.sbn))) {
TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON
- else -> upperBound(type, getPeopleTypeOfSummary(sbn))
+ else -> upperBound(type, getPeopleTypeOfSummary(entry))
}
}
}
- override fun compareTo(@PeopleNotificationType a: Int,
- @PeopleNotificationType b: Int): Int {
- return b.compareTo(a);
+ override fun compareTo(
+ @PeopleNotificationType a: Int,
+ @PeopleNotificationType b: Int
+ ): Int
+ {
+ return b.compareTo(a)
}
/**
@@ -105,14 +111,14 @@ class PeopleNotificationIdentifierImpl @Inject constructor(
private fun extractPersonTypeInfo(sbn: StatusBarNotification) =
if (personExtractor.isPersonNotification(sbn)) TYPE_PERSON else TYPE_NON_PERSON
- private fun getPeopleTypeOfSummary(statusBarNotification: StatusBarNotification): Int {
- if (!groupManager.isSummaryOfGroup(statusBarNotification)) {
+ private fun getPeopleTypeOfSummary(entry: NotificationEntry): Int {
+ if (!groupManager.isGroupSummary(entry)) {
return TYPE_NON_PERSON
}
- val childTypes = groupManager.getChildren(statusBarNotification)
+ val childTypes = groupManager.getChildren(entry)
?.asSequence()
- ?.map { getPeopleNotificationType(it.sbn, it.ranking) }
+ ?.map { getPeopleNotificationType(it) }
?: return TYPE_NON_PERSON
var groupType = TYPE_NON_PERSON
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 46b497339d94..89f720535402 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
@@ -86,6 +86,8 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -97,7 +99,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationChildrenCon
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
@@ -220,7 +221,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mNeedsRedaction;
private boolean mLastChronometerRunning = true;
private ViewStub mChildrenContainerStub;
- private NotificationGroupManager mGroupManager;
+ private GroupMembershipManager mGroupMembershipManager;
+ private GroupExpansionManager mGroupExpansionManager;
private boolean mChildrenExpanded;
private boolean mIsSummaryWithChildren;
private NotificationChildrenContainer mChildrenContainer;
@@ -269,10 +271,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public void onClick(View v) {
if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
- && mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
+ && mGroupMembershipManager.isGroupSummary(mEntry)) {
mGroupExpansionChanging = true;
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
- boolean nowExpanded = mGroupManager.toggleGroupExpansion(mEntry.getSbn());
+ final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
+ boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry);
mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
nowExpanded);
@@ -527,8 +529,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
private boolean isConversation() {
- return mPeopleNotificationIdentifier
- .getPeopleNotificationType(mEntry.getSbn(), mEntry.getRanking())
+ return mPeopleNotificationIdentifier.getPeopleNotificationType(mEntry)
!= PeopleNotificationIdentifier.TYPE_NON_PERSON;
}
@@ -820,7 +821,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @return whether this notification is the only child in the group summary
*/
public boolean isOnlyChildInGroup() {
- return mGroupManager.isOnlyChildInGroup(mEntry.getSbn());
+ return mGroupMembershipManager.isOnlyChildInGroup(mEntry);
}
public ExpandableNotificationRow getNotificationParent() {
@@ -1425,8 +1426,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void performDismiss(boolean fromAccessibility) {
if (isOnlyChildInGroup()) {
- NotificationEntry groupSummary =
- mGroupManager.getLogicalGroupSummary(mEntry.getSbn());
+ NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(mEntry);
if (groupSummary.isClearable()) {
// If this is the only child in the group, dismiss the group, but don't try to show
// the blocking helper affordance!
@@ -1579,7 +1579,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
String notificationKey,
ExpansionLogger logger,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager,
HeadsUpManager headsUpManager,
RowContentBindStage rowContentBindStage,
OnExpandClickListener onExpandClickListener,
@@ -1600,8 +1601,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mLogger = logger;
mLoggingKey = notificationKey;
mBypassController = bypassController;
- mGroupManager = groupManager;
- mPrivateLayout.setGroupManager(groupManager);
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
+ mPrivateLayout.setGroupMembershipManager(groupMembershipManager);
mHeadsUpManager = headsUpManager;
mRowContentBindStage = rowContentBindStage;
mOnExpandClickListener = onExpandClickListener;
@@ -2184,8 +2186,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mFalsingManager.setNotificationExpanded();
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
- mGroupManager.setGroupExpanded(mEntry.getSbn(), userExpanded);
+ final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
+ mGroupExpansionManager.setGroupExpanded(mEntry, userExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
return;
}
@@ -2328,7 +2330,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public boolean isGroupExpanded() {
- return mGroupManager.isGroupExpanded(mEntry.getSbn());
+ return mGroupExpansionManager.isGroupExpanded(mEntry);
}
private void onAttachedChildrenCountChanged() {
@@ -2574,7 +2576,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void makeActionsVisibile() {
setUserExpanded(true, true);
if (isChildInGroup()) {
- mGroupManager.setGroupExpanded(mEntry.getSbn(), true);
+ mGroupExpansionManager.setGroupExpanded(mEntry, true);
}
notifyHeightChanged(false /* needsAnimation */);
}
@@ -2867,7 +2869,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void onExpandedByGesture(boolean userExpanded) {
int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
- if (mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
+ if (mGroupMembershipManager.isGroupSummary(mEntry)) {
event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
}
MetricsLogger.action(mContext, event, userExpanded);
@@ -2912,7 +2914,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
boolean nowExpanded = isExpanded();
if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
- nowExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+ nowExpanded = mGroupExpansionManager.isGroupExpanded(mEntry);
}
if (nowExpanded != wasExpanded) {
updateShelfIconColor();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index ce760cb525f9..05d9fe757dfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -31,6 +31,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NodeController;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -39,7 +41,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.time.SystemClock;
@@ -62,7 +63,8 @@ public class ExpandableNotificationRowController implements NodeController {
private final String mAppName;
private final String mNotificationKey;
private final KeyguardBypassController mKeyguardBypassController;
- private final NotificationGroupManager mNotificationGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
+ private final GroupExpansionManager mGroupExpansionManager;
private final RowContentBindStage mRowContentBindStage;
private final NotificationLogger mNotificationLogger;
private final HeadsUpManager mHeadsUpManager;
@@ -85,7 +87,8 @@ public class ExpandableNotificationRowController implements NodeController {
NotificationMediaManager mediaManager, PluginManager pluginManager,
SystemClock clock, @AppName String appName, @NotificationKey String notificationKey,
KeyguardBypassController keyguardBypassController,
- NotificationGroupManager notificationGroupManager,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager,
RowContentBindStage rowContentBindStage,
NotificationLogger notificationLogger, HeadsUpManager headsUpManager,
ExpandableNotificationRow.OnExpandClickListener onExpandClickListener,
@@ -103,7 +106,8 @@ public class ExpandableNotificationRowController implements NodeController {
mAppName = appName;
mNotificationKey = notificationKey;
mKeyguardBypassController = keyguardBypassController;
- mNotificationGroupManager = notificationGroupManager;
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
mRowContentBindStage = rowContentBindStage;
mNotificationLogger = notificationLogger;
mHeadsUpManager = headsUpManager;
@@ -128,7 +132,8 @@ public class ExpandableNotificationRowController implements NodeController {
mNotificationKey,
mExpansionLogger,
mKeyguardBypassController,
- mNotificationGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mHeadsUpManager,
mRowContentBindStage,
mOnExpandClickListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index c7e44c5e8e0a..1de9308a40b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -28,9 +28,7 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -52,11 +50,10 @@ import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
-import com.android.systemui.statusbar.notification.row.wrapper.NotificationTemplateViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplies;
import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -122,8 +119,8 @@ public class NotificationContentView extends FrameLayout {
private int mSmallHeight;
private int mHeadsUpHeight;
private int mNotificationMaxHeight;
- private StatusBarNotification mStatusBarNotification;
- private NotificationGroupManager mGroupManager;
+ private NotificationEntry mNotificationEntry;
+ private GroupMembershipManager mGroupMembershipManager;
private RemoteInputController mRemoteInputController;
private Runnable mExpandedVisibleListener;
private PeopleNotificationIdentifier mPeopleIdentifier;
@@ -778,7 +775,7 @@ public class NotificationContentView extends FrameLayout {
}
private boolean isGroupExpanded() {
- return mGroupManager.isGroupExpanded(mStatusBarNotification);
+ return mContainingNotification.isGroupExpanded();
}
public void setClipTopAmount(int clipTopAmount) {
@@ -908,10 +905,10 @@ public class NotificationContentView extends FrameLayout {
public int getBackgroundColorForExpansionState() {
// When expanding or user locked we want the new type, when collapsing we want
// the original type
- final int visibleType = (mContainingNotification.isGroupExpanded()
- || mContainingNotification.isUserLocked())
- ? calculateVisibleType()
- : getVisibleType();
+ final int visibleType = (
+ isGroupExpanded() || mContainingNotification.isUserLocked())
+ ? calculateVisibleType()
+ : getVisibleType();
return getBackgroundColor(visibleType);
}
@@ -1145,7 +1142,7 @@ public class NotificationContentView extends FrameLayout {
}
public void onNotificationUpdated(NotificationEntry entry) {
- mStatusBarNotification = entry.getSbn();
+ mNotificationEntry = entry;
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateAllSingleLineViews();
ExpandableNotificationRow row = entry.getRow();
@@ -1176,7 +1173,7 @@ public class NotificationContentView extends FrameLayout {
if (mIsChildInGroup) {
boolean isNewView = mSingleLineView == null;
mSingleLineView = mHybridGroupManager.bindFromNotification(
- mSingleLineView, mContractedChild, mStatusBarNotification, this);
+ mSingleLineView, mContractedChild, mNotificationEntry.getSbn(), this);
if (isNewView) {
updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE,
mSingleLineView, mSingleLineView);
@@ -1363,7 +1360,7 @@ public class NotificationContentView extends FrameLayout {
return;
}
boolean isPersonWithShortcut =
- mPeopleIdentifier.getPeopleNotificationType(entry.getSbn(), entry.getRanking())
+ mPeopleIdentifier.getPeopleNotificationType(entry)
>= PeopleNotificationIdentifier.TYPE_FULL_PERSON;
boolean showButton = isBubblesEnabled()
&& isPersonWithShortcut
@@ -1516,8 +1513,8 @@ public class NotificationContentView extends FrameLayout {
}
}
- public void setGroupManager(NotificationGroupManager groupManager) {
- mGroupManager = groupManager;
+ public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) {
+ mGroupMembershipManager = groupMembershipManager;
}
public void setRemoteInputController(RemoteInputController r) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 205cecc92e55..65a72cc0b76b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -24,7 +24,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
-import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -260,8 +259,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
}
mFeedbackItem = createFeedbackItem(mContext);
NotificationEntry entry = mParent.getEntry();
- int personNotifType = mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking());
+ int personNotifType = mPeopleNotificationIdentifier.getPeopleNotificationType(entry);
if (personNotifType == PeopleNotificationIdentifier.TYPE_PERSON) {
mInfoItem = createPartialConversationItem(mContext);
} else if (personNotifType >= PeopleNotificationIdentifier.TYPE_FULL_PERSON) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 3370773df807..60883f04c9e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -117,6 +117,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -129,8 +131,6 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -233,7 +233,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private final StackScrollAlgorithm mStackScrollAlgorithm;
private final AmbientState mAmbientState;
- private NotificationGroupManager mGroupManager;
+ private GroupMembershipManager mGroupMembershipManager;
+ private GroupExpansionManager mGroupExpansionManager;
private NotificationActivityStarter mNotificationActivityStarter;
private HashSet<ExpandableView> mChildrenToAddAnimated = new HashSet<>();
private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
@@ -415,7 +416,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private boolean mPulsing;
- private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
@@ -560,7 +560,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
NotifPipeline notifPipeline,
NotificationEntryManager entryManager,
NotifCollection notifCollection,
- UiEventLogger uiEventLogger
+ UiEventLogger uiEventLogger,
+ GroupMembershipManager groupMembershipManager,
+ GroupExpansionManager groupExpansionManager
) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -636,6 +638,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
});
}
+ mGroupMembershipManager = groupMembershipManager;
+ mGroupExpansionManager = groupExpansionManager;
mDynamicPrivacyController = dynamicPrivacyController;
mStatusbarStateController = statusbarStateController;
@@ -1440,7 +1444,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
ExpandableNotificationRow row = mTopHeadsUpEntry.getRow();
if (row.isChildInGroup()) {
final NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(row.getEntry().getSbn());
+ mGroupMembershipManager.getGroupSummary(row.getEntry());
if (groupSummary != null) {
row = groupSummary.getRow();
}
@@ -1617,9 +1621,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
NotificationEntry entry = row.getEntry();
if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
&& mTopHeadsUpEntry.getRow() != row
- && mGroupManager.getGroupSummary(
- mTopHeadsUpEntry.getSbn())
- != entry) {
+ && mGroupMembershipManager.getGroupSummary(mTopHeadsUpEntry) != entry) {
continue;
}
return row.getViewAtPosition(touchY - childTop);
@@ -3017,8 +3019,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.ADAPTER)
private boolean isChildInGroup(View child) {
return child instanceof ExpandableNotificationRow
- && mGroupManager.isChildInGroupWithSummary(
- ((ExpandableNotificationRow) child).getEntry().getSbn());
+ && mGroupMembershipManager.isChildInGroup(
+ ((ExpandableNotificationRow) child).getEntry());
}
/**
@@ -3083,6 +3085,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return hasAddEvent;
}
+ // TODO (b/162832756): remove since this won't happen in new pipeline (we prune groups in
+ // ShadeListBuilder)
/**
* @param child the child to query
* @return whether a view is not a top level child but a child notification and that group is
@@ -3093,7 +3097,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(row.getEntry().getSbn());
+ mGroupMembershipManager.getGroupSummary(row.getEntry());
if (groupSummary != null && groupSummary.getRow() != row) {
return row.getVisibility() == View.INVISIBLE;
}
@@ -4349,7 +4353,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (changed) {
mWillExpand = false;
if (!mIsExpanded) {
- mGroupManager.collapseAllGroups();
+ mGroupExpansionManager.collapseGroups();
mExpandHelper.cancelImmediately();
}
updateNotificationAnimationStates();
@@ -4886,12 +4890,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
this.mStatusBar = statusBar;
}
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setGroupManager(NotificationGroupManager groupManager) {
- this.mGroupManager = groupManager;
- mGroupManager.addOnGroupChangeListener(mOnGroupChangeListener);
- }
-
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
void requestAnimateEverything() {
if (mIsExpanded && mAnimationsEnabled) {
@@ -4990,17 +4988,29 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
public void removeContainerView(View v) {
Assert.isMainThread();
removeView(v);
+ if (v instanceof ExpandableNotificationRow && !mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
Assert.isMainThread();
addView(v);
+ if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
public void addContainerViewAt(View v, int index) {
Assert.isMainThread();
addView(v, index);
+ if (v instanceof ExpandableNotificationRow && mController.isShowingEmptyShadeView()) {
+ mController.updateShowEmptyShadeView();
+ updateFooter();
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5101,6 +5111,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
updateScrollability();
}
+ boolean isQsExpanded() {
+ return mQsExpanded;
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setQsExpansionFraction(float qsExpansionFraction) {
mQsExpansionFraction = qsExpansionFraction;
@@ -6296,39 +6310,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
public HeadsUpTouchHelper.Callback getHeadsUpCallback() { return mHeadsUpCallback; }
-
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() {
- @Override
- public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) {
- boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled
- && (mIsExpanded || changedRow.isPinned());
- if (animated) {
- mExpandedGroupView = changedRow;
- mNeedsAnimation = true;
- }
- changedRow.setChildrenExpanded(expanded, animated);
- if (!mGroupExpandedForMeasure) {
- onChildHeightChanged(changedRow, false /* needsAnimation */);
- }
- runAfterAnimationFinished(new Runnable() {
- @Override
- public void run() {
- changedRow.onFinishedExpansionChange();
- }
- });
- }
-
- @Override
- public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
- mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
+ void onGroupExpandChanged(ExpandableNotificationRow changedRow, boolean expanded) {
+ boolean animated = mAnimationsEnabled && (mIsExpanded || changedRow.isPinned());
+ if (animated) {
+ mExpandedGroupView = changedRow;
+ mNeedsAnimation = true;
}
+ changedRow.setChildrenExpanded(expanded, animated);
+ onChildHeightChanged(changedRow, false /* needsAnimation */);
- @Override
- public void onGroupsChanged() {
- mStatusBar.requestNotificationUpdate("onGroupsChanged");
- }
- };
+ runAfterAnimationFinished(new Runnable() {
+ @Override
+ public void run() {
+ changedRow.onFinishedExpansionChange();
+ }
+ });
+ }
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 70892e0f9b38..a0b49aca6ded 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.content.res.Resources;
import android.graphics.Point;
@@ -56,6 +57,10 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -67,7 +72,6 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -117,6 +121,8 @@ public class NotificationStackScrollLayoutController {
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
private NotificationSwipeHelper mSwipeHelper;
+ private boolean mShowEmptyShadeView;
+ private int mBarState;
private final NotificationListContainerImpl mNotificationListContainer =
new NotificationListContainerImpl();
@@ -127,6 +133,8 @@ public class NotificationStackScrollLayoutController {
@Override
public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
+ mZenModeController.addCallback(mZenModeControllerCallback);
+ mBarState = mStatusBarStateController.getState();
mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
}
@@ -134,6 +142,7 @@ public class NotificationStackScrollLayoutController {
@Override
public void onViewDetachedFromWindow(View v) {
mConfigurationController.removeCallback(mConfigurationListener);
+ mZenModeController.removeCallback(mZenModeControllerCallback);
mStatusBarStateController.removeCallback(mStateListener);
}
};
@@ -154,11 +163,13 @@ public class NotificationStackScrollLayoutController {
final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onDensityOrFontScaleChanged() {
+ updateShowEmptyShadeView();
mView.reinflateViews();
}
@Override
public void onOverlayChanged() {
+ updateShowEmptyShadeView();
mView.updateCornerRadius();
mView.reinflateViews();
}
@@ -179,14 +190,15 @@ public class NotificationStackScrollLayoutController {
@Override
public void onStatePreChange(int oldState, int newState) {
if (oldState == StatusBarState.SHADE_LOCKED
- && newState == StatusBarState.KEYGUARD) {
+ && newState == KEYGUARD) {
mView.requestAnimateEverything();
}
}
@Override
public void onStateChanged(int newState) {
- mView.setStatusBarState(newState);
+ mBarState = newState;
+ mView.setStatusBarState(mBarState);
}
@Override
@@ -480,6 +492,14 @@ public class NotificationStackScrollLayoutController {
}
};
+ private final ZenModeController.Callback mZenModeControllerCallback =
+ new ZenModeController.Callback() {
+ @Override
+ public void onZenChanged(int zen) {
+ updateShowEmptyShadeView();
+ }
+ };
+
@Inject
public NotificationStackScrollLayoutController(
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
@@ -501,7 +521,9 @@ public class NotificationStackScrollLayoutController {
@Main Resources resources,
NotificationSwipeHelper.Builder notificationSwipeHelperBuilder,
StatusBar statusBar,
- ScrimController scrimController) {
+ ScrimController scrimController,
+ NotificationGroupManagerLegacy legacyGroupManager,
+ GroupExpansionManager groupManager) {
mAllowLongPress = allowLongPress;
mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager;
@@ -522,12 +544,28 @@ public class NotificationStackScrollLayoutController {
mNotificationSwipeHelperBuilder = notificationSwipeHelperBuilder;
mStatusBar = statusBar;
mScrimController = scrimController;
+ groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> {
+ mView.onGroupExpandChanged(changedRow, expanded);
+ });
+
+ legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
+ @Override
+ public void onGroupCreatedFromChildren(NotificationGroup group) {
+ mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
+ }
+
+ @Override
+ public void onGroupsChanged() {
+ mStatusBar.requestNotificationUpdate("onGroupsChanged");
+ }
+ });
}
public void attach(NotificationStackScrollLayout view) {
mView = view;
mView.setController(this);
mView.setTouchHandler(new TouchHandler());
+ mView.setStatusBar(mStatusBar);
mSwipeHelper = mNotificationSwipeHelperBuilder
.setSwipeDirection(SwipeHelper.X)
@@ -795,6 +833,7 @@ public class NotificationStackScrollLayoutController {
public void setQsExpanded(boolean expanded) {
mView.setQsExpanded(expanded);
+ updateShowEmptyShadeView();
}
public void setScrollingEnabled(boolean enabled) {
@@ -903,8 +942,21 @@ public class NotificationStackScrollLayoutController {
return mView.getFooterViewHeightWithPadding();
}
- public void updateEmptyShadeView(boolean visible) {
- mView.updateEmptyShadeView(visible, mZenModeController.areNotificationsHiddenInShade());
+ /**
+ * Update whether we should show the empty shade view (no notifications in the shade).
+ * If so, send the update to our view.
+ */
+ public void updateShowEmptyShadeView() {
+ mShowEmptyShadeView = mBarState != KEYGUARD
+ && !mView.isQsExpanded()
+ && mView.getVisibleNotificationCount() == 0;
+ mView.updateEmptyShadeView(
+ mShowEmptyShadeView,
+ mZenModeController.areNotificationsHiddenInShade());
+ }
+
+ public boolean isShowingEmptyShadeView() {
+ return mShowEmptyShadeView;
}
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
@@ -1012,14 +1064,6 @@ public class NotificationStackScrollLayoutController {
mView.setNotificationPanelController(notificationPanelViewController);
}
- public void setStatusBar(StatusBar statusBar) {
- mView.setStatusBar(statusBar);
- }
-
- public void setGroupManager(NotificationGroupManager groupManager) {
- mView.setGroupManager(groupManager);
- }
-
public void setShelfController(NotificationShelfController notificationShelfController) {
mView.setShelfController(notificationShelfController);
}
@@ -1095,6 +1139,7 @@ public class NotificationStackScrollLayoutController {
}
private class NotificationListContainerImpl implements NotificationListContainer {
+
@Override
public void setChildTransferInProgress(boolean childTransferInProgress) {
mView.setChildTransferInProgress(childTransferInProgress);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 8092cb910b07..3827123f0160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -33,6 +33,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController.StateList
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -55,7 +56,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@VisibleForTesting
final int mExtensionTime;
private final KeyguardBypassController mBypassController;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>();
private final int mAutoHeadsUpNotificationDecay;
// TODO (b/162832756): remove visual stability manager when migrating to new pipeline
@@ -101,7 +102,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
public HeadsUpManagerPhone(@NonNull final Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
ConfigurationController configurationController) {
super(context);
Resources resources = mContext.getResources();
@@ -110,7 +111,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
R.integer.auto_heads_up_notification_decay);
statusBarStateController.addCallback(mStatusBarStateListener);
mBypassController = bypassController;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
updateResources();
configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@@ -166,7 +167,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
} else {
if (topEntry.isChildInGroup()) {
final NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(topEntry.getSbn());
+ mGroupMembershipManager.getGroupSummary(topEntry);
if (groupSummary != null) {
topEntry = groupSummary;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index b6a284c5e3c4..09034c0899f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -40,6 +40,8 @@ import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.ContainerView;
+import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -50,9 +52,12 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
+import javax.inject.Inject;
+
/**
* A class which manages the bouncer on the lockscreen.
*/
+@KeyguardBouncerScope
public class KeyguardBouncer {
private static final String TAG = "KeyguardBouncer";
@@ -95,8 +100,9 @@ public class KeyguardBouncer {
private boolean mIsAnimatingAway;
private boolean mIsScrimmed;
+ @Inject
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, ViewGroup container,
+ LockPatternUtils lockPatternUtils, @ContainerView ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
BouncerExpansionCallback expansionCallback,
KeyguardStateController keyguardStateController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index dd9c8207af06..3181f520dca2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -31,11 +31,11 @@ import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup;
-import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -44,8 +44,8 @@ import java.util.ArrayList;
import java.util.Objects;
/**
- * A helper class dealing with the alert interactions between {@link NotificationGroupManager} and
- * {@link HeadsUpManager}. In particular, this class deals with keeping
+ * A helper class dealing with the alert interactions between {@link NotificationGroupManagerLegacy}
+ * and {@link HeadsUpManager}. In particular, this class deals with keeping
* the correct notification in a group alerting based off the group suppression.
*/
public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener,
@@ -66,8 +66,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
private HeadsUpManager mHeadsUpManager;
private final RowContentBindStage mRowContentBindStage;
- private final NotificationGroupManager mGroupManager =
- Dependency.get(NotificationGroupManager.class);
+ private final NotificationGroupManagerLegacy mGroupManager =
+ Dependency.get(NotificationGroupManagerLegacy.class);
private NotificationEntryManager mEntryManager;
@@ -83,7 +83,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
/** Causes the TransferHelper to register itself as a listener to the appropriate classes. */
public void bind(NotificationEntryManager entryManager,
- NotificationGroupManager groupManager) {
+ NotificationGroupManagerLegacy groupManager) {
if (mEntryManager != null) {
throw new IllegalStateException("Already bound.");
}
@@ -95,7 +95,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
mEntryManager = entryManager;
mEntryManager.addNotificationEntryListener(mNotificationEntryListener);
- groupManager.addOnGroupChangeListener(mOnGroupChangeListener);
+ groupManager.registerGroupChangeListener(mOnGroupChangeListener);
}
/**
@@ -128,7 +128,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
mIsDozing = isDozing;
}
- private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() {
+ private final NotificationGroupManagerLegacy.OnGroupChangeListener mOnGroupChangeListener =
+ new NotificationGroupManagerLegacy.OnGroupChangeListener() {
@Override
public void onGroupCreated(NotificationGroup group, String groupKey) {
mGroupAlertEntries.put(groupKey, new GroupAlertEntry(group));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 1cd85e3b3cc1..169058a3da21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -107,6 +107,8 @@ import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -120,7 +122,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
@@ -168,9 +169,6 @@ public class NotificationPanelViewController extends PanelViewController {
mOnHeadsUpChangedListener =
new MyOnHeadsUpChangedListener();
private final HeightListener mHeightListener = new HeightListener();
- private final ZenModeControllerCallback
- mZenModeControllerCallback =
- new ZenModeControllerCallback();
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
@@ -178,7 +176,6 @@ public class NotificationPanelViewController extends PanelViewController {
private final NotificationPanelView mView;
private final MetricsLogger mMetricsLogger;
private final ActivityManager mActivityManager;
- private final ZenModeController mZenModeController;
private final ConfigurationController mConfigurationController;
private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
@@ -342,8 +339,6 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean mKeyguardStatusViewAnimating;
private ValueAnimator mQsSizeChangeAnimator;
- private boolean mShowEmptyShadeView;
-
private boolean mQsScrimEnabled = true;
private boolean mQsTouchAboveFalsingThreshold;
private int mQsFalsingThreshold;
@@ -367,7 +362,8 @@ public class NotificationPanelViewController extends PanelViewController {
setHeadsUpAnimatingAway(false);
notifyBarPanelExpansionChanged();
};
- private NotificationGroupManager mGroupManager;
+ // TODO (b/162832756): once migrated to the new pipeline, delete legacy group manager
+ private NotificationGroupManagerLegacy mGroupManager;
private boolean mShowIconsWhenExpanded;
private int mIndicationBottomPadding;
private int mAmbientIndicationBottomPadding;
@@ -505,7 +501,7 @@ public class NotificationPanelViewController extends PanelViewController {
LatencyTracker latencyTracker, PowerManager powerManager,
AccessibilityManager accessibilityManager, @DisplayId int displayId,
KeyguardUpdateMonitor keyguardUpdateMonitor, MetricsLogger metricsLogger,
- ActivityManager activityManager, ZenModeController zenModeController,
+ ActivityManager activityManager,
ConfigurationController configurationController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
@@ -514,20 +510,21 @@ public class NotificationPanelViewController extends PanelViewController {
BiometricUnlockController biometricUnlockController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
- NotificationIconAreaController notificationIconAreaController,
- KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) {
+ KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
+ NotificationGroupManagerLegacy groupManager,
+ NotificationIconAreaController notificationIconAreaController) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
mView = view;
mMetricsLogger = metricsLogger;
mActivityManager = activityManager;
- mZenModeController = zenModeController;
mConfigurationController = configurationController;
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
mMediaHierarchyManager = mediaHierarchyManager;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
+ mGroupManager = groupManager;
mNotificationIconAreaController = notificationIconAreaController;
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
mView.setWillNotDraw(!DEBUG);
@@ -724,8 +721,6 @@ public class NotificationPanelViewController extends PanelViewController {
}
private void reInflateViews() {
- updateShowEmptyShadeView();
-
// Re-inflate the status view group.
int index = mView.indexOfChild(mKeyguardStatusView);
mView.removeView(mKeyguardStatusView);
@@ -1727,7 +1722,6 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScrollLayoutController.setScrollingEnabled(
mBarState != KEYGUARD && (!mQsExpanded
|| mQsExpansionFromOverscroll));
- updateEmptyShadeView();
mQsNavbarScrim.setVisibility(
mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling
@@ -2145,7 +2139,7 @@ public class NotificationPanelViewController extends PanelViewController {
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
if (mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0
- && mShowEmptyShadeView) {
+ && mNotificationStackScrollLayoutController.isShowingEmptyShadeView()) {
notificationHeight = mNotificationStackScrollLayoutController.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2561,17 +2555,6 @@ public class NotificationPanelViewController extends PanelViewController {
return mDozing;
}
- public void showEmptyShadeView(boolean emptyShadeViewVisible) {
- mShowEmptyShadeView = emptyShadeViewVisible;
- updateEmptyShadeView();
- }
-
- private void updateEmptyShadeView() {
- // Hide "No notifications" in QS.
- mNotificationStackScrollLayoutController.updateEmptyShadeView(
- mShowEmptyShadeView && !mQsExpanded);
- }
-
public void setQsScrimEnabled(boolean qsScrimEnabled) {
boolean changed = mQsScrimEnabled != qsScrimEnabled;
mQsScrimEnabled = qsScrimEnabled;
@@ -2873,10 +2856,6 @@ public class NotificationPanelViewController extends PanelViewController {
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
}
- private void setGroupManager(NotificationGroupManager groupManager) {
- mGroupManager = groupManager;
- }
-
public boolean hideStatusBarIconsWhenExpanded() {
if (mLaunchingNotification) {
return mHideIconsDuringNotificationLaunch;
@@ -3078,22 +3057,21 @@ public class NotificationPanelViewController extends PanelViewController {
return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL);
}
- private void updateShowEmptyShadeView() {
- boolean
- showEmptyShadeView =
- mBarState != KEYGUARD && !mEntryManager.hasActiveNotifications();
- showEmptyShadeView(showEmptyShadeView);
- }
-
public RemoteInputController.Delegate createRemoteInputDelegate() {
return mNotificationStackScrollLayoutController.createDelegate();
}
- void updateNotificationViews(String reason) {
+ /**
+ * Updates the notification views' sections and status bar icons. This is
+ * triggered by the NotificationPresenter whenever there are changes to the underlying
+ * notification data being displayed. In the new notification pipeline, this is handled in
+ * {@link ShadeViewManager}.
+ */
+ public void updateNotificationViews(String reason) {
mNotificationStackScrollLayoutController.updateSectionBoundaries(reason);
mNotificationStackScrollLayoutController.updateSpeedBumpIndex();
mNotificationStackScrollLayoutController.updateFooter();
- updateShowEmptyShadeView();
+
mNotificationIconAreaController.updateNotificationIcons(createVisibleEntriesList());
}
@@ -3139,15 +3117,10 @@ public class NotificationPanelViewController extends PanelViewController {
*/
public void initDependencies(
StatusBar statusBar,
- NotificationGroupManager groupManager,
NotificationShelfController notificationShelfController) {
setStatusBar(statusBar);
- setGroupManager(mGroupManager);
mNotificationStackScrollLayoutController.setNotificationPanelController(this);
- mNotificationStackScrollLayoutController.setStatusBar(statusBar);
- mNotificationStackScrollLayoutController.setGroupManager(groupManager);
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
- updateShowEmptyShadeView();
mNotificationShelfController = notificationShelfController;
updateMaxDisplayedNotifications(true);
}
@@ -3602,20 +3575,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
- private class ZenModeControllerCallback implements ZenModeController.Callback {
- @Override
- public void onZenChanged(int zen) {
- updateShowEmptyShadeView();
- }
- }
-
private class ConfigurationListener implements ConfigurationController.ConfigurationListener {
@Override
- public void onDensityOrFontScaleChanged() {
- updateShowEmptyShadeView();
- }
-
- @Override
public void onThemeChanged() {
final int themeResId = mView.getContext().getThemeResId();
if (mThemeResId == themeResId) {
@@ -3712,7 +3673,6 @@ public class NotificationPanelViewController extends PanelViewController {
public void onViewAttachedToWindow(View v) {
FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mZenModeController.addCallback(mZenModeControllerCallback);
mConfigurationController.addCallback(mConfigurationListener);
mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
// Theme might have changed between inflating this view and attaching it to the
@@ -3725,7 +3685,6 @@ public class NotificationPanelViewController extends PanelViewController {
public void onViewDetachedFromWindow(View v) {
FragmentHostManager.get(mView).removeTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
- mZenModeController.removeCallback(mZenModeControllerCallback);
mConfigurationController.removeCallback(mConfigurationListener);
mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 58828797cfde..298672769b56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -699,7 +699,6 @@ public class StatusBar extends SystemUI implements DemoMode,
SysuiStatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper,
BubbleController bubbleController,
- NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
@@ -780,7 +779,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController = statusBarStateController;
mVibratorHelper = vibratorHelper;
mBubbleController = bubbleController;
- mGroupManager = groupManager;
mVisualStabilityManager = visualStabilityManager;
mDeviceProvisionedController = deviceProvisionedController;
mNavigationBarController = navigationBarController;
@@ -1159,7 +1157,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanelViewController.initDependencies(
this,
- mGroupManager,
mNotificationShelfController);
BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
@@ -1506,9 +1503,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarKeyguardViewManager.registerStatusBar(
/* statusBar= */ this, getBouncerContainer(),
mNotificationPanelViewController, mBiometricUnlockController,
- mDismissCallbackRegistry,
mNotificationShadeWindowView.findViewById(R.id.lock_icon_container),
- mStackScroller, mKeyguardBypassController, mFalsingManager);
+ mStackScroller, mKeyguardBypassController);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
@@ -4084,8 +4080,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// all notifications
protected NotificationStackScrollLayout mStackScroller;
- private final NotificationGroupManager mGroupManager;
-
// handling reordering
private final VisualStabilityManager mVisualStabilityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 777bf3f73480..b56993b5f439 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,15 +44,13 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.systemui.DejankUtils;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -106,6 +104,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final NavigationModeController mNavigationModeController;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
+ private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@Override
public void onFullyShown() {
@@ -216,7 +215,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
NotificationShadeWindowController notificationShadeWindowController,
KeyguardStateController keyguardStateController,
Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
- NotificationMediaManager notificationMediaManager) {
+ NotificationMediaManager notificationMediaManager,
+ KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
mContext = context;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
@@ -229,6 +229,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mStatusBarStateController = sysuiStatusBarStateController;
mDockManager = dockManager;
mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
+ mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
}
@Override
@@ -236,9 +237,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
ViewGroup container,
NotificationPanelViewController notificationPanelViewController,
BiometricUnlockController biometricUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager) {
+ KeyguardBypassController bypassController) {
mStatusBar = statusBar;
mContainer = container;
mLockIconContainer = lockIconContainer;
@@ -246,9 +246,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE;
}
mBiometricUnlockController = biometricUnlockController;
- mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
- mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
- mExpansionCallback, mKeyguardStateController, falsingManager, bypassController);
+ mBouncer = mKeyguardBouncerComponentFactory
+ .build(container, mExpansionCallback)
+ .createKeyguardBouncer();
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addExpansionListener(this);
mBypassController = bypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index de11c9023200..f80656706f37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -66,10 +66,10 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -96,7 +96,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
- private final NotifCollection mNotifCollection;
private final HeadsUpManagerPhone mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final NotificationClickNotifier mClickNotifier;
@@ -107,7 +106,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final BubbleController mBubbleController;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final KeyguardStateController mKeyguardStateController;
@@ -135,7 +134,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
Executor uiBgExecutor,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
- NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
NotificationClickNotifier clickNotifier,
@@ -146,7 +144,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
KeyguardStateController keyguardStateController,
@@ -170,7 +168,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
- mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
mClickNotifier = clickNotifier;
@@ -181,7 +178,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
mKeyguardStateController = keyguardStateController;
@@ -228,8 +225,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
mLogger.logStartingActivityFromClick(sbn.getKey());
+ final NotificationEntry entry = row.getEntry();
RemoteInputController controller = mRemoteInputManager.getController();
- if (controller.isRemoteInputActive(row.getEntry())
+ if (controller.isRemoteInputActive(entry)
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
// We have an active remote input typed and the user clicked on the notification.
// this was probably unintentional, so we're closing the edit text instead.
@@ -240,7 +238,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
- final boolean isBubble = row.getEntry().isBubble();
+ final boolean isBubble = entry.isBubble();
// This code path is now executed for notification without a contentIntent.
// The only valid case is Bubble notifications. Guard against other cases
@@ -260,7 +258,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
() -> handleNotificationClickAfterKeyguardDismissed(
- sbn, row, controller, intent,
+ entry, row, controller, intent,
isActivityIntent, wasOccluded, showOverLockscreen);
if (showOverLockscreen) {
mIsCollapsingToShowActivityOverLockscreen = true;
@@ -272,27 +270,27 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
private boolean handleNotificationClickAfterKeyguardDismissed(
- StatusBarNotification sbn,
+ NotificationEntry entry,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
boolean isActivityIntent,
boolean wasOccluded,
boolean showOverLockscreen) {
- mLogger.logHandleClickAfterKeyguardDismissed(sbn.getKey());
+ mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
// TODO: Some of this code may be able to move to NotificationEntryManager.
removeHUN(row);
NotificationEntry parentToCancel = null;
- if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
- NotificationEntry summarySbn = mGroupManager.getLogicalGroupSummary(sbn);
+ if (shouldAutoCancel(entry.getSbn()) && mGroupMembershipManager.isOnlyChildInGroup(entry)) {
+ NotificationEntry summarySbn = mGroupMembershipManager.getLogicalGroupSummary(entry);
if (shouldAutoCancel(summarySbn.getSbn())) {
parentToCancel = summarySbn;
}
}
final NotificationEntry parentToCancelFinal = parentToCancel;
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
- sbn, row, controller, intent,
+ entry, row, controller, intent,
isActivityIntent, wasOccluded, parentToCancelFinal);
if (showOverLockscreen) {
@@ -309,16 +307,16 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
private void handleNotificationClickAfterPanelCollapsed(
- StatusBarNotification sbn,
+ NotificationEntry entry,
ExpandableNotificationRow row,
RemoteInputController controller,
PendingIntent intent,
boolean isActivityIntent,
boolean wasOccluded,
NotificationEntry parentToCancelFinal) {
- mLogger.logHandleClickAfterPanelCollapsed(sbn.getKey());
+ String notificationKey = entry.getKey();
+ mLogger.logHandleClickAfterPanelCollapsed(notificationKey);
- String notificationKey = sbn.getKey();
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
@@ -346,7 +344,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
}
Intent fillInIntent = null;
- NotificationEntry entry = row.getEntry();
CharSequence remoteInputText = null;
if (!TextUtils.isEmpty(entry.remoteInputText)) {
remoteInputText = entry.remoteInputText;
@@ -385,7 +382,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
// necessary in the new pipeline due to group pruning in ShadeListBuilder.
removeNotification(parentToCancelFinal);
}
- if (shouldAutoCancel(sbn)
+ if (shouldAutoCancel(entry.getSbn())
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
notificationKey)) {
// Automatically remove all notifications that we may have kept around longer
@@ -605,7 +602,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final Executor mUiBgExecutor;
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
- private final NotifCollection mNotifCollection;
private final HeadsUpManagerPhone mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final NotificationClickNotifier mClickNotifier;
@@ -616,7 +612,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final BubbleController mBubbleController;
private final Lazy<AssistManager> mAssistManagerLazy;
private final NotificationRemoteInputManager mRemoteInputManager;
- private final NotificationGroupManager mGroupManager;
+ private final GroupMembershipManager mGroupMembershipManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final ShadeController mShadeController;
private final KeyguardStateController mKeyguardStateController;
@@ -643,7 +639,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
@UiBackground Executor uiBgExecutor,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
- NotifCollection notifCollection,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
NotificationClickNotifier clickNotifier,
@@ -654,7 +649,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
BubbleController bubbleController,
Lazy<AssistManager> assistManagerLazy,
NotificationRemoteInputManager remoteInputManager,
- NotificationGroupManager groupManager,
+ GroupMembershipManager groupMembershipManager,
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController,
KeyguardStateController keyguardStateController,
@@ -674,7 +669,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
- mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
mClickNotifier = clickNotifier;
@@ -685,7 +679,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mBubbleController = bubbleController;
mAssistManagerLazy = assistManagerLazy;
mRemoteInputManager = remoteInputManager;
- mGroupManager = groupManager;
+ mGroupMembershipManager = groupMembershipManager;
mLockscreenUserManager = lockscreenUserManager;
mShadeController = shadeController;
mKeyguardStateController = keyguardStateController;
@@ -731,7 +725,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mUiBgExecutor,
mEntryManager,
mNotifPipeline,
- mNotifCollection,
mHeadsUpManager,
mActivityStarter,
mClickNotifier,
@@ -742,7 +735,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mBubbleController,
mAssistManagerLazy,
mRemoteInputManager,
- mGroupManager,
+ mGroupMembershipManager,
mLockscreenUserManager,
mShadeController,
mKeyguardStateController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 8a8942975d2e..36519ac0d808 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -45,6 +45,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -65,7 +66,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final ShadeController mShadeController;
private final ActivityIntentHelper mActivityIntentHelper;
- private final NotificationGroupManager mGroupManager;
+ private final GroupExpansionManager mGroupExpansionManager;
private View mPendingWorkRemoteInputView;
private View mPendingRemoteInputView;
private KeyguardManager mKeyguardManager;
@@ -78,12 +79,15 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
/**
*/
@Inject
- public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager,
+ public StatusBarRemoteInputCallback(
+ Context context,
+ GroupExpansionManager groupExpansionManager,
NotificationLockscreenUserManager notificationLockscreenUserManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- ActivityStarter activityStarter, ShadeController shadeController,
+ ActivityStarter activityStarter,
+ ShadeController shadeController,
CommandQueue commandQueue,
ActionClickLogger clickLogger) {
mContext = context;
@@ -101,7 +105,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
mCommandQueue.addCallback(this);
mActionClickLogger = clickLogger;
mActivityIntentHelper = new ActivityIntentHelper(mContext);
- mGroupManager = groupManager;
+ mGroupExpansionManager = groupExpansionManager;
}
@Override
@@ -182,7 +186,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
} else {
if (row.isChildInGroup() && !row.areChildrenExpanded()) {
// The group isn't expanded, let's make sure it's visible!
- mGroupManager.toggleGroupExpansion(row.getEntry().getSbn());
+ mGroupExpansionManager.toggleGroupExpansion(row.getEntry());
}
row.setUserExpanded(true);
row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 72067d376f7c..16c3dc460a9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -80,7 +80,6 @@ import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -158,7 +157,6 @@ public interface StatusBarPhoneModule {
SysuiStatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper,
BubbleController bubbleController,
- NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
@@ -238,7 +236,6 @@ public interface StatusBarPhoneModule {
statusBarStateController,
vibratorHelper,
bubbleController,
- groupManager,
visualStabilityManager,
deviceProvisionedController,
navigationBarController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 9b4e16525df2..485b1b109eb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -15,8 +15,6 @@
package com.android.systemui.statusbar.policy;
import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -30,6 +28,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
@@ -43,8 +43,8 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
protected static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName();
protected final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
- private final ContentResolver mContentResolver;
- private final Context mContext;
+ private final GlobalSettings mGlobalSettings;
+ private final SecureSettings mSecureSettings;
private final Uri mDeviceProvisionedUri;
private final Uri mUserSetupUri;
protected final ContentObserver mSettingsObserver;
@@ -52,13 +52,14 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
- BroadcastDispatcher broadcastDispatcher) {
+ public DeviceProvisionedControllerImpl(@Main Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSettings,
+ SecureSettings secureSettings) {
super(broadcastDispatcher);
- mContext = context;
- mContentResolver = context.getContentResolver();
- mDeviceProvisionedUri = Global.getUriFor(Global.DEVICE_PROVISIONED);
- mUserSetupUri = Secure.getUriFor(Secure.USER_SETUP_COMPLETE);
+ mGlobalSettings = globalSettings;
+ mSecureSettings = secureSettings;
+ mDeviceProvisionedUri = mGlobalSettings.getUriFor(Global.DEVICE_PROVISIONED);
+ mUserSetupUri = mSecureSettings.getUriFor(Secure.USER_SETUP_COMPLETE);
mSettingsObserver = new ContentObserver(mainHandler) {
@Override
public void onChange(boolean selfChange, Uri uri, int flags) {
@@ -74,13 +75,12 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
@Override
public boolean isDeviceProvisioned() {
- return Global.getInt(mContentResolver, Global.DEVICE_PROVISIONED, 0) != 0;
+ return mGlobalSettings.getInt(Global.DEVICE_PROVISIONED, 0) != 0;
}
@Override
public boolean isUserSetup(int currentUser) {
- return Secure.getIntForUser(mContentResolver, Secure.USER_SETUP_COMPLETE, 0, currentUser)
- != 0;
+ return mSecureSettings.getIntForUser(Secure.USER_SETUP_COMPLETE, 0, currentUser) != 0;
}
@Override
@@ -107,24 +107,24 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
}
protected void startListening(int user) {
- mContentResolver.registerContentObserver(mDeviceProvisionedUri, true,
+ mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
mSettingsObserver, 0);
- mContentResolver.registerContentObserver(mUserSetupUri, true,
+ mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
mSettingsObserver, user);
startTracking();
}
protected void stopListening() {
stopTracking();
- mContentResolver.unregisterContentObserver(mSettingsObserver);
+ mGlobalSettings.unregisterContentObserver(mSettingsObserver);
}
@Override
public void onUserSwitched(int newUserId) {
- mContentResolver.unregisterContentObserver(mSettingsObserver);
- mContentResolver.registerContentObserver(mDeviceProvisionedUri, true,
+ mGlobalSettings.unregisterContentObserver(mSettingsObserver);
+ mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
mSettingsObserver, 0);
- mContentResolver.registerContentObserver(mUserSetupUri, true,
+ mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
mSettingsObserver, newUserId);
notifyUserChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index f9ac760a3367..17fcb1dd6f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -206,7 +206,7 @@ public class UserSwitcherController implements Dumpable {
@Override
protected ArrayList<UserRecord> doInBackground(SparseArray<Bitmap>... params) {
final SparseArray<Bitmap> bitmaps = params[0];
- List<UserInfo> infos = mUserManager.getUsers(true);
+ List<UserInfo> infos = mUserManager.getAliveUsers();
if (infos == null) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
new file mode 100644
index 000000000000..914105fdc4c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 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.statusbar.policy.dagger;
+
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.HotspotControllerImpl;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+
+/** Dagger Module for code in the statusbar.policy package. */
+@Module
+public interface StatusBarPolicyModule {
+ /** */
+ @Binds
+ BluetoothController provideBluetoothController(BluetoothControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ CastController provideCastController(CastControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ ExtensionController provideExtensionController(ExtensionControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ FlashlightController provideFlashlightController(FlashlightControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ KeyguardStateController provideKeyguardMonitor(KeyguardStateControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ HotspotController provideHotspotController(HotspotControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ LocationController provideLocationController(LocationControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ NetworkController provideNetworkController(NetworkControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ NextAlarmController provideNextAlarmController(NextAlarmControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ RotationLockController provideRotationLockController(RotationLockControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ SecurityController provideSecurityController(SecurityControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ SensorPrivacyController provideSensorPrivacyControllerImpl(
+ SensorPrivacyControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ UserInfoController provideUserInfoContrller(UserInfoControllerImpl controllerImpl);
+
+ /** */
+ @Binds
+ ZenModeController provideZenModeController(ZenModeControllerImpl controllerImpl);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/dagger/TunerModule.java b/packages/SystemUI/src/com/android/systemui/tuner/dagger/TunerModule.java
new file mode 100644
index 000000000000..faf7b842f3b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/dagger/TunerModule.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.tuner.dagger;
+
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerServiceImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+/** Dagger Module for code in the tuner package. */
+@Module
+public interface TunerModule {
+ /** */
+ @Binds
+ TunerService provideTunerService(TunerServiceImpl controllerImpl);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
index 3577bc05d1c4..bef05ebb724e 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
@@ -17,7 +17,6 @@
package com.android.systemui.tv;
import com.android.systemui.dagger.DefaultComponentBinder;
-import com.android.systemui.dagger.DependencyBinder;
import com.android.systemui.dagger.DependencyProvider;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.SysUISingleton;
@@ -33,7 +32,6 @@ import dagger.Subcomponent;
@Subcomponent(modules = {
DefaultComponentBinder.class,
DependencyProvider.class,
- DependencyBinder.class,
SystemUIBinder.class,
SystemUIModule.class,
TvSystemUIModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index e7c10f1697f5..d727bfbdf48a 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -47,11 +47,11 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
@@ -136,7 +136,7 @@ public abstract class TvSystemUIModule {
Context context,
StatusBarStateController statusBarStateController,
KeyguardBypassController bypassController,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
ConfigurationController configurationController) {
return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
groupManager, configurationController);
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
new file mode 100644
index 000000000000..5946af383b0f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.concurrency;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.util.concurrent.Executor;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module for classes found within the concurrent package.
+ */
+@Module
+public abstract class GlobalConcurrencyModule {
+
+ /**
+ * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}.
+ */
+ @Binds
+ public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl);
+
+ /** Main Looper */
+ @Provides
+ @Main
+ public static Looper provideMainLooper() {
+ return Looper.getMainLooper();
+ }
+
+ /**
+ * Main Handler.
+ *
+ * Prefer the Main Executor when possible.
+ */
+ @Provides
+ @Main
+ public static Handler provideMainHandler(@Main Looper mainLooper) {
+ return new Handler(mainLooper);
+ }
+
+ /**
+ * Provide a Main-Thread Executor.
+ */
+ @Provides
+ @Main
+ public static Executor provideMainExecutor(Context context) {
+ return context.getMainExecutor();
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
index 628c808aa12b..b9b20c73c5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
@@ -16,7 +16,6 @@
package com.android.systemui.util.concurrency;
-import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -31,7 +30,6 @@ import com.android.systemui.dagger.qualifiers.UiBackground;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -39,7 +37,7 @@ import dagger.Provides;
* Dagger Module for classes found within the concurrent package.
*/
@Module
-public abstract class ConcurrencyModule {
+public abstract class SysUIConcurrencyModule {
/** Background Looper */
@Provides
@SysUISingleton
@@ -62,13 +60,6 @@ public abstract class ConcurrencyModule {
return thread.getLooper();
}
- /** Main Looper */
- @Provides
- @Main
- public static Looper provideMainLooper() {
- return Looper.getMainLooper();
- }
-
/**
* Background Handler.
*
@@ -81,17 +72,6 @@ public abstract class ConcurrencyModule {
}
/**
- * Main Handler.
- *
- * Prefer the Main Executor when possible.
- */
- @Provides
- @Main
- public static Handler provideMainHandler(@Main Looper mainLooper) {
- return new Handler(mainLooper);
- }
-
- /**
* Provide a Background-Thread Executor by default.
*/
@Provides
@@ -121,15 +101,6 @@ public abstract class ConcurrencyModule {
}
/**
- * Provide a Main-Thread Executor.
- */
- @Provides
- @Main
- public static Executor provideMainExecutor(Context context) {
- return context.getMainExecutor();
- }
-
- /**
* Provide a Background-Thread Executor by default.
*/
@Provides
@@ -199,10 +170,4 @@ public abstract class ConcurrencyModule {
public static Executor provideUiBackgroundExecutor() {
return Executors.newSingleThreadExecutor();
}
-
- /**
- * Binds {@link ThreadFactoryImpl} to {@link ThreadFactory}.
- */
- @Binds
- public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
new file mode 100644
index 000000000000..cdfa1457f4a5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.dagger;
+
+import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.RingerModeTrackerImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+/** Dagger Module for code in the util package. */
+@Module
+public interface UtilModule {
+ /** */
+ @Binds
+ RingerModeTracker provideRingerModeTracker(RingerModeTrackerImpl ringerModeTrackerImpl);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
index 5c37f797b678..5aaf7f680d5c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
@@ -67,7 +67,35 @@ public interface SettingsProxy {
* Implicitly calls {@link #getUriFor(String)} on the passed in name.
*/
default void registerContentObserver(String name, ContentObserver settingsObserver) {
- registerContentObserverForUser(name, settingsObserver, getUserId());
+ registerContentObserver(getUriFor(name), settingsObserver);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ */
+ default void registerContentObserver(Uri uri, ContentObserver settingsObserver) {
+ registerContentObserverForUser(uri, settingsObserver, getUserId());
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ *
+ * Implicitly calls {@link #getUriFor(String)} on the passed in name.
+ */
+ default void registerContentObserver(String name, boolean notifyForDescendents,
+ ContentObserver settingsObserver) {
+ registerContentObserver(getUriFor(name), notifyForDescendents, settingsObserver);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
+ */
+ default void registerContentObserver(Uri uri, boolean notifyForDescendents,
+ ContentObserver settingsObserver) {
+ registerContentObserverForUser(uri, notifyForDescendents, settingsObserver, getUserId());
}
/**
@@ -78,8 +106,42 @@ public interface SettingsProxy {
*/
default void registerContentObserverForUser(
String name, ContentObserver settingsObserver, int userHandle) {
+ registerContentObserverForUser(
+ getUriFor(name), settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ */
+ default void registerContentObserverForUser(
+ Uri uri, ContentObserver settingsObserver, int userHandle) {
+ registerContentObserverForUser(
+ uri, false, settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ *
+ * Implicitly calls {@link #getUriFor(String)} on the passed in name.
+ */
+ default void registerContentObserverForUser(
+ String name, boolean notifyForDescendents, ContentObserver settingsObserver,
+ int userHandle) {
+ registerContentObserverForUser(
+ getUriFor(name), notifyForDescendents, settingsObserver, userHandle);
+ }
+
+ /**
+ * Convenience wrapper around
+ * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
+ */
+ default void registerContentObserverForUser(
+ Uri uri, boolean notifyForDescendents, ContentObserver settingsObserver,
+ int userHandle) {
getContentResolver().registerContentObserver(
- getUriFor(name), false, settingsObserver, userHandle);
+ uri, notifyForDescendents, settingsObserver, userHandle);
}
/** See {@link ContentResolver#unregisterContentObserver(ContentObserver)}. */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 51ad30ebcac6..78f83d3c09b4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -49,6 +49,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
+import android.graphics.Region;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -71,6 +72,7 @@ import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
+import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
@@ -109,7 +111,8 @@ import java.util.List;
* Methods ending in "H" must be called on the (ui) handler.
*/
public class VolumeDialogImpl implements VolumeDialog,
- ConfigurationController.ConfigurationListener {
+ ConfigurationController.ConfigurationListener,
+ ViewTreeObserver.OnComputeInternalInsetsListener {
private static final String TAG = Util.logTag(VolumeDialogImpl.class);
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
@@ -126,6 +129,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private final H mHandler = new H();
private final VolumeDialogController mController;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final Region mTouchableRegion = new Region();
private Window mWindow;
private CustomDialog mDialog;
@@ -204,6 +208,33 @@ public class VolumeDialogImpl implements VolumeDialog,
Dependency.get(ConfigurationController.class).removeCallback(this);
}
+ @Override
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo internalInsetsInfo) {
+ // Set touchable region insets on the root dialog view. This tells WindowManager that
+ // touches outside of this region should not be delivered to the volume window, and instead
+ // go to the window below. This is the only way to do this - returning false in
+ // onDispatchTouchEvent results in the event being ignored entirely, rather than passed to
+ // the next window.
+ internalInsetsInfo.setTouchableInsets(
+ ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+
+ mTouchableRegion.setEmpty();
+
+ // Set the touchable region to the union of all child view bounds. We don't use touches on
+ // the volume dialog container itself, so this is fine.
+ for (int i = 0; i < mDialogView.getChildCount(); i++) {
+ final View view = mDialogView.getChildAt(i);
+ mTouchableRegion.op(
+ view.getLeft(),
+ view.getTop(),
+ view.getRight(),
+ view.getBottom(),
+ Region.Op.UNION);
+ }
+
+ internalInsetsInfo.touchableRegion.set(mTouchableRegion);
+ }
+
private void initDialog() {
mDialog = new CustomDialog(mContext);
@@ -235,6 +266,7 @@ public class VolumeDialogImpl implements VolumeDialog,
mDialogView.setAlpha(0);
mDialog.setCanceledOnTouchOutside(true);
mDialog.setOnShowListener(dialog -> {
+ mDialogView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
if (!isLandscape()) mDialogView.setTranslationX(mDialogView.getWidth() / 2.0f);
mDialogView.setAlpha(0);
mDialogView.animate()
@@ -253,6 +285,11 @@ public class VolumeDialogImpl implements VolumeDialog,
.start();
});
+ mDialog.setOnDismissListener(dialogInterface ->
+ mDialogView
+ .getViewTreeObserver()
+ .removeOnComputeInternalInsetsListener(VolumeDialogImpl.this));
+
mDialogView.setOnHoverListener((v, event) -> {
int action = event.getActionMasked();
mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
@@ -1369,6 +1406,11 @@ public class VolumeDialogImpl implements VolumeDialog,
super(context, R.style.volume_dialog_theme);
}
+ /**
+ * NOTE: This will only be called for touches within the touchable region of the volume
+ * dialog, as returned by {@link #onComputeInternalInsets}. Other touches, even if they are
+ * within the bounds of the volume dialog, will fall through to the window below.
+ */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
rescheduleTimeoutH();
@@ -1387,6 +1429,12 @@ public class VolumeDialogImpl implements VolumeDialog,
mHandler.sendEmptyMessage(H.RECHECK_ALL);
}
+ /**
+ * NOTE: This will be called with ACTION_OUTSIDE MotionEvents for touches that occur outside
+ * of the touchable region of the volume dialog (as returned by
+ * {@link #onComputeInternalInsets}) even if those touches occurred within the bounds of the
+ * volume dialog.
+ */
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mShowing) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
new file mode 100644
index 000000000000..1ef4c169b786
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.volume.dagger;
+
+import com.android.systemui.volume.VolumeComponent;
+import com.android.systemui.volume.VolumeDialogComponent;
+
+import dagger.Binds;
+import dagger.Module;
+
+
+/** Dagger Module for code in the volume package. */
+@Module
+public interface VolumeModule {
+ /** */
+ @Binds
+ VolumeComponent provideVolumeComponent(VolumeDialogComponent volumeDialogComponent);
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index a7808ad54d63..f65c2c91c50a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -77,13 +77,13 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -118,7 +118,7 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
- private NotificationGroupManager mNotificationGroupManager;
+ private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private WindowManager mWindowManager;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 4936360756fd..dd191e9cd328 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -82,7 +83,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -116,7 +116,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
- private NotificationGroupManager mNotificationGroupManager;
+ private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private BubbleController.NotifCallback mNotifCallback;
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index 51ca2a4e5966..58b27f24a1d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -30,8 +30,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -52,7 +52,7 @@ public class TestableBubbleController extends BubbleController {
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
FeatureFlags featureFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index d2bf483a6bd6..d041ee047ae0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -45,6 +45,7 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -53,7 +54,6 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.google.android.collect.Lists;
@@ -76,7 +76,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
// Dependency mocks:
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private VisualStabilityManager mVisualStabilityManager;
private TestableLooper mTestableLooper;
@@ -95,7 +95,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mLockscreenUserManager);
- mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
@@ -136,11 +136,11 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
Lists.newArrayList(entry0, entry1, entry2));
// Set up group manager to report that they should be bundled now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(true);
- when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(true);
- when(mGroupManager.getGroupSummary(entry1.getSbn())).thenReturn(entry0);
- when(mGroupManager.getGroupSummary(entry2.getSbn())).thenReturn(entry0);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(true);
+ when(mGroupManager.isChildInGroup(entry2)).thenReturn(true);
+ when(mGroupManager.getGroupSummary(entry1)).thenReturn(entry0);
+ when(mGroupManager.getGroupSummary(entry2)).thenReturn(entry0);
// Run updateNotifications - the view hierarchy should be reorganized.
mViewHierarchyManager.updateNotificationViews();
@@ -165,9 +165,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
Lists.newArrayList(entry0, entry1, entry2));
// Set up group manager to report that they should not be bundled now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry2)).thenReturn(false);
// Run updateNotifications - the view hierarchy should be reorganized.
mViewHierarchyManager.updateNotificationViews();
@@ -194,8 +194,8 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
Lists.newArrayList(entry0, entry1));
// Set up group manager to report a suppressed summary now.
- when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
- when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry0)).thenReturn(false);
+ when(mGroupManager.isChildInGroup(entry1)).thenReturn(false);
when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true);
// Run updateNotifications - the view hierarchy should be reorganized.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index fc0201ad82f0..3e1616c9fa7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -75,13 +75,13 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -119,7 +119,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Mock private NotificationRemoveInterceptor mRemoveInterceptor;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private RankingMap mRankingMap;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private RowInflaterTask mAsyncInflationTask;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 5a81d36ea744..dfe006dfd4fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -48,10 +48,10 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import org.junit.After;
@@ -109,8 +109,8 @@ public class NotificationFilterTest extends SysuiTestCase {
eq(UID_ALLOW_DURING_SETUP)))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
- mDependency.injectTestDependency(NotificationGroupManager.class,
- new NotificationGroupManager(
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class,
+ new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class)));
mDependency.injectMockDependency(ShadeController.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index 386c866cdd03..14877eec9a83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -37,8 +37,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import org.junit.Before;
import org.junit.Test;
@@ -48,12 +48,13 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class HighPriorityProviderTest extends SysuiTestCase {
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private GroupMembershipManager mGroupMembershipManager;
private HighPriorityProvider mHighPriorityProvider;
@Before
@@ -61,7 +62,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mHighPriorityProvider = new HighPriorityProvider(
mPeopleNotificationIdentifier,
- mGroupManager);
+ mGroupMembershipManager);
}
@Test
@@ -71,7 +72,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(IMPORTANCE_HIGH)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -88,7 +89,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(IMPORTANCE_LOW)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_PERSON);
// THEN it has high priority
@@ -105,7 +106,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setNotification(notification)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -123,7 +124,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(IMPORTANCE_LOW)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it has high priority
@@ -141,7 +142,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(IMPORTANCE_MIN)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_NON_PERSON);
// THEN it does NOT have high priority
@@ -165,7 +166,7 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setChannel(channel)
.build();
when(mPeopleNotificationIdentifier
- .getPeopleNotificationType(entry.getSbn(), entry.getRanking()))
+ .getPeopleNotificationType(entry))
.thenReturn(TYPE_PERSON);
// THEN it does NOT have high priority
@@ -173,13 +174,13 @@ public class HighPriorityProviderTest extends SysuiTestCase {
}
@Test
- public void testIsHighPriority_checkChildrenToCalculatePriority() {
+ public void testIsHighPriority_checkChildrenToCalculatePriority_legacy() {
// GIVEN: a summary with low priority has a highPriorityChild and a lowPriorityChild
final NotificationEntry summary = createNotifEntry(false);
final NotificationEntry lowPriorityChild = createNotifEntry(false);
final NotificationEntry highPriorityChild = createNotifEntry(true);
- when(mGroupManager.isGroupSummary(summary.getSbn())).thenReturn(true);
- when(mGroupManager.getChildren(summary.getSbn())).thenReturn(
+ when(mGroupMembershipManager.isGroupSummary(summary)).thenReturn(true);
+ when(mGroupMembershipManager.getChildren(summary)).thenReturn(
new ArrayList<>(Arrays.asList(lowPriorityChild, highPriorityChild)));
// THEN the summary is high priority since it has a high priority child
@@ -210,16 +211,20 @@ public class HighPriorityProviderTest extends SysuiTestCase {
}
@Test
- public void testIsHighPriority_checkChildrenToCalculatePriorityOf() {
+ public void testIsHighPriority_checkChildrenToCalculatePriority() {
// GIVEN:
- // GroupEntry = parentEntry, summary = lowPrioritySummary
+ // parent with summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
// NotificationEntry = highPriorityChild
+ final NotificationEntry lowPrioritySummary = createNotifEntry(false);
final GroupEntry parentEntry = new GroupEntryBuilder()
- .setSummary(createNotifEntry(false))
- .addChild(createNotifEntry(false))
- .addChild(createNotifEntry(true))
+ .setSummary(lowPrioritySummary)
.build();
+ when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn(
+ new ArrayList<>(
+ List.of(
+ createNotifEntry(false),
+ createNotifEntry(true))));
// THEN the GroupEntry parentEntry is high priority since it has a high priority child
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
@@ -228,13 +233,15 @@ public class HighPriorityProviderTest extends SysuiTestCase {
@Test
public void testIsHighPriority_childEntryRankingUpdated() {
// GIVEN:
- // GroupEntry = parentEntry, summary = lowPrioritySummary
+ // parent with summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
- final NotificationEntry lowPriorityChild = createNotifEntry(false);
+ final NotificationEntry lowPrioritySummary = createNotifEntry(false);
final GroupEntry parentEntry = new GroupEntryBuilder()
- .setSummary(createNotifEntry(false))
- .addChild(lowPriorityChild)
+ .setSummary(lowPrioritySummary)
.build();
+ final NotificationEntry lowPriorityChild = createNotifEntry(false);
+ when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn(
+ new ArrayList<>(List.of(lowPriorityChild)));
// WHEN the child entry ranking changes to high priority
lowPriorityChild.setRanking(
@@ -243,9 +250,8 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(IMPORTANCE_HIGH)
.build());
- // THEN the parent entry's high priority value is updated - but not the parent's summary
+ // THEN the parent entry's high priority value is updated
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
- assertFalse(mHighPriorityProvider.isHighPriority(parentEntry.getSummary()));
}
private NotificationEntry createNotifEntry(boolean highPriority) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index 82a7774b4d82..c832fe481f74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -40,7 +40,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
-import com.android.systemui.statusbar.phone.NotificationGroupManager
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
@@ -71,14 +71,14 @@ class NotificationRankingManagerTest : SysuiTestCase() {
notificationFilter = mock(NotificationFilter::class.java)
rankingManager = TestableNotificationRankingManager(
lazyMedia,
- mock(NotificationGroupManager::class.java),
+ mock(NotificationGroupManagerLegacy::class.java),
mock(HeadsUpManager::class.java),
notificationFilter,
mock(NotificationEntryManagerLogger::class.java),
sectionsManager,
personNotificationIdentifier,
HighPriorityProvider(personNotificationIdentifier,
- mock(NotificationGroupManager::class.java))
+ mock(NotificationGroupManagerLegacy::class.java))
)
}
@@ -174,7 +174,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_IMPORTANT_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -194,7 +194,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
whenever(it.isHeadsUp).thenReturn(true)
}
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test"))
@@ -216,7 +216,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -232,7 +232,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(b))
.thenReturn(TYPE_IMPORTANT_PERSON)
whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_IMPORTANT_PERSON))
@@ -261,7 +261,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_PERSON)
val bN = Notification.Builder(mContext, "test")
@@ -277,7 +277,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(b))
.thenReturn(TYPE_FULL_PERSON)
whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_FULL_PERSON))
@@ -400,7 +400,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
.setUser(mContext.user)
.setOverrideGroupKey("")
.build()
- whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking))
+ whenever(personNotificationIdentifier.getPeopleNotificationType(a))
.thenReturn(TYPE_IMPORTANT_PERSON)
assertThat(rankingManager.updateRanking(null, listOf(a, b, c), "test"))
@@ -410,7 +410,7 @@ class NotificationRankingManagerTest : SysuiTestCase() {
internal class TestableNotificationRankingManager(
mediaManager: Lazy<NotificationMediaManager>,
- groupManager: NotificationGroupManager,
+ groupManager: NotificationGroupManagerLegacy,
headsUpManager: HeadsUpManager,
filter: NotificationFilter,
logger: NotificationEntryManagerLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
index c49393d2ed34..09c9bcd967bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
@@ -84,8 +84,8 @@ class ConversationCoordinatorTest : SysuiTestCase() {
@Test
fun testInPeopleSection() {
- whenever(peopleNotificationIdentifier.getPeopleNotificationType(
- entry.sbn, entry.ranking)).thenReturn(TYPE_PERSON)
+ whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry))
+ .thenReturn(TYPE_PERSON)
// only put people notifications in this section
assertTrue(peopleSectioner.isInSection(entry))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 7a0a19bd5424..aff8ade6f1ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -67,6 +67,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.icon.IconBuilder;
import com.android.systemui.statusbar.notification.icon.IconManager;
@@ -77,7 +78,6 @@ import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotifica
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -130,7 +130,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private StatusBarStateController mStatusBarStateController;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupMembershipManager;
+ @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@Mock private FeatureFlags mFeatureFlags;
@Mock private LeakDetector mLeakDetector;
@@ -170,10 +171,10 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
- mGroupManager,
+ mGroupMembershipManager,
new NotificationRankingManager(
() -> mock(NotificationMediaManager.class),
- mGroupManager,
+ mGroupMembershipManager,
mHeadsUpManager,
mock(NotificationFilter.class),
mock(NotificationEntryManagerLogger.class),
@@ -228,7 +229,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
new FakeSystemClock(),
"FOOBAR", "FOOBAR",
mKeyguardBypassController,
- mGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mRowContentBindStage,
mock(NotificationLogger.class),
mHeadsUpManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index df26c5b15505..b952c056c33d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -57,6 +57,7 @@ import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.icon.IconBuilder;
@@ -68,7 +69,6 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import org.mockito.ArgumentCaptor;
@@ -96,7 +96,8 @@ public class NotificationTestHelper {
private final Context mContext;
private final TestableLooper mTestLooper;
private int mId;
- private final NotificationGroupManager mGroupManager;
+ private final NotificationGroupManagerLegacy mGroupMembershipManager;
+ private final NotificationGroupManagerLegacy mGroupExpansionManager;
private ExpandableNotificationRow mRow;
private HeadsUpManagerPhone mHeadsUpManager;
private final NotifBindPipeline mBindPipeline;
@@ -116,13 +117,14 @@ public class NotificationTestHelper {
dependency.injectMockDependency(BubbleController.class);
dependency.injectMockDependency(NotificationShadeWindowController.class);
mStatusBarStateController = mock(StatusBarStateController.class);
- mGroupManager = new NotificationGroupManager(
+ mGroupMembershipManager = new NotificationGroupManagerLegacy(
mStatusBarStateController,
() -> mock(PeopleNotificationIdentifier.class));
+ mGroupExpansionManager = mGroupMembershipManager;
mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
- mock(KeyguardBypassController.class), mock(NotificationGroupManager.class),
+ mock(KeyguardBypassController.class), mock(NotificationGroupManagerLegacy.class),
mock(ConfigurationControllerImpl.class));
- mGroupManager.setHeadsUpManager(mHeadsUpManager);
+ mGroupMembershipManager.setHeadsUpManager(mHeadsUpManager);
mIconManager = new IconManager(
mock(CommonNotifCollection.class),
mock(LauncherApps.class),
@@ -416,7 +418,8 @@ public class NotificationTestHelper {
entry.getKey(),
mock(ExpansionLogger.class),
mock(KeyguardBypassController.class),
- mGroupManager,
+ mGroupMembershipManager,
+ mGroupExpansionManager,
mHeadsUpManager,
mBindStage,
mock(OnExpandClickListener.class),
@@ -434,7 +437,7 @@ public class NotificationTestHelper {
// This would be done as part of onAsyncInflationFinished, but we skip large amounts of
// the callback chain, so we need to make up for not adding it to the group manager
// here.
- mGroupManager.onEntryAdded(entry);
+ mGroupMembershipManager.onEntryAdded(entry);
return row;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 62b741c1938a..5264458cb9cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -47,9 +47,6 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -72,6 +69,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
@@ -80,8 +78,6 @@ import com.android.systemui.statusbar.notification.row.FooterView;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.LeakDetector;
@@ -115,7 +111,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private SysuiStatusBarStateController mBarState;
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationBlockingHelperManager mBlockingHelperManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupMembershipManger;
+ @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@Mock private ExpandHelper mExpandHelper;
@Mock private EmptyShadeView mEmptyShadeView;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@@ -128,6 +125,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private FeatureFlags mFeatureFlags;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
+ @Mock NotificationStackScrollLayoutController mStackScrollLayoutController;
private NotificationEntryManager mEntryManager;
private int mOriginalInterruptionModelSetting;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -159,10 +157,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
- mock(NotificationGroupManager.class),
+ mock(NotificationGroupManagerLegacy.class),
new NotificationRankingManager(
() -> mock(NotificationMediaManager.class),
- mGroupManager,
+ mGroupMembershipManger,
mHeadsUpManager,
mock(NotificationFilter.class),
mock(NotificationEntryManagerLogger.class),
@@ -207,15 +205,19 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mock(NotifPipeline.class),
mEntryManager,
mock(NotifCollection.class),
- mUiEventLoggerFake
+ mUiEventLoggerFake,
+ mGroupMembershipManger,
+ mGroupExpansionManager
);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper);
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelfController(notificationShelfController);
mStackScroller.setStatusBar(mBar);
- mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mStackScrollLayoutController.getNoticationRoundessManager())
+ .thenReturn(mock(NotificationRoundnessManager.class));
+ mStackScroller.setController(mStackScrollLayoutController);
// Stub out functionality that isn't necessary to test.
doNothing().when(mBar)
@@ -224,7 +226,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
anyBoolean(),
anyBoolean(),
anyBoolean());
- doNothing().when(mGroupManager).collapseAllGroups();
+ doNothing().when(mGroupExpansionManager).collapseGroups();
doNothing().when(mExpandHelper).cancelImmediately();
doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
index f5d9fa07fa1c..32c682878c28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
@@ -45,11 +48,11 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -62,6 +65,7 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -114,6 +118,11 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
private StatusBar mStatusBar;
@Mock
private ScrimController mScrimController;
+ @Mock
+ private NotificationGroupManagerLegacy mLegacyGroupManager;
+
+ @Captor
+ ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
private NotificationStackScrollLayoutController mController;
@@ -143,7 +152,9 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
mResources,
mNotificationSwipeHelperBuilder,
mStatusBar,
- mScrimController
+ mScrimController,
+ mLegacyGroupManager,
+ mLegacyGroupManager
);
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
@@ -181,32 +192,49 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
}
@Test
- public void testUpdateEmptyShadeView_notificationsVisible() {
+ public void testUpdateEmptyShadeView_notificationsVisible_zenHiding() {
when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(true);
mController.attach(mNotificationStackScrollLayout);
+ verify(mSysuiStatusBarStateController).addCallback(
+ mStateListenerArgumentCaptor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener =
+ mStateListenerArgumentCaptor.getValue();
- mController.updateEmptyShadeView(true /* visible */);
+ setupShowEmptyShadeViewState(stateListener, true);
+ reset(mNotificationStackScrollLayout);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
true /* visible */,
+
true /* notifVisibleInShade */);
+
+ setupShowEmptyShadeViewState(stateListener, false);
reset(mNotificationStackScrollLayout);
- mController.updateEmptyShadeView(false /* visible */);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
false /* visible */,
true /* notifVisibleInShade */);
}
@Test
- public void testUpdateEmptyShadeView_notificationsHidden() {
+ public void testUpdateEmptyShadeView_notificationsHidden_zenNotHiding() {
when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
mController.attach(mNotificationStackScrollLayout);
+ verify(mSysuiStatusBarStateController).addCallback(
+ mStateListenerArgumentCaptor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener =
+ mStateListenerArgumentCaptor.getValue();
- mController.updateEmptyShadeView(true /* visible */);
+ setupShowEmptyShadeViewState(stateListener, true);
+ reset(mNotificationStackScrollLayout);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
true /* visible */,
false /* notifVisibleInShade */);
+
+ setupShowEmptyShadeViewState(stateListener, false);
reset(mNotificationStackScrollLayout);
- mController.updateEmptyShadeView(false /* visible */);
+ mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
false /* visible */,
false /* notifVisibleInShade */);
@@ -234,15 +262,12 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
public void testOnStatePostChange_verifyIfProfileIsPublic() {
when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true);
- ArgumentCaptor<StatusBarStateController.StateListener> stateListenerArgumentCaptor =
- ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
-
mController.attach(mNotificationStackScrollLayout);
verify(mSysuiStatusBarStateController).addCallback(
- stateListenerArgumentCaptor.capture(), anyInt());
+ mStateListenerArgumentCaptor.capture(), anyInt());
StatusBarStateController.StateListener stateListener =
- stateListenerArgumentCaptor.getValue();
+ mStateListenerArgumentCaptor.getValue();
stateListener.onStatePostChange();
verify(mNotificationStackScrollLayout).updateSensitiveness(false, true);
@@ -299,6 +324,20 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
return argThat(new LogMatcher(category, type));
}
+ private void setupShowEmptyShadeViewState(
+ StatusBarStateController.StateListener statusBarStateListener,
+ boolean toShow) {
+ if (toShow) {
+ statusBarStateListener.onStateChanged(SHADE);
+ mController.setQsExpanded(false);
+ mController.getView().removeAllViews();
+ } else {
+ statusBarStateListener.onStateChanged(KEYGUARD);
+ mController.setQsExpanded(true);
+ mController.getView().addContainerView(mock(ExpandableNotificationRow.class));
+ }
+ }
+
static class LogMatcher implements ArgumentMatcher<LogMaker> {
private int mCategory, mType;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 2239b1b96ac8..57020eb08a7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.AlertingNotificationManagerTest;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -57,7 +58,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest {
private HeadsUpManagerPhone mHeadsUpManager;
- @Mock private NotificationGroupManager mGroupManager;
+ @Mock private NotificationGroupManagerLegacy mGroupManager;
@Mock private View mNotificationShadeWindowView;
@Mock private VisualStabilityManager mVSManager;
@Mock private StatusBar mBar;
@@ -69,7 +70,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest {
private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
TestableHeadsUpManagerPhone(
Context context,
- NotificationGroupManager groupManager,
+ NotificationGroupManagerLegacy groupManager,
VisualStabilityManager vsManager,
StatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 885dff39f7b3..2ece8be8d332 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -42,6 +42,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
@@ -68,7 +69,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
@Rule public MockitoRule rule = MockitoJUnit.rule();
private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper;
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
private HeadsUpManager mHeadsUpManager;
@Mock private NotificationEntryManager mNotificationEntryManager;
@Mock private RowContentBindStage mBindStage;
@@ -88,10 +89,10 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
when(mNotificationEntryManager.getPendingNotificationsIterator())
.thenReturn(mPendingEntries.values());
- mGroupManager = new NotificationGroupManager(
+ mGroupManager = new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class));
- mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
+ mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
when(mBindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
index 5a6f74a4c6aa..0aa009134440 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
@@ -33,6 +33,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -47,11 +48,11 @@ import org.mockito.junit.MockitoRule;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotificationGroupManagerTest extends SysuiTestCase {
+public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
private final NotificationGroupTestHelper mGroupTestHelper =
new NotificationGroupTestHelper(mContext);
@@ -64,7 +65,7 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
}
private void initializeGroupManager() {
- mGroupManager = new NotificationGroupManager(
+ mGroupManager = new NotificationGroupManagerLegacy(
mock(StatusBarStateController.class),
() -> mock(PeopleNotificationIdentifier.class));
mGroupManager.setHeadsUpManager(mHeadsUpManager);
@@ -78,7 +79,7 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
mGroupManager.onEntryAdded(summaryEntry);
mGroupManager.onEntryAdded(childEntry);
- assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.getSbn()));
+ assertTrue(mGroupManager.isOnlyChildInGroup(childEntry));
}
@Test
@@ -90,7 +91,7 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
mGroupManager.onEntryAdded(childEntry);
mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
- assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
+ assertTrue(mGroupManager.isChildInGroup(childEntry));
}
@Test
@@ -102,8 +103,8 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
mGroupManager.onEntryAdded(childEntry);
mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
- assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
- assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
+ assertTrue(mGroupManager.isGroupSummary(summaryEntry));
+ assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry));
}
@Test
@@ -116,7 +117,7 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
mGroupManager.onEntryRemoved(childEntry);
- assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
+ assertFalse(mGroupManager.isChildInGroup(childEntry));
}
@Test
@@ -129,8 +130,8 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
mGroupManager.onEntryRemoved(summaryEntry);
- assertNull(mGroupManager.getGroupSummary(childEntry.getSbn()));
- assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
+ assertNull(mGroupManager.getGroupSummary(childEntry));
+ assertFalse(mGroupManager.isGroupSummary(summaryEntry));
}
@Test
@@ -146,7 +147,7 @@ public class NotificationGroupManagerTest extends SysuiTestCase {
// Child entries that are heads upped should be considered separate groups visually even if
// they are the same group logically
- assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
- assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.getSbn()));
+ assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry));
+ assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 453baa5e16fd..cf64ff2f8cd6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -74,12 +74,12 @@ import com.android.systemui.statusbar.notification.ConversationNotificationManag
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
@@ -118,7 +118,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private NotificationShelfController mNotificationShelfController;
@Mock
- private NotificationGroupManager mGroupManager;
+ private NotificationGroupManagerLegacy mGroupManager;
@Mock
private KeyguardStatusBarView mKeyguardStatusBar;
@Mock
@@ -174,8 +174,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private KeyguardClockSwitch mKeyguardClockSwitch;
private PanelViewController.TouchHandler mTouchHandler;
@Mock
- private ZenModeController mZenModeController;
- @Mock
private ConfigurationController mConfigurationController;
@Mock
private MediaHierarchyManager mMediaHiearchyManager;
@@ -259,16 +257,16 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mKeyguardStateController, mStatusBarStateController, mDozeLog,
mDozeParameters, mCommandQueue, mVibratorHelper,
mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
- mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
+ mMetricsLogger, mActivityManager, mConfigurationController,
flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
mConversationNotificationManager, mMediaHiearchyManager,
mBiometricUnlockController, mStatusBarKeyguardViewManager,
mNotificationStackScrollLayoutController,
- mNotificationAreaController,
- mKeyguardStatusViewComponentFactory);
+ mKeyguardStatusViewComponentFactory,
+ mGroupManager,
+ mNotificationAreaController);
mNotificationPanelViewController.initDependencies(
mStatusBar,
- mGroupManager,
mNotificationShelfController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelViewController.setBar(mPanelBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 2f4511329041..108327341f94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
@@ -27,7 +28,6 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -39,14 +39,13 @@ import androidx.test.filters.SmallTest;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -71,8 +70,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock
private LockPatternUtils mLockPatternUtils;
@Mock
- private KeyguardBouncer mBouncer;
- @Mock
private KeyguardStateController mKeyguardStateController;
@Mock
private StatusBar mStatusBar;
@@ -94,6 +91,13 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
private KeyguardBypassController mBypassController;
@Mock
private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController;
+ @Mock
+ private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
+ @Mock
+ private KeyguardBouncerComponent mKeyguardBouncerComponent;
+ @Mock
+ private KeyguardBouncer mBouncer;
+
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Before
@@ -102,7 +106,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
when(mLockIconContainer.getParent()).thenReturn(mock(ViewGroup.class));
when(mLockIconContainer.animate()).thenReturn(mock(ViewPropertyAnimator.class,
RETURNS_DEEP_STUBS));
- mStatusBarKeyguardViewManager = new TestableStatusBarKeyguardViewManager(
+
+ when(mKeyguardBouncerComponentFactory.build(
+ any(ViewGroup.class),
+ any(KeyguardBouncer.BouncerExpansionCallback.class)))
+ .thenReturn(mKeyguardBouncerComponent);
+ when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer);
+
+ mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(
getContext(),
mViewMediatorCallback,
mLockPatternUtils,
@@ -113,12 +124,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mock(DockManager.class),
mock(NotificationShadeWindowController.class),
mKeyguardStateController,
- mFaceAuthScreenBrightnessController,
- mock(NotificationMediaManager.class));
+ Optional.of(mFaceAuthScreenBrightnessController),
+ mock(NotificationMediaManager.class),
+ mKeyguardBouncerComponentFactory);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
- mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
- mLockIconContainer, mNotificationContainer, mBypassController,
- new FalsingManagerFake());
+ mNotificationPanelView, mBiometrucUnlockController,
+ mLockIconContainer, mNotificationContainer, mBypassController);
mStatusBarKeyguardViewManager.show(null);
}
@@ -267,38 +278,4 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
verify(action).onDismiss();
verify(cancelAction, never()).run();
}
-
- private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
-
- public TestableStatusBarKeyguardViewManager(Context context,
- ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils,
- SysuiStatusBarStateController sysuiStatusBarStateController,
- ConfigurationController configurationController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- NavigationModeController navigationModeController,
- DockManager dockManager,
- NotificationShadeWindowController notificationShadeWindowController,
- KeyguardStateController keyguardStateController,
- FaceAuthScreenBrightnessController faceAuthScreenBrightnessController,
- NotificationMediaManager notificationMediaManager) {
- super(context, callback, lockPatternUtils, sysuiStatusBarStateController,
- configurationController, keyguardUpdateMonitor, navigationModeController,
- dockManager, notificationShadeWindowController, keyguardStateController,
- Optional.of(faceAuthScreenBrightnessController), notificationMediaManager);
- }
-
- @Override
- public void registerStatusBar(StatusBar statusBar, ViewGroup container,
- NotificationPanelViewController notificationPanelViewController,
- BiometricUnlockController fingerprintUnlockController,
- DismissCallbackRegistry dismissCallbackRegistry,
- ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController, FalsingManager falsingManager) {
- super.registerStatusBar(statusBar, container, notificationPanelViewController,
- fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController, falsingManager);
- mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 3f631b1f6282..792637d8479b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -67,9 +67,9 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -122,8 +122,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private FeatureFlags mFeatureFlags;
@Mock
private NotifPipeline mNotifPipeline;
- @Mock
- private NotifCollection mNotifCollection;
@Mock
private ActivityIntentHelper mActivityIntentHelper;
@@ -187,7 +185,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mUiBgExecutor,
mEntryManager,
mNotifPipeline,
- mNotifCollection,
mock(HeadsUpManagerPhone.class),
mActivityStarter,
mClickNotifier,
@@ -198,7 +195,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mBubbleController,
() -> mAssistManager,
mRemoteInputManager,
- mock(NotificationGroupManager.class),
+ mock(NotificationGroupManagerLegacy.class),
mock(NotificationLockscreenUserManager.class),
mShadeController,
mKeyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index bf2bd38638ff..6fbbee22a73c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -72,7 +73,7 @@ public class StatusBarRemoteInputCallbackTest extends SysuiTestCase {
mNotificationLockscreenUserManager);
mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
- mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
+ mock(NotificationGroupManagerLegacy.class), mNotificationLockscreenUserManager,
mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager,
mActivityStarter, mShadeController, new CommandQueue(mContext),
mock(ActionClickLogger.class)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 87aee3fd4794..5143596f0214 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -220,7 +220,6 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NetworkController mNetworkController;
@Mock private VibratorHelper mVibratorHelper;
@Mock private BubbleController mBubbleController;
- @Mock private NotificationGroupManager mGroupManager;
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@@ -376,7 +375,6 @@ public class StatusBarTest extends SysuiTestCase {
mStatusBarStateController,
mVibratorHelper,
mBubbleController,
- mGroupManager,
mVisualStabilityManager,
mDeviceProvisionedController,
mNavigationBarController,
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
index 070626be9f80..c70dfcc93e49 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java
@@ -256,6 +256,7 @@ class EventDispatcher {
return actionMasked;
}
}
+
/**
* Sends down events to the view hierarchy for all pointers which are not already being
* delivered i.e. pointers that are not yet injected.
@@ -285,6 +286,74 @@ class EventDispatcher {
}
/**
+ * Sends down events to the view hierarchy for all pointers which are not already being
+ * delivered with original down location. i.e. pointers that are not yet injected.
+ *
+ * @param prototype The prototype from which to create the injected events.
+ * @param policyFlags The policy flags associated with the event.
+ */
+ void sendDownForAllNotInjectedPointersWithOriginalDown(MotionEvent prototype, int policyFlags) {
+ // Inject the injected pointers.
+ int pointerIdBits = 0;
+ final int pointerCount = prototype.getPointerCount();
+ final MotionEvent event = computeEventWithOriginalDown(prototype);
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = prototype.getPointerId(i);
+ // Do not send event for already delivered pointers.
+ if (!mState.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(
+ event,
+ action,
+ mState.getLastReceivedEvent(),
+ pointerIdBits,
+ policyFlags);
+ }
+ }
+ }
+
+ private MotionEvent computeEventWithOriginalDown(MotionEvent prototype) {
+ final int pointerCount = prototype.getPointerCount();
+ if (pointerCount != mState.getReceivedPointerTracker().getReceivedPointerDownCount()) {
+ Slog.w(LOG_TAG, "The pointer count doesn't match the received count.");
+ return MotionEvent.obtain(prototype);
+ }
+ MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointerCount];
+ MotionEvent.PointerProperties[] properties =
+ new MotionEvent.PointerProperties[pointerCount];
+ for (int i = 0; i < pointerCount; ++i) {
+ final int pointerId = prototype.getPointerId(i);
+ final float x = mState.getReceivedPointerTracker().getReceivedPointerDownX(pointerId);
+ final float y = mState.getReceivedPointerTracker().getReceivedPointerDownY(pointerId);
+ coords[i] = new MotionEvent.PointerCoords();
+ coords[i].x = x;
+ coords[i].y = y;
+ properties[i] = new MotionEvent.PointerProperties();
+ properties[i].id = pointerId;
+ properties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;
+ }
+ MotionEvent event =
+ MotionEvent.obtain(
+ prototype.getDownTime(),
+ prototype.getEventTime(),
+ prototype.getAction(),
+ pointerCount,
+ properties,
+ coords,
+ prototype.getMetaState(),
+ prototype.getButtonState(),
+ prototype.getXPrecision(),
+ prototype.getYPrecision(),
+ prototype.getDeviceId(),
+ prototype.getEdgeFlags(),
+ prototype.getSource(),
+ prototype.getFlags());
+ return event;
+ }
+
+ /**
+ *
* Sends up events to the view hierarchy for all pointers which are already being delivered i.e.
* pointers that are injected.
*
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
index 07e82111d4e5..5b46cb4ab378 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
@@ -294,7 +294,7 @@ class MultiFingerSwipe extends GestureMatcher {
+ Float.toString(mGestureDetectionThresholdPixels));
}
if (getState() == STATE_CLEAR) {
- if (moveDelta < mTouchSlop) {
+ if (moveDelta < (mTargetFingerCount * mTouchSlop)) {
// This still counts as a touch not a swipe.
continue;
} else if (mStrokeBuffers[pointerIndex].size() == 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index adccf6cfc99c..8305be393ab1 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -608,7 +608,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
mReceivedPointerTracker.getReceivedPointerDownY(id)
- rawEvent.getY(index);
final double moveDelta = Math.hypot(deltaX, deltaY);
- if (moveDelta < mTouchSlop) {
+ if (moveDelta < (2 * mTouchSlop)) {
return;
}
}
@@ -651,7 +651,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
Slog.d(LOG_TAG, "Three-finger edge swipe detected.");
}
mState.startDelegating();
- mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
+ if (mState.isTouchExploring()) {
+ mDispatcher.sendDownForAllNotInjectedPointers(event,
+ policyFlags);
+ } else {
+ mDispatcher.sendDownForAllNotInjectedPointersWithOriginalDown(
+ event, policyFlags);
+ }
}
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 3ee5b28ee338..7d6067c8e1da 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -176,7 +176,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
Slog.i(LOG_TAG, "onDestroy(); delayed = "
+ mDetectingState.toString());
}
- mWindowMagnificationMgr.disableWindowMagnifier(mDisplayId, true);
+ mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true);
resetToDetectState();
}
@@ -211,14 +211,14 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
final float scale = MathUtils.constrain(
mWindowMagnificationMgr.getPersistedScale(),
MIN_SCALE, MAX_SCALE);
- mWindowMagnificationMgr.enableWindowMagnifier(mDisplayId, scale, centerX, centerY);
+ mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY);
}
private void disableWindowMagnifier() {
if (DEBUG_ALL) {
Slog.i(LOG_TAG, "disableWindowMagnifier()");
}
- mWindowMagnificationMgr.disableWindowMagnifier(mDisplayId, false);
+ mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, false);
}
private void toggleMagnification(float centerX, float centerY) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index ed2b26f24478..ecbece6f1f27 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -73,7 +73,7 @@ public class WindowMagnificationManager implements
public void onReceive(Context context, Intent intent) {
final int displayId = context.getDisplayId();
removeMagnificationButton(displayId);
- disableWindowMagnification(displayId);
+ disableWindowMagnification(displayId, false);
}
};
@@ -136,10 +136,10 @@ public class WindowMagnificationManager implements
/**
* Requests {@link IWindowMagnificationConnection} through
* {@link StatusBarManagerInternal#requestWindowMagnificationConnection(boolean)} and
- * destroys all window magnifiers if necessary.
+ * destroys all window magnifications if necessary.
*
* @param connect {@code true} if needs connection, otherwise set the connection to null and
- * destroy all window magnifiers.
+ * destroy all window magnifications.
* @return {@code true} if {@link IWindowMagnificationConnection} state is going to change.
*/
public boolean requestConnection(boolean connect) {
@@ -171,7 +171,7 @@ public class WindowMagnificationManager implements
private void disableAllWindowMagnifiers() {
for (int i = 0; i < mWindowMagnifiers.size(); i++) {
final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i);
- magnifier.disable();
+ magnifier.disableWindowMagnificationInternal();
}
mWindowMagnifiers.clear();
}
@@ -187,12 +187,12 @@ public class WindowMagnificationManager implements
@Override
public boolean processScroll(int displayId, float distanceX, float distanceY) {
- moveWindowMagnifier(displayId, -distanceX, -distanceY);
+ moveWindowMagnification(displayId, -distanceX, -distanceY);
return /* event consumed: */ true;
}
/**
- * Scales the magnified region on the specified display if the window magnifier is enabled.
+ * Scales the magnified region on the specified display if the window magnifier is initiated.
*
* @param displayId The logical display id.
* @param scale The target scale, must be >= 1
@@ -209,7 +209,7 @@ public class WindowMagnificationManager implements
}
/**
- * Enables the window magnifier with specified center and scale on the specified display.
+ * Enables window magnification with specified center and scale on the specified display.
* @param displayId The logical display id.
* @param scale The target scale, must be >= 1.
* @param centerX The screen-relative X coordinate around which to center,
@@ -217,29 +217,29 @@ public class WindowMagnificationManager implements
* @param centerY The screen-relative Y coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
*/
- void enableWindowMagnifier(int displayId, float scale, float centerX, float centerY) {
+ void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
magnifier = createWindowMagnifier(displayId);
}
- magnifier.enable(scale, centerX, centerY);
+ magnifier.enableWindowMagnificationInternal(scale, centerX, centerY);
}
}
/**
- * Disables the window magnifier on the specified display.
+ * Disables window magnification on the specified display.
*
* @param displayId The logical display id.
* @param clear {@true} Clears the state of the window magnifier
*/
- void disableWindowMagnifier(int displayId, boolean clear) {
+ void disableWindowMagnification(int displayId, boolean clear) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
return;
}
- magnifier.disable();
+ magnifier.disableWindowMagnificationInternal();
if (clear) {
mWindowMagnifiers.delete(displayId);
}
@@ -264,10 +264,10 @@ public class WindowMagnificationManager implements
}
/**
- * Indicates whether this window magnifier is enabled on specified display.
+ * Indicates whether window magnification is enabled on specified display.
*
* @param displayId The logical display id.
- * @return {@code true} if the window magnifier is enabled.
+ * @return {@code true} if the window magnification is enabled.
*/
boolean isWindowMagnifierEnabled(int displayId) {
synchronized (mLock) {
@@ -323,7 +323,7 @@ public class WindowMagnificationManager implements
}
/**
- * Moves the window magnifier with specified offset.
+ * Moves window magnification on the specified display with the specified offset.
*
* @param displayId The logical display id.
* @param offsetX the amount in pixels to offset the region in the X direction, in current
@@ -331,7 +331,7 @@ public class WindowMagnificationManager implements
* @param offsetY the amount in pixels to offset the region in the Y direction, in current
* screen pixels.
*/
- void moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
+ void moveWindowMagnification(int displayId, float offsetX, float offsetY) {
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
@@ -425,7 +425,8 @@ public class WindowMagnificationManager implements
}
/**
- * A class to manipulate the window magnifier and contains the relevant information.
+ * A class manipulates window magnification per display and contains the magnification
+ * information.
*/
private static class WindowMagnifier {
@@ -434,7 +435,7 @@ public class WindowMagnificationManager implements
private boolean mEnabled;
private final WindowMagnificationManager mWindowMagnificationManager;
- //Records the bounds of window magnifier.
+ //Records the bounds of window magnification.
private final Rect mBounds = new Rect();
//The magnified bounds on the screen.
private final Rect mSourceBounds = new Rect();
@@ -444,12 +445,12 @@ public class WindowMagnificationManager implements
}
@GuardedBy("mLock")
- void enable(float scale, float centerX, float centerY) {
+ void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
if (mEnabled) {
return;
}
final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
- if (mWindowMagnificationManager.enableWindowMagnification(mDisplayId, normScale,
+ if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,
centerX, centerY)) {
mScale = normScale;
mEnabled = true;
@@ -457,8 +458,9 @@ public class WindowMagnificationManager implements
}
@GuardedBy("mLock")
- void disable() {
- if (mEnabled && mWindowMagnificationManager.disableWindowMagnification(mDisplayId)) {
+ void disableWindowMagnificationInternal() {
+ if (mEnabled && mWindowMagnificationManager.disableWindowMagnificationInternal(
+ mDisplayId)) {
mEnabled = false;
}
}
@@ -519,7 +521,7 @@ public class WindowMagnificationManager implements
}
}
- private boolean enableWindowMagnification(int displayId, float scale, float centerX,
+ private boolean enableWindowMagnificationInternal(int displayId, float scale, float centerX,
float centerY) {
return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification(
displayId, scale, centerX, centerY);
@@ -529,7 +531,7 @@ public class WindowMagnificationManager implements
return mConnectionWrapper != null && mConnectionWrapper.setScale(displayId, scale);
}
- private boolean disableWindowMagnification(int displayId) {
+ private boolean disableWindowMagnificationInternal(int displayId) {
return mConnectionWrapper != null && mConnectionWrapper.disableWindowMagnification(
displayId);
}
diff --git a/services/companion/TEST_MAPPING b/services/companion/TEST_MAPPING
new file mode 100644
index 000000000000..63f54fa35158
--- /dev/null
+++ b/services/companion/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsOsTestCases",
+ "options": [
+ {
+ "include-filter": "android.os.cts.CompanionDeviceManagerTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 35e88eb804cb..7d81d412e369 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2114,7 +2114,7 @@ public class AccountManagerService
* Owner or system user account was renamed, rename the account for
* those users with which the account was shared.
*/
- List<UserInfo> users = getUserManager().getUsers(true);
+ List<UserInfo> users = getUserManager().getAliveUsers();
for (UserInfo user : users) {
if (user.isRestricted()
&& (user.restrictedProfileParentId == parentUserId)) {
@@ -2373,7 +2373,7 @@ public class AccountManagerService
int parentUserId = accounts.userId;
if (canHaveProfile(parentUserId)) {
// Remove from any restricted profiles that are sharing this account.
- List<UserInfo> users = getUserManager().getUsers(true);
+ List<UserInfo> users = getUserManager().getAliveUsers();
for (UserInfo user : users) {
if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) {
removeSharedAccountAsUser(account, user.id, callingUid);
@@ -4267,7 +4267,7 @@ public class AccountManagerService
*/
@NonNull
public AccountAndUser[] getAllAccounts() {
- final List<UserInfo> users = getUserManager().getUsers(true);
+ final List<UserInfo> users = getUserManager().getAliveUsers();
final int[] userIds = new int[users.size()];
for (int i = 0; i < userIds.length; i++) {
userIds[i] = users.get(i).id;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2d803437beb9..1502b7e0355c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17144,8 +17144,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public int checkContentProviderUriPermission(Uri uri, int userId,
int callingUid, int modeFlags) {
- return mCpHelper.checkContentProviderUriPermission(uri,
- userId, callingUid, modeFlags);
+ return mCpHelper.checkContentProviderUriPermission(uri, userId, callingUid, modeFlags);
}
@Override
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index bfba4afcd4e4..05a731d2b50b 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -198,22 +198,10 @@ public class ContentProviderHelper {
if (providerRunning) {
cpi = cpr.info;
- String msg;
if (r != null && cpr.canRunHere(r)) {
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup "
- + cpr.name.flattenToShortString()
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
+ cpr.name.flattenToShortString(), startTime);
// This provider has been published or is in the process
// of being published... but it is also allowed to run
@@ -234,26 +222,14 @@ public class ContentProviderHelper {
} catch (RemoteException e) {
}
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException(
- "Content provider lookup " + cpr.name.flattenToShortString()
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
+ cpr.name.flattenToShortString(), startTime);
final long origId = Binder.clearCallingIdentity();
checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
- // In this case the provider instance already exists, so we can
- // return it right away.
+ // In this case the provider instance already exists so we can return it right away.
conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
stable, true, startTime, mService.mProcessList);
@@ -328,19 +304,8 @@ public class ContentProviderHelper {
cpi.applicationInfo = mService.getAppInfoForUser(cpi.applicationInfo, userId);
checkTime(startTime, "getContentProviderImpl: got app info for user");
- String msg;
- if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup " + name
- + " failed: association not allowed with package " + msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: before checkContentProviderPermission");
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
- != null) {
- throw new SecurityException(msg);
- }
- checkTime(startTime,
- "getContentProviderImpl: after checkContentProviderPermission");
+ checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, !singleton,
+ name, startTime);
if (!mService.mProcessesReady && !cpi.processName.equals("system")) {
// If this content provider does not run in the system
@@ -352,10 +317,12 @@ public class ContentProviderHelper {
// If system providers are not installed yet we aggressively crash to avoid
// creating multiple instance of these providers and then bad things happen!
- if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp()
- && "system".equals(cpi.processName)) {
- throw new IllegalStateException("Cannot access system provider: '"
- + cpi.authority + "' before system providers are installed!");
+ synchronized (this) {
+ if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp()
+ && "system".equals(cpi.processName)) {
+ throw new IllegalStateException("Cannot access system provider: '"
+ + cpi.authority + "' before system providers are installed!");
+ }
}
// Make sure that the user who owns this provider is running. If not,
@@ -605,6 +572,23 @@ public class ContentProviderHelper {
return cpr.newHolder(conn, false);
}
+ private void checkAssociationAndPermissionLocked(ProcessRecord callingApp, ProviderInfo cpi,
+ int callingUid, int userId, boolean checkUser, String cprName, long startTime) {
+ String msg;
+ if ((msg = checkContentProviderAssociation(callingApp, callingUid, cpi)) != null) {
+ throw new SecurityException("Content provider lookup " + cprName
+ + " failed: association not allowed with package " + msg);
+ }
+ checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
+ if ((msg = checkContentProviderPermission(
+ cpi, Binder.getCallingPid(), Binder.getCallingUid(), userId, checkUser,
+ callingApp != null ? callingApp.toString() : null))
+ != null) {
+ throw new SecurityException(msg);
+ }
+ checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
+ }
+
void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
if (providers == null) {
return;
@@ -623,7 +607,7 @@ public class ContentProviderHelper {
}
final long origId = Binder.clearCallingIdentity();
-
+ boolean providersPublished = false;
for (int i = 0, size = providers.size(); i < size; i++) {
ContentProviderHolder src = providers.get(i);
if (src == null || src.info == null || src.provider == null) {
@@ -636,6 +620,7 @@ public class ContentProviderHelper {
if (DEBUG_MU) {
Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
}
+ providersPublished = true;
ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
mProviderMap.putProviderByClass(comp, dst);
@@ -673,8 +658,19 @@ public class ContentProviderHelper {
dst.onProviderPublishStatusLocked(true);
}
dst.mRestartCount = 0;
+ }
+
+ // update the app's oom adj value and each provider's usage stats
+ if (providersPublished) {
mService.updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
- maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority);
+ for (int i = 0, size = providers.size(); i < size; i++) {
+ ContentProviderHolder src = providers.get(i);
+ if (src == null || src.info == null || src.provider == null) {
+ continue;
+ }
+ maybeUpdateProviderUsageStatsLocked(r,
+ src.info.packageName, src.info.authority);
+ }
}
Binder.restoreCallingIdentity(origId);
@@ -997,17 +993,19 @@ public class ContentProviderHelper {
+ "; expected to find a valid ContentProvider for this authority";
}
+ final int callingPid = Binder.getCallingPid();
ProcessRecord r;
+ final String appName;
synchronized (mService.mPidsSelfLocked) {
- r = mService.mPidsSelfLocked.get(Binder.getCallingPid());
- }
- if (r == null) {
- return "Failed to find PID " + Binder.getCallingPid();
+ r = mService.mPidsSelfLocked.get(callingPid);
+ if (r == null) {
+ return "Failed to find PID " + callingPid;
+ }
+ appName = r.toString();
}
- synchronized (mService) {
- return checkContentProviderPermissionLocked(cpi, r, userId, true);
- }
+ return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(),
+ userId, true, appName);
}
int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
@@ -1163,13 +1161,14 @@ public class ContentProviderHelper {
}
}
}
- if (providers != null) {
- mService.mSystemThread.installSystemProviders(providers);
- }
- synchronized (mService) {
+ synchronized (this) {
+ if (providers != null) {
+ mService.mSystemThread.installSystemProviders(providers);
+ }
mSystemProvidersInstalled = true;
}
+
mService.mConstants.start(mService.mContext.getContentResolver());
mService.mCoreSettingsObserver = new CoreSettingsObserver(mService);
mService.mActivityTaskManager.installSystemProviders();
@@ -1305,10 +1304,8 @@ public class ContentProviderHelper {
* given {@link ProviderInfo}. Final permission checking is always done
* in {@link ContentProvider}.
*/
- private String checkContentProviderPermissionLocked(ProviderInfo cpi, ProcessRecord r,
- int userId, boolean checkUser) {
- final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
- final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
+ private String checkContentProviderPermission(ProviderInfo cpi, int callingPid, int callingUid,
+ int userId, boolean checkUser, String appName) {
boolean checkedGrants = false;
if (checkUser) {
// Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -1376,8 +1373,8 @@ public class ContentProviderHelper {
suffix = " requires " + cpi.readPermission + " or " + cpi.writePermission;
}
final String msg = "Permission Denial: opening provider " + cpi.name
- + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
- + ", uid=" + callingUid + ")" + suffix;
+ + " from " + (appName != null ? appName : "(null)")
+ + " (pid=" + callingPid + ", uid=" + callingUid + ")" + suffix;
Slog.w(TAG, msg);
return msg;
}
@@ -1398,18 +1395,17 @@ public class ContentProviderHelper {
}
ProviderInfo getProviderInfoLocked(String authority, @UserIdInt int userId, int pmFlags) {
- ProviderInfo pi = null;
ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
if (cpr != null) {
- pi = cpr.info;
+ return cpr.info;
} else {
try {
- pi = AppGlobals.getPackageManager().resolveContentProvider(
+ return AppGlobals.getPackageManager().resolveContentProvider(
authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userId);
} catch (RemoteException ex) {
+ return null;
}
}
- return pi;
}
private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
@@ -1419,7 +1415,6 @@ public class ContentProviderHelper {
return;
}
-
UserState userState = mService.mUserController.getStartedUserState(app.userId);
if (userState == null) return;
final long now = SystemClock.elapsedRealtime();
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d59780d7f609..3f29eb5636ea 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6528,8 +6528,8 @@ public class AudioService extends IAudioService.Stub
CHECK_MODE_FOR_UID_PERIOD_MS);
break;
}
- // For now just log the fact that an app is hogging the audio mode.
- // TODO(b/160260850): remove abusive app from audio mode stack.
+ setModeInt(AudioSystem.MODE_NORMAL, h.getBinder(), h.getPid(), h.getUid(),
+ h.isPrivileged(), "MSG_CHECK_MODE_FOR_UID");
mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid()));
}
break;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index 32bb2db77ddc..d9c62df3f3ea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -29,7 +29,6 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
-import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Build;
@@ -383,7 +382,7 @@ class Face10 implements IHwBinder.DeathRecipient {
// is safe because authenticatorIds only change when A) new template has been enrolled,
// or B) all templates are removed.
mHandler.post(() -> {
- for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+ for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
final int targetUserId = user.id;
if (!mAuthenticatorIds.containsKey(targetUserId)) {
scheduleUpdateActiveUserWithoutHandler(targetUserId);
@@ -480,7 +479,8 @@ class Face10 implements IHwBinder.DeathRecipient {
* notifying the previous caller that the interrupting operation is complete (e.g. the
* interrupting client's challenge has been revoked, so that the interrupted client can
* start retry logic if necessary). See
- * {@link FaceManager.GenerateChallengeCallback#onChallengeInterruptFinished(int)}
+ * {@link
+ *android.hardware.face.FaceManager.GenerateChallengeCallback#onChallengeInterruptFinished(int)}
* The only case of conflicting challenges is currently resetLockout --> enroll. So, the second
* option seems better as it prioritizes the new operation, which is user-facing.
*/
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
index c5c28227fd24..3754bd748781 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Fingerprint21.java
@@ -440,7 +440,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
// is safe because authenticatorIds only change when A) new template has been enrolled,
// or B) all templates are removed.
mHandler.post(() -> {
- for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+ for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
final int targetUserId = user.id;
if (!mAuthenticatorIds.containsKey(targetUserId)) {
scheduleUpdateActiveUserWithoutHandler(targetUserId);
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index a75a80a606eb..4c63eb488118 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -174,7 +174,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
- List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
+ List<UserInfo> users = mUserManager.getAliveUsers();
if (users != null) {
for (UserInfo user : users) {
mUsers.add(user.id);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 5484bfca5851..7175489614ea 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1463,7 +1463,7 @@ public class Vpn {
final long token = Binder.clearCallingIdentity();
List<UserInfo> users;
try {
- users = UserManager.get(mContext).getUsers(true);
+ users = UserManager.get(mContext).getAliveUsers();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index ec12a971e445..b33aa0a6fad3 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -367,7 +367,7 @@ public class SyncManager {
}
private void removeStaleAccounts() {
- for (UserInfo user : mUserManager.getUsers(true)) {
+ for (UserInfo user : mUserManager.getAliveUsers()) {
// Skip any partially created/removed users
if (user.partial) continue;
Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
@@ -777,7 +777,7 @@ public class SyncManager {
if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) {
return;
}
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
UserHandle userHandle = users.get(i).getUserHandle();
diff --git a/services/core/java/com/android/server/inputmethod/TEST_MAPPING b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
new file mode 100644
index 000000000000..0ccd75dcbdce
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/view/inputmethod"
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index e9a05a8aa16c..715e41c62a05 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -746,7 +746,7 @@ class LockSettingsStorage {
public void dump(IndentingPrintWriter pw) {
final UserManager um = UserManager.get(mContext);
- for (UserInfo user : um.getUsers(false)) {
+ for (UserInfo user : um.getUsers()) {
File userPath = getSyntheticPasswordDirectoryForUser(user.id);
pw.println(String.format("User %d [%s]:", user.id, userPath.getAbsolutePath()));
pw.increaseIndent();
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index a604625460a7..74b7bd76b047 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1554,7 +1554,7 @@ abstract public class ManagedServices {
if (!isEnabledForCurrentProfiles()) {
return false;
}
- return this.userid == userId;
+ return userId == USER_ALL || userId == this.userid;
}
public boolean enabledAndUserMatches(int nid) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 04658555f22b..12419a9fcafa 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -262,7 +262,6 @@ import com.android.server.EventLogTags;
import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.UiThread;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -966,8 +965,7 @@ public class NotificationManagerService extends SystemService {
nv.recycle();
}
reportUserInteraction(r);
- mAssistants.notifyAssistantActionClicked(
- r.getSbn(), actionIndex, action, generatedByAssistant);
+ mAssistants.notifyAssistantActionClicked(r.getSbn(), action, generatedByAssistant);
}
}
@@ -8629,12 +8627,25 @@ public class NotificationManagerService extends SystemService {
ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
}
- private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
+ @VisibleForTesting
+ boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
if (!listener.enabledAndUserMatches(sbn.getUserId())) {
return false;
}
- // TODO: remove this for older listeners.
- return true;
+ return isInteractionVisibleToListener(listener, sbn.getUserId());
+ }
+
+ /**
+ * Returns whether the given assistant should be informed about interactions on the given user.
+ *
+ * Normally an assistant would be able to see all interactions on the current user and any
+ * associated profiles because they are notification listeners, but since NASes have one
+ * instance per user, we want to filter out interactions that are not for the user that the
+ * given NAS is bound in.
+ */
+ private boolean isInteractionVisibleToListener(ManagedServiceInfo info, int userId) {
+ boolean isAssistantService = mAssistants.isServiceTokenValidLocked(info.service);
+ return !isAssistantService || info.isSameUser(userId);
}
private boolean isPackageSuspendedForUser(String pkg, int uid) {
@@ -8856,8 +8867,6 @@ public class NotificationManagerService extends SystemService {
}
protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) {
- // There should be only one, but it's a list, so while we enforce
- // singularity elsewhere, we keep it general here, to avoid surprises.
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
ArrayList<String> keys = new ArrayList<>(records.size());
for (NotificationRecord r : records) {
@@ -8875,6 +8884,8 @@ public class NotificationManagerService extends SystemService {
}
protected void onPanelRevealed(int items) {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the panel
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
mHandler.post(() -> {
final INotificationListener assistant = (INotificationListener) info.service;
@@ -8888,6 +8899,8 @@ public class NotificationManagerService extends SystemService {
}
protected void onPanelHidden() {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the panel
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
mHandler.post(() -> {
final INotificationListener assistant = (INotificationListener) info.service;
@@ -8976,7 +8989,7 @@ public class NotificationManagerService extends SystemService {
}
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationVisibilityChanged(key, isVisible);
@@ -8994,7 +9007,7 @@ public class NotificationManagerService extends SystemService {
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationExpansionChanged(key, isUserAction, isExpanded);
@@ -9010,7 +9023,7 @@ public class NotificationManagerService extends SystemService {
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationDirectReply(key);
@@ -9026,7 +9039,7 @@ public class NotificationManagerService extends SystemService {
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onSuggestedReplySent(
@@ -9043,12 +9056,12 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
void notifyAssistantActionClicked(
- final StatusBarNotification sbn, int actionIndex, Notification.Action action,
+ final StatusBarNotification sbn, Notification.Action action,
boolean generatedByAssistant) {
final String key = sbn.getKey();
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onActionClicked(
@@ -9072,7 +9085,7 @@ public class NotificationManagerService extends SystemService {
final StatusBarNotification sbn, final String snoozeCriterionId) {
notifyAssistantLocked(
sbn,
- false /* sameUserOnly */,
+ true /* sameUserOnly */,
(assistant, sbnHolder) -> {
try {
assistant.onNotificationSnoozedUntilContext(
@@ -9129,7 +9142,7 @@ public class NotificationManagerService extends SystemService {
}
protected void resetDefaultAssistantsIfNecessary() {
- final List<UserInfo> activeUsers = mUm.getUsers(true);
+ final List<UserInfo> activeUsers = mUm.getAliveUsers();
for (UserInfo userInfo : activeUsers) {
int userId = userInfo.getUserHandle().getIdentifier();
if (!hasUserSet(userId)) {
@@ -9293,10 +9306,12 @@ public class NotificationManagerService extends SystemService {
}
public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+ // send to all currently bounds NASes since notifications from both users will appear in
+ // the status bar
for (final ManagedServiceInfo info : getServices()) {
mHandler.post(() -> {
final INotificationListener listener = (INotificationListener) info.service;
- try {
+ try {
listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
} catch (RemoteException ex) {
Slog.e(TAG, "unable to notify listener "
@@ -9470,7 +9485,8 @@ public class NotificationManagerService extends SystemService {
&& changedHiddenNotifications.size() > 0;
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
@@ -9489,12 +9505,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRankingUpdate update = makeRankingUpdateLocked(
serviceInfo);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRankingUpdate(serviceInfo, update);
- }
- });
+ mHandler.post(() -> notifyRankingUpdate(serviceInfo, update));
}
}
}
@@ -9502,15 +9513,11 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
public void notifyListenerHintsChangedLocked(final int hints) {
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyListenerHintsChanged(serviceInfo, hints);
- }
- });
+ mHandler.post(() -> notifyListenerHintsChanged(serviceInfo, hints));
}
}
@@ -9562,15 +9569,12 @@ public class NotificationManagerService extends SystemService {
public void notifyInterruptionFilterChanged(final int interruptionFilter) {
for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ if (!serviceInfo.isEnabledForCurrentProfiles() || !isInteractionVisibleToListener(
+ serviceInfo, ActivityManager.getCurrentUser())) {
continue;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyInterruptionFilterChanged(serviceInfo, interruptionFilter);
- }
- });
+ mHandler.post(
+ () -> notifyInterruptionFilterChanged(serviceInfo, interruptionFilter));
}
}
@@ -9579,15 +9583,16 @@ public class NotificationManagerService extends SystemService {
if (channel == null) {
return;
}
- for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ for (final ManagedServiceInfo info : getServices()) {
+ if (!info.enabledAndUserMatches(UserHandle.getCallingUserId())
+ || !isInteractionVisibleToListener(info, UserHandle.getCallingUserId())) {
continue;
}
BackgroundThread.getHandler().post(() -> {
- if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
+ if (info.isSystem || hasCompanionDevice(info)) {
notifyNotificationChannelChanged(
- serviceInfo, pkg, user, channel, modificationType);
+ info, pkg, user, channel, modificationType);
}
});
}
@@ -9599,15 +9604,16 @@ public class NotificationManagerService extends SystemService {
if (group == null) {
return;
}
- for (final ManagedServiceInfo serviceInfo : getServices()) {
- if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ for (final ManagedServiceInfo info : getServices()) {
+ if (!info.enabledAndUserMatches(UserHandle.getCallingUserId())
+ || !isInteractionVisibleToListener(info, UserHandle.getCallingUserId())) {
continue;
}
BackgroundThread.getHandler().post(() -> {
- if (serviceInfo.isSystem || hasCompanionDevice(serviceInfo)) {
+ if (info.isSystem || hasCompanionDevice(info)) {
notifyNotificationChannelGroupChanged(
- serviceInfo, pkg, user, group, modificationType);
+ info, pkg, user, group, modificationType);
}
});
}
@@ -9626,9 +9632,6 @@ public class NotificationManagerService extends SystemService {
private void notifyRemoved(ManagedServiceInfo info, StatusBarNotification sbn,
NotificationRankingUpdate rankingUpdate, NotificationStats stats, int reason) {
- if (!info.enabledAndUserMatches(sbn.getUserId())) {
- return;
- }
final INotificationListener listener = (INotificationListener) info.service;
StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index a4debc16493a..d7a1ba2a93d4 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -288,7 +288,7 @@ public final class OverlayManagerService extends SystemService {
private void initIfNeeded() {
final UserManager um = getContext().getSystemService(UserManager.class);
- final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
+ final List<UserInfo> users = um.getAliveUsers();
synchronized (mLock) {
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 4b246c3b330c..162bfee8848d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -743,9 +743,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mStagingManager.createSession(session);
}
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionCreated(session.sessionId, session.userId);
- }
+ mCallbacks.notifySessionCreated(session.sessionId, session.userId);
+
writeSessionsAsync();
return sessionId;
}
@@ -1355,25 +1354,18 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
class InternalCallback {
public void onSessionBadgingChanged(PackageInstallerSession session) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
- }
-
+ mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
writeSessionsAsync();
}
public void onSessionActiveChanged(PackageInstallerSession session, boolean active) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId,
- active);
- }
+ mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId,
+ active);
}
public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId,
- progress);
- }
+ mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId,
+ progress);
}
public void onStagedSessionChanged(PackageInstallerSession session) {
@@ -1389,17 +1381,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
public void onSessionFinished(final PackageInstallerSession session, boolean success) {
- if ((session.params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
- }
+ mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
mInstallHandler.post(new Runnable() {
@Override
public void run() {
- if (session.isStaged()) {
- if (!success) {
- mStagingManager.abortSession(session);
- }
+ if (session.isStaged() && !success) {
+ mStagingManager.abortSession(session);
}
synchronized (mSessions) {
if (!session.isStaged() || !success) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ed62362b04fb..4e429cf362b5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3306,8 +3306,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// Send broadcast to default launcher only if it's a new install
// TODO(b/144270665): Secure the usage of this broadcast.
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
- if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()
- && (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
+ if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bf01fd314207..ffd23788223e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13882,7 +13882,7 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean isCallerOwner = isCallerDeviceOrProfileOwner(userId);
final long callingId = Binder.clearCallingIdentity();
try {
- final String activeLauncherPackageName = getActiveLauncherPackageName(userId);
+ final String activeLauncherPackageName = mPermissionManager.getDefaultHome(userId);
final String dialerPackageName = mPermissionManager.getDefaultDialer(userId);
for (int i = 0; i < packageNames.length; i++) {
canSuspend[i] = false;
@@ -13958,18 +13958,6 @@ public class PackageManagerService extends IPackageManager.Stub
return canSuspend;
}
- private String getActiveLauncherPackageName(int userId) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- ResolveInfo resolveInfo = resolveIntent(
- intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- PackageManager.MATCH_DEFAULT_ONLY,
- userId);
-
- return resolveInfo == null ? null : resolveInfo.activityInfo.packageName;
- }
-
@Override
public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
mContext.enforceCallingOrSelfPermission(
@@ -14553,13 +14541,11 @@ public class PackageManagerService extends IPackageManager.Stub
Log.v(TAG, "restoreAndPostInstall userId=" + userId + " package=" + res.pkg);
}
- // A restore should be performed at this point if (a) the install
- // succeeded, (b) the operation is not an update, and (c) the new
- // package has not opted out of backup participation.
+ // A restore should be requested at this point if (a) the install
+ // succeeded, (b) the operation is not an update.
final boolean update = res.removedInfo != null
&& res.removedInfo.removedPackage != null;
- boolean allowBackup = res.pkg != null && res.pkg.isAllowBackup();
- boolean doRestore = !update && allowBackup;
+ boolean doRestore = !update;
// Set up the post-install work request bookkeeping. This will be used
// and cleaned up by the post-install event handling regardless of whether
@@ -19542,6 +19528,9 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (outInfo != null) {
+ if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
+ outInfo.dataRemoved = true;
+ }
outInfo.removedPackage = ps.name;
outInfo.installerPackageName = ps.installSource.installerPackageName;
outInfo.isStaticSharedLib = pkg != null && pkg.getStaticSharedLibName() != null;
@@ -20641,6 +20630,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (cn != null) {
return cn;
}
+ // TODO: This should not happen since there should always be a default package set for
+ // ROLE_HOME in RoleManager. Continue with a warning log for now.
+ Slog.w(TAG, "Default package for ROLE_HOME is not set in RoleManager");
// Find the launcher with the highest priority and return that component if there are no
// other home activity with the same priority.
@@ -20689,6 +20681,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (packageName == null) {
return null;
}
+
int resolveInfosSize = resolveInfos.size();
for (int i = 0; i < resolveInfosSize; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
@@ -20748,6 +20741,11 @@ public class PackageManagerService extends IPackageManager.Stub
// PermissionController manages default home directly.
return false;
}
+
+ if (packageName == null) {
+ // Keep the default home package in RoleManager.
+ return false;
+ }
mPermissionManager.setDefaultHome(packageName, userId, (successful) -> {
if (successful) {
postPreferredActivityChangedBroadcast(userId);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d137fd05f793..e44c8ab3f7f3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -760,6 +760,8 @@ public class UserManagerService extends IUserManager.Stub {
return null;
}
+ // TODO(b/157921703): replace by getAliveUsers() or remove (so callers
+ // explicitly call the 3-booleans version)
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
true);
diff --git a/services/core/java/com/android/server/slice/SliceFullAccessList.java b/services/core/java/com/android/server/slice/SliceFullAccessList.java
index 6f5afa207d31..d25ddf877951 100644
--- a/services/core/java/com/android/server/slice/SliceFullAccessList.java
+++ b/services/core/java/com/android/server/slice/SliceFullAccessList.java
@@ -101,7 +101,7 @@ public class SliceFullAccessList {
public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
// upgrade xml
int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0);
- final List<UserInfo> activeUsers = UserManager.get(mContext).getUsers(true);
+ final List<UserInfo> activeUsers = UserManager.get(mContext).getAliveUsers();
for (UserInfo userInfo : activeUsers) {
upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier());
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 0c85387be695..386f390c6cb9 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -379,7 +379,7 @@ public class TrustManagerService extends SystemService {
}
private void updateTrustAll() {
- List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (UserInfo userInfo : userInfos) {
updateTrust(userInfo.id, 0);
}
@@ -485,7 +485,7 @@ public class TrustManagerService extends SystemService {
List<UserInfo> userInfos;
if (userIdOrAll == UserHandle.USER_ALL) {
- userInfos = mUserManager.getUsers(true /* excludeDying */);
+ userInfos = mUserManager.getAliveUsers();
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userIdOrAll));
@@ -644,7 +644,7 @@ public class TrustManagerService extends SystemService {
}
List<UserInfo> userInfos;
if (userId == UserHandle.USER_ALL) {
- userInfos = mUserManager.getUsers(true /* excludeDying */);
+ userInfos = mUserManager.getAliveUsers();
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
@@ -1171,7 +1171,7 @@ public class TrustManagerService extends SystemService {
fout.println("disabled because the third-party apps can't run yet.");
return;
}
- final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index be7a6aed7489..f206259b8fe0 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1710,8 +1710,9 @@ class ActivityStarter {
mRootWindowContainer.startPowerModeLaunchIfNeeded(
false /* forceSend */, mStartActivity);
- mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
- newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity,
+ topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
+ mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f9e6270aec5d..6182a55b6e52 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2286,10 +2286,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- if (display.shouldSleep()) {
- continue;
- }
-
final boolean curResult = result;
boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas(
(taskDisplayArea, resumed) -> {
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 33935d61ead2..7df2b407557d 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -26,6 +26,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.util.DebugUtils;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
@@ -429,7 +430,8 @@ class SurfaceAnimator {
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
- pw.print(" mAnimationType=" + mAnimationType);
+ pw.print(" mAnimationType=" + DebugUtils.valueToString(SurfaceAnimator.class,
+ "ANIMATION_TYPE_", mAnimationType));
pw.println(mAnimationStartDelayed ? " mAnimationStartDelayed=true" : "");
pw.print(prefix); pw.print("Animation: "); pw.println(mAnimation);
if (mAnimation != null) {
@@ -442,56 +444,56 @@ class SurfaceAnimator {
* No animation is specified.
* @hide
*/
- static final int ANIMATION_TYPE_NONE = 0;
+ public static final int ANIMATION_TYPE_NONE = 0;
/**
* Animation for an app transition.
* @hide
*/
- static final int ANIMATION_TYPE_APP_TRANSITION = 1;
+ public static final int ANIMATION_TYPE_APP_TRANSITION = 1;
/**
* Animation for screen rotation.
* @hide
*/
- static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
+ public static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1;
/**
* Animation for dimming.
* @hide
*/
- static final int ANIMATION_TYPE_DIMMER = 1 << 2;
+ public static final int ANIMATION_TYPE_DIMMER = 1 << 2;
/**
* Animation for recent apps.
* @hide
*/
- static final int ANIMATION_TYPE_RECENTS = 1 << 3;
+ public static final int ANIMATION_TYPE_RECENTS = 1 << 3;
/**
* Animation for a {@link WindowState} without animating the activity.
* @hide
*/
- static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
+ public static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4;
/**
* Animation to control insets. This is actually not an animation, but is used to give the
* client a leash over the system window causing insets.
* @hide
*/
- static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
+ public static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5;
/**
* Animation when a fixed rotation transform is applied to a window token.
* @hide
*/
- static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6;
+ public static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6;
/**
* Bitmask to include all animation types. This is NOT an {@link AnimationType}
* @hide
*/
- static final int ANIMATION_TYPE_ALL = -1;
+ public static final int ANIMATION_TYPE_ALL = -1;
/**
* The type of the animation.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 19bf451cec05..bfaaf462ed51 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -6348,7 +6348,7 @@ class Task extends WindowContainer<WindowContainer> {
return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
}
- void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
Task rTask = r.getTask();
final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
@@ -7585,7 +7585,11 @@ class Task extends WindowContainer<WindowContainer> {
// Do not sleep activities in this stack if we're marked as focused and the keyguard
// is in the process of going away.
if (isFocusedStackOnDisplay()
- && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
+ && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()
+ // Avoid resuming activities on secondary displays since we don't want bubble
+ // activities to be resumed while bubble is still collapsed.
+ // TODO(b/113840485): Having keyguard going away state for secondary displays.
+ && display.isDefaultDisplay) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 1b779c6a0cc9..63a595e3bc17 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -38,6 +38,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseBooleanArray;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
@@ -50,6 +51,7 @@ import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -206,7 +208,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private final DeathRecipient mDeathRecipient;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
private final int mUid;
- private boolean mInterceptBackPressedOnTaskRoot;
TaskOrganizerState(ITaskOrganizer organizer, int uid) {
final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
@@ -224,10 +225,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
mUid = uid;
}
- void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
- mInterceptBackPressedOnTaskRoot = interceptBackPressed;
- }
-
void addTask(Task t) {
if (t.mTaskAppearedSent) return;
@@ -247,6 +244,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
mOrganizer.onTaskVanished(t);
}
mOrganizedTasks.remove(t);
+ mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
}
void dispose() {
@@ -278,6 +276,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
+ // Set of organized tasks (by taskId) that dispatch back pressed to their organizers
+ private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet();
private final ActivityTaskManagerService mService;
@@ -623,7 +623,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
- public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
+ public void setInterceptBackPressedOnTaskRoot(WindowContainerToken token,
boolean interceptBackPressed) {
enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
final long origId = Binder.clearCallingIdentity();
@@ -631,9 +631,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Set intercept back pressed on root=%b",
interceptBackPressed);
- final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
- if (state != null) {
- state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
+ final Task task = WindowContainer.fromBinder(token.asBinder()).asTask();
+ if (task == null) {
+ Slog.w(TAG, "Could not resolve task from token");
+ return;
+ }
+ if (interceptBackPressed) {
+ mInterceptBackPressedOnRootTasks.add(task.mTaskId);
+ } else {
+ mInterceptBackPressedOnRootTasks.remove(task.mTaskId);
}
}
} finally {
@@ -642,15 +648,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
- if (task == null || !task.isOrganized()) {
+ if (task == null || !task.isOrganized()
+ || !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
return false;
}
final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
- if (!state.mInterceptBackPressedOnTaskRoot) {
- return false;
- }
-
state.mOrganizer.onBackPressedOnTaskRoot(task);
return true;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 22e309cdc2b4..80455833a3eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5782,9 +5782,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
- final CallerIdentity identity = getCallerIdentity();
- Preconditions.checkCallAuthorization(isSystemUid(identity) || isRootUid(identity)
- || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL));
final ActiveAdmin admin;
synchronized (getLockObject()) {
@@ -9438,8 +9435,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(isDeviceOwner(identity));
return mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mInjector.getUserManager().getUsers(true
- /*excludeDying*/);
+ final List<UserInfo> userInfos = mInjector.getUserManager().getAliveUsers();
final List<UserHandle> userHandles = new ArrayList<>();
for (UserInfo userInfo : userInfos) {
UserHandle userHandle = userInfo.getUserHandle();
@@ -10362,7 +10358,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void maybeClearLockTaskPolicyLocked() {
mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = userInfos.size() - 1; i >= 0; i--) {
int userId = userInfos.get(i).id;
if (canUserUseLockTaskLocked(userId)) {
@@ -10849,7 +10845,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* them.
*/
void updateUserSetupCompleteAndPaired() {
- List<UserInfo> users = mUserManager.getUsers(true);
+ List<UserInfo> users = mUserManager.getAliveUsers();
final int N = users.size();
for (int i = 0; i < N; i++) {
int userHandle = users.get(i).id;
@@ -12052,14 +12048,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean isSystemOnlyUser(ComponentName admin) {
- Objects.requireNonNull(admin, "ComponentName is null");
- final CallerIdentity identity = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(identity));
- return UserManager.isSplitSystemUser() && identity.getUserId() == UserHandle.USER_SYSTEM;
- }
-
- @Override
public void reboot(ComponentName admin) {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity identity = getCallerIdentity(admin);
@@ -12579,7 +12567,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private boolean areAllUsersAffiliatedWithDeviceLocked() {
return mInjector.binderWithCleanCallingIdentity(() -> {
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = 0; i < userInfos.size(); i++) {
int userId = userInfos.get(i).id;
if (!isUserAffiliatedWithDeviceLocked(userId)) {
@@ -13048,7 +13036,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
} else {
// Caller is the device owner: Look for profile owners that it can bind to.
- final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+ final List<UserInfo> userInfos = mUserManager.getAliveUsers();
for (int i = 0; i < userInfos.size(); i++) {
final int userId = userInfos.get(i).id;
if (userId != callingUserId && canUserBindToDeviceOwnerLocked(userId)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 3cdd482ffa37..7649af4ee911 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -169,7 +169,7 @@ class Owners {
// First, try to read from the legacy file.
final File legacy = getLegacyConfigFile();
- final List<UserInfo> users = mUserManager.getUsers(true);
+ final List<UserInfo> users = mUserManager.getAliveUsers();
if (readLegacyOwnerFileLocked(legacy)) {
if (DEBUG) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index bec9f26672f4..a10e0ba5020c 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -81,7 +81,7 @@ public class WindowMagnificationGestureHandlerTest {
@After
public void tearDown() {
- mWindowMagnificationManager.disableWindowMagnifier(DISPLAY_0, true);
+ mWindowMagnificationManager.disableWindowMagnification(DISPLAY_0, true);
}
@Test
@@ -225,7 +225,7 @@ public class WindowMagnificationGestureHandlerTest {
}
break;
case STATE_SHOW_MAGNIFIER: {
- mWindowMagnificationManager.disableWindowMagnifier(DISPLAY_0, false);
+ mWindowMagnificationManager.disableWindowMagnification(DISPLAY_0, false);
}
break;
case STATE_TWO_FINGERS_DOWN: {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
index 70e6a340816a..e067b7eca755 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -68,8 +68,10 @@ public class WindowMagnificationManagerTest {
private static final int CURRENT_USER_ID = UserHandle.USER_CURRENT;
private MockWindowMagnificationConnection mMockConnection;
- @Mock private Context mContext;
- @Mock private StatusBarManagerInternal mMockStatusBarManagerInternal;
+ @Mock
+ private Context mContext;
+ @Mock
+ private StatusBarManagerInternal mMockStatusBarManagerInternal;
private MockContentResolver mResolver;
private WindowMagnificationManager mWindowMagnificationManager;
@@ -84,7 +86,7 @@ public class WindowMagnificationManagerTest {
when(mContext.getContentResolver()).thenReturn(mResolver);
doAnswer((InvocationOnMock invocation) -> {
- final boolean connect = (Boolean) invocation.getArguments()[0];
+ final boolean connect = (Boolean) invocation.getArguments()[0];
mWindowMagnificationManager.setConnection(
connect ? mMockConnection.getConnection() : null);
return null;
@@ -161,7 +163,7 @@ public class WindowMagnificationManagerTest {
public void enable_TestDisplay_enableWindowMagnification() throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2f, 200f, 300f);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f);
verify(mMockConnection.getConnection()).enableWindowMagnification(TEST_DISPLAY, 2f,
200f, 300f);
@@ -170,9 +172,9 @@ public class WindowMagnificationManagerTest {
@Test
public void disable_testDisplay_disableWindowMagnification() throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 3f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
- mWindowMagnificationManager.disableWindowMagnifier(TEST_DISPLAY, false);
+ mWindowMagnificationManager.disableWindowMagnification(TEST_DISPLAY, false);
verify(mMockConnection.getConnection()).disableWindowMagnification(TEST_DISPLAY);
}
@@ -183,7 +185,7 @@ public class WindowMagnificationManagerTest {
assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN);
assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
}
@@ -198,7 +200,7 @@ public class WindowMagnificationManagerTest {
@Test
public void persistScale_setValue_expectedValueInProvider() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2.0f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN);
mWindowMagnificationManager.setScale(TEST_DISPLAY, 2.5f);
mWindowMagnificationManager.persistScale(TEST_DISPLAY);
@@ -211,7 +213,7 @@ public class WindowMagnificationManagerTest {
@Test
public void scaleSetterGetter_enabledOnTestDisplay_expectedValue() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2.0f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.0f, NaN, NaN);
mWindowMagnificationManager.setScale(TEST_DISPLAY, 2.5f);
@@ -221,7 +223,7 @@ public class WindowMagnificationManagerTest {
@Test
public void scaleSetterGetter_scaleIsOutOfRang_getNormalizeValue() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2.5f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN);
mWindowMagnificationManager.setScale(TEST_DISPLAY, 10.0f);
@@ -232,9 +234,9 @@ public class WindowMagnificationManagerTest {
@Test
public void moveWindowMagnifier() throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 2f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, NaN, NaN);
- mWindowMagnificationManager.moveWindowMagnifier(TEST_DISPLAY, 200, 300);
+ mWindowMagnificationManager.moveWindowMagnification(TEST_DISPLAY, 200, 300);
verify(mMockConnection.getConnection()).moveWindowMagnifier(TEST_DISPLAY, 200, 300);
}
@@ -254,7 +256,7 @@ public class WindowMagnificationManagerTest {
@Test
public void pointersInWindow_returnCorrectValue() throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 3.0f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, NaN, NaN);
mMockConnection.getConnectionCallback().onWindowMagnifierBoundsChanged(TEST_DISPLAY,
new Rect(0, 0, 500, 500));
PointF[] pointersLocation = new PointF[2];
@@ -268,7 +270,7 @@ public class WindowMagnificationManagerTest {
@Test
public void binderDied_windowMagnifierIsEnabled_resetState() throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 3f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
mMockConnection.getDeathRecipient().binderDied();
@@ -280,7 +282,7 @@ public class WindowMagnificationManagerTest {
requestConnectionToNull_disableAllMagnifiersAndRequestWindowMagnificationConnection()
throws RemoteException {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
- mWindowMagnificationManager.enableWindowMagnifier(TEST_DISPLAY, 3f, NaN, NaN);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
assertTrue(mWindowMagnificationManager.requestConnection(false));
@@ -306,21 +308,24 @@ public class WindowMagnificationManagerTest {
@Test
public void requestConnection_registerAndUnregisterBroadcastReceiver() {
assertTrue(mWindowMagnificationManager.requestConnection(true));
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+ verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
assertTrue(mWindowMagnificationManager.requestConnection(false));
verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
}
@Test
- public void onReceiveScreenOff_removeMagnificationButtonAndDisableWindowMagnification()
+ public void onScreenOff_windowMagnifierIsEnabled_removeButtonAndDisableWindowMagnification()
throws RemoteException {
mWindowMagnificationManager.requestConnection(true);
+ mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2.5f, NaN, NaN);
+
mWindowMagnificationManager.mScreenStateReceiver.onReceive(mContext,
new Intent(Intent.ACTION_SCREEN_OFF));
verify(mMockConnection.getConnection()).removeMagnificationButton(TEST_DISPLAY);
verify(mMockConnection.getConnection()).disableWindowMagnification(TEST_DISPLAY);
+ assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
}
private MotionEvent generatePointersDownEvent(PointF[] pointersLocation) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index b306ff091267..431cc27a6635 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -16,7 +16,6 @@
package com.android.server.devicepolicy;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -236,7 +235,7 @@ public class MockSystemServices {
}
mUserInfos.add(uh);
when(userManager.getUsers()).thenReturn(mUserInfos);
- when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
+ when(userManager.getAliveUsers()).thenReturn(mUserInfos);
when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
when(userManager.getProfileParent(anyInt())).thenAnswer(
invocation -> {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index ef2365e6da3e..3f324a279270 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -15,6 +15,7 @@
*/
package com.android.server.hdmi;
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -693,6 +694,82 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
+ public void sendVolumeKeyEvent_toTv_activeSource() {
+ mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setSystemAudioActivated(false);
+ mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress);
+
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+ HdmiCecMessage pressed = HdmiCecMessageBuilder.buildUserControlPressed(
+ mPlaybackLogicalAddress, ADDR_TV, HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP);
+ HdmiCecMessage released = HdmiCecMessageBuilder.buildUserControlReleased(
+ mPlaybackLogicalAddress, ADDR_TV);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
+ }
+
+ @Test
+ public void sendVolumeKeyEvent_toAudio_activeSource() {
+ mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setSystemAudioActivated(true);
+ mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress);
+
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+ HdmiCecMessage pressed = HdmiCecMessageBuilder.buildUserControlPressed(
+ mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM, HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP);
+ HdmiCecMessage released = HdmiCecMessageBuilder.buildUserControlReleased(
+ mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
+ }
+
+ @Test
+ public void sendVolumeKeyEvent_toTv_inactiveSource() {
+ mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setSystemAudioActivated(false);
+ mHdmiControlService.setActiveSource(ADDR_TV, 0x0000);
+
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+ HdmiCecMessage pressed = HdmiCecMessageBuilder.buildUserControlPressed(
+ mPlaybackLogicalAddress, ADDR_TV, HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP);
+ HdmiCecMessage released = HdmiCecMessageBuilder.buildUserControlReleased(
+ mPlaybackLogicalAddress, ADDR_TV);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
+ }
+
+ @Test
+ public void sendVolumeKeyEvent_toAudio_inactiveSource() {
+ mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
+ mHdmiControlService.setSystemAudioActivated(true);
+ mHdmiControlService.setActiveSource(ADDR_TV, 0x0000);
+
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
+ mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
+
+ HdmiCecMessage pressed = HdmiCecMessageBuilder.buildUserControlPressed(
+ mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM, HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP);
+ HdmiCecMessage released = HdmiCecMessageBuilder.buildUserControlReleased(
+ mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
+ }
+
+ @Test
public void handleSetStreamPath_broadcastsActiveSource() {
HdmiCecMessage setStreamPath = HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV,
mPlaybackPhysicalAddress);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 99433a6603c9..d7e431f3bb51 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -978,6 +978,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
assertFalse(services.isSameUser(service, 0));
assertTrue(services.isSameUser(service, 10));
+ assertTrue(services.isSameUser(service, UserHandle.USER_ALL));
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index ab4dc476ff20..5796e848ff6e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -103,7 +103,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
}
when(mUm.getUsers()).thenReturn(users);
- when(mUm.getUsers(anyBoolean())).thenReturn(users);
+ when(mUm.getAliveUsers()).thenReturn(users);
IntArray profileIds = new IntArray();
profileIds.add(0);
profileIds.add(11);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9319bea497fb..86447192a441 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5058,7 +5058,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
10, 10, r.getKey(), actionIndex, action, notificationVisibility,
generatedByAssistant);
verify(mAssistants).notifyAssistantActionClicked(
- eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
+ eq(r.getSbn()), eq(action), eq(generatedByAssistant));
assertEquals(1, mNotificationRecordLogger.numCalls());
assertEquals(
@@ -5082,7 +5082,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
10, 10, r.getKey(), actionIndex, action, notificationVisibility,
generatedByAssistant);
verify(mAssistants).notifyAssistantActionClicked(
- eq(r.getSbn()), eq(actionIndex), eq(action), eq(generatedByAssistant));
+ eq(r.getSbn()), eq(action), eq(generatedByAssistant));
assertEquals(1, mNotificationRecordLogger.numCalls());
assertEquals(
@@ -6948,4 +6948,63 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
mService.getNotificationRecordCount());
}
+
+ @Test
+ public void testIsVisibleToListener_notEnabled() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(false);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertFalse(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_noAssistant() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(null);
+
+ assertTrue(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_assistant_differentUser() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 0;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertFalse(mService.isVisibleToListener(sbn, info));
+ }
+
+ @Test
+ public void testIsVisibleToListener_assistant_sameUser() {
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ when(sbn.getUserId()).thenReturn(10);
+ ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+ ManagedServices.ManagedServiceInfo assistant = mock(ManagedServices.ManagedServiceInfo.class);
+ info.userid = 10;
+ when(info.isSameUser(anyInt())).thenReturn(true);
+ when(assistant.isSameUser(anyInt())).thenReturn(true);
+ when(info.enabledAndUserMatches(info.userid)).thenReturn(true);
+ when(mAssistants.checkServiceTokenLocked(any())).thenReturn(assistant);
+
+ assertTrue(mService.isVisibleToListener(sbn, info));
+ }
+
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index e2948a724acd..4cad39762a7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1202,19 +1202,22 @@ public class ActivityStackTests extends WindowTestsBase {
@Test
public void testShouldSleepActivities() {
// When focused activity and keyguard is going away, we should not sleep regardless
- // of the display state
+ // of the display state, but keyguard-going-away should only take effects on default
+ // display since there is no keyguard on secondary displays (yet).
verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, false /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
+ verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
+ true /* displaySleeping */, false /* isDefaultDisplay */, true /* expected */);
// When not the focused stack, defer to display sleeping state.
verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
// If keyguard is going away, defer to the display sleeping state.
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- false /* displaySleeping */, false /* expected*/);
+ false /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
}
@Test
@@ -1423,9 +1426,11 @@ public class ActivityStackTests extends WindowTestsBase {
}
private void verifyShouldSleepActivities(boolean focusedStack,
- boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
+ boolean keyguardGoingAway, boolean displaySleeping, boolean isDefaultDisplay,
+ boolean expected) {
final DisplayContent display = mock(DisplayContent.class);
final KeyguardController keyguardController = mSupervisor.getKeyguardController();
+ display.isDefaultDisplay = isDefaultDisplay;
doReturn(display).when(mStack).getDisplay();
doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index b89d16807a6e..26b0bfb1dd7c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -915,24 +915,6 @@ public class RootActivityContainerTests extends WindowTestsBase {
assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
}
- @Test
- public void testResumeFocusedStackOnSleepingDisplay() {
- // Create an activity on secondary display.
- final TestDisplayContent secondDisplay = addNewDisplayContentAt(
- DisplayContent.POSITION_TOP);
- final Task stack = secondDisplay.getDefaultTaskDisplayArea()
- .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setStack(stack).build();
- spyOn(activity);
- spyOn(stack);
-
- // Cannot resumed activities on secondary display if the display should sleep.
- doReturn(true).when(secondDisplay).shouldSleep();
- mRootWindowContainer.resumeFocusedStacksTopActivities();
- verify(stack, never()).resumeTopActivityUncheckedLocked(any(), any());
- verify(activity, never()).makeActiveIfNeeded(any());
- }
-
/**
* Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 289d54e967f5..46a6a82faba5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -930,23 +930,36 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task stack = createStack();
final Task task = createTask(stack);
final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
+ final Task stack2 = createStack();
+ final Task task2 = createTask(stack2);
+ final ActivityRecord activity2 = createActivityRecordInTask(stack.mDisplayContent, task2);
final ITaskOrganizer organizer = registerMockOrganizer();
// Setup the task to be controlled by the MW mode organizer
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
assertTrue(stack.isOrganized());
+ assertTrue(stack2.isOrganized());
// Verify a back pressed does not call the organizer
mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
verify(organizer, never()).onBackPressedOnTaskRoot(any());
// Enable intercepting back
- mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(organizer,
- true);
+ mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(
+ stack.mRemoteToken.toWindowContainerToken(), true);
// Verify now that the back press does call the organizer
mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
+
+ // Disable intercepting back
+ mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(
+ stack.mRemoteToken.toWindowContainerToken(), false);
+
+ // Verify now that the back press no longer calls the organizer
+ mWm.mAtmService.onBackPressedOnTaskRoot(activity.token);
+ verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
}
@Test
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 81aad972898e..f151d9ca2420 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -183,6 +183,7 @@ public class UsageStatsService extends SystemService implements
private static class ActivityData {
private final String mTaskRootPackage;
private final String mTaskRootClass;
+ public int lastEvent = Event.NONE;
private ActivityData(String taskRootPackage, String taskRootClass) {
mTaskRootPackage = taskRootPackage;
mTaskRootClass = taskRootClass;
@@ -785,6 +786,7 @@ public class UsageStatsService extends SystemService implements
switch (event.mEventType) {
case Event.ACTIVITY_RESUMED:
case Event.ACTIVITY_PAUSED:
+ case Event.ACTIVITY_STOPPED:
uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId);
break;
default:
@@ -817,8 +819,10 @@ public class UsageStatsService extends SystemService implements
.APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
// check if this activity has already been resumed
if (mVisibleActivities.get(event.mInstanceId) != null) break;
- mVisibleActivities.put(event.mInstanceId,
- new ActivityData(event.mTaskRootPackage, event.mTaskRootClass));
+ final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
+ event.mTaskRootClass);
+ resumedData.lastEvent = Event.ACTIVITY_RESUMED;
+ mVisibleActivities.put(event.mInstanceId, resumedData);
try {
switch(mUsageSource) {
case USAGE_SOURCE_CURRENT_ACTIVITY:
@@ -834,16 +838,17 @@ public class UsageStatsService extends SystemService implements
}
break;
case Event.ACTIVITY_PAUSED:
- if (event.mTaskRootPackage == null) {
- // Task Root info is missing. Repair the event based on previous data
- final ActivityData prevData = mVisibleActivities.get(event.mInstanceId);
- if (prevData == null) {
- Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
- + "/" + event.mClass + " event : " + event.mEventType
- + " instanceId : " + event.mInstanceId + ")");
- } else {
- event.mTaskRootPackage = prevData.mTaskRootPackage;
- event.mTaskRootClass = prevData.mTaskRootClass;
+ final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
+ if (pausedData == null) {
+ Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
+ + "/" + event.mClass + " event : " + event.mEventType
+ + " instanceId : " + event.mInstanceId + ")");
+ } else {
+ pausedData.lastEvent = Event.ACTIVITY_PAUSED;
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ event.mTaskRootPackage = pausedData.mTaskRootPackage;
+ event.mTaskRootClass = pausedData.mTaskRootClass;
}
}
FrameworkStatsLog.write(
@@ -866,6 +871,16 @@ public class UsageStatsService extends SystemService implements
return;
}
+ if (prevData.lastEvent != Event.ACTIVITY_PAUSED) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
+ uid,
+ event.mPackage,
+ event.mClass,
+ FrameworkStatsLog
+ .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
+ }
+
ArraySet<String> tokens;
synchronized (mUsageReporters) {
tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 4f5a30502c91..7dd003eb9755 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -15,6 +15,7 @@
android_test {
name: "RollbackTest",
manifest: "RollbackTest/AndroidManifest.xml",
+ platform_apis: true,
srcs: ["RollbackTest/src/**/*.java"],
static_libs: ["androidx.test.rules", "cts-rollback-lib", "cts-install-lib"],
test_suites: ["general-tests"],
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index de51c5ca19ed..0db2b2af7260 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -175,7 +175,7 @@ public class RollbackTest {
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
UserManager um = (UserManager) context.getSystemService(context.USER_SERVICE);
- List<Integer> userIds = um.getUsers(true)
+ List<Integer> userIds = um.getAliveUsers()
.stream().map(user -> user.id).collect(Collectors.toList());
assertThat(InstallUtils.isOnlyInstalledForUser(TestApp.A,
context.getUserId(), userIds)).isTrue();
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index f50d2e134730..702f8719ff24 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -84,7 +84,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
Log.e(TAG, e);
}
deleteFiles("/system/apex/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
- "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex");
+ "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
+ "/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex");
}
@Before
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a3673df1c713..bcb5c992f162 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1199,7 +1199,7 @@ public class ConnectivityServiceTest {
MockitoAnnotations.initMocks(this);
when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
- when(mUserManager.getUsers(eq(true))).thenReturn(
+ when(mUserManager.getAliveUsers()).thenReturn(
Arrays.asList(new UserInfo[] {
new UserInfo(VPN_USER, "", 0),
}));
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 5a29c2c96ba7..de35f910d53a 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -123,7 +123,7 @@ public class PermissionMonitorTest {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManager.getUsers(eq(true))).thenReturn(
+ when(mUserManager.getAliveUsers()).thenReturn(
Arrays.asList(new UserInfo[] {
new UserInfo(MOCK_USER1, "", 0),
new UserInfo(MOCK_USER2, "", 0),
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index e8c4ee9c628d..c76b4cd501e7 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -1238,15 +1238,14 @@ public class VpnTest {
* @see UserManagerService#getUsers(boolean)
*/
doAnswer(invocation -> {
- final boolean excludeDying = (boolean) invocation.getArguments()[0];
final ArrayList<UserInfo> result = new ArrayList<>(users.length);
for (UserInfo ui : users) {
- if (!excludeDying || (ui.isEnabled() && !ui.partial)) {
+ if (ui.isEnabled() && !ui.partial) {
result.add(ui);
}
}
return result;
- }).when(mUserManager).getUsers(anyBoolean());
+ }).when(mUserManager).getAliveUsers();
doAnswer(invocation -> {
final int id = (int) invocation.getArguments()[0];
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index aa3a13925894..9302f78b7fca 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -81,6 +81,12 @@ public final class ScanResult implements Parcelable {
public String capabilities;
/**
+ * The interface name on which the scan result was received.
+ * @hide
+ */
+ public String ifaceName;
+
+ /**
* @hide
* No security protocol.
*/
@@ -939,6 +945,7 @@ public final class ScanResult implements Parcelable {
flags = source.flags;
radioChainInfos = source.radioChainInfos;
this.mWifiStandard = source.mWifiStandard;
+ this.ifaceName = source.ifaceName;
}
}
@@ -977,6 +984,7 @@ public final class ScanResult implements Parcelable {
sb.append(", 80211mcResponder: ");
sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
+ sb.append(", interface name: ").append(ifaceName);
return sb.toString();
}
@@ -1056,6 +1064,7 @@ public final class ScanResult implements Parcelable {
} else {
dest.writeInt(0);
}
+ dest.writeString((ifaceName != null) ? ifaceName.toString() : "");
}
/** Implement the Parcelable interface */
@@ -1134,6 +1143,7 @@ public final class ScanResult implements Parcelable {
sr.radioChainInfos[i].level = in.readInt();
}
}
+ sr.ifaceName = in.readString();
return sr;
}
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 5516f433070f..4a3586826de9 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -44,6 +44,7 @@ public class ScanResultTest {
public static final long TEST_TSF = 04660l;
public static final @WifiAnnotations.WifiStandard int TEST_WIFI_STANDARD =
ScanResult.WIFI_STANDARD_11AC;
+ public static final String TEST_IFACE_NAME = "test_ifname";
/**
* Frequency to channel map. This include some frequencies used outside the US.
@@ -219,7 +220,7 @@ public class ScanResultTest {
+ "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, "
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
- + "Radio Chain Infos: null", scanResult.toString());
+ + "Radio Chain Infos: null, interface name: test_ifname", scanResult.toString());
}
/**
@@ -242,7 +243,8 @@ public class ScanResultTest {
+ "standard: 11ac, "
+ "80211mcResponder: is not supported, "
+ "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, "
- + "RadioChainInfo: id=1, level=-54]", scanResult.toString());
+ + "RadioChainInfo: id=1, level=-54], interface name: test_ifname",
+ scanResult.toString());
}
/**
@@ -283,6 +285,8 @@ public class ScanResultTest {
result.frequency = TEST_FREQUENCY;
result.timestamp = TEST_TSF;
result.setWifiStandard(TEST_WIFI_STANDARD);
+ result.ifaceName = TEST_IFACE_NAME;
+
return result;
}