summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp11
-rw-r--r--apct-tests/perftests/aconfig/src/android/os/flagging/AconfigPackagePerfTest.java5
-rw-r--r--core/api/system-current.txt1
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/UiModeManager.java4
-rw-r--r--core/java/android/app/WallpaperManager.java2
-rw-r--r--core/java/android/companion/virtual/flags.aconfig8
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java69
-rw-r--r--core/java/android/content/pm/flags.aconfig8
-rw-r--r--core/java/android/content/res/ApkAssets.java56
-rw-r--r--core/java/android/content/res/ResourceTimer.java56
-rw-r--r--core/java/android/hardware/SystemSensorManager.java43
-rw-r--r--core/java/android/hardware/display/DisplayTopology.java3
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/view/InputEventConsistencyVerifier.java2
-rw-r--r--core/java/android/view/SurfaceControl.java64
-rw-r--r--core/java/android/view/WindowManagerPolicyConstants.java3
-rw-r--r--core/java/android/view/contentprotection/flags/content_protection_flags.aconfig7
-rw-r--r--core/java/android/window/flags/window_surfaces.aconfig8
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig7
-rw-r--r--core/java/com/android/internal/policy/IKeyguardService.aidl14
-rw-r--r--core/jni/android_content_res_ApkAssets.cpp66
-rw-r--r--core/jni/android_view_SurfaceControl.cpp20
-rw-r--r--core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java79
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationController.aidl6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java13
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java54
-rw-r--r--libs/androidfw/ApkAssets.cpp9
-rw-r--r--libs/androidfw/AssetsProvider.cpp82
-rw-r--r--libs/androidfw/Idmap.cpp21
-rw-r--r--libs/androidfw/ResourceTypes.cpp78
-rw-r--r--libs/androidfw/Util.cpp25
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h2
-rw-r--r--libs/androidfw/include/androidfw/AssetsProvider.h25
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h32
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h48
-rw-r--r--libs/androidfw/include/androidfw/misc.h6
-rw-r--r--libs/androidfw/misc.cpp69
-rw-r--r--libs/androidfw/tests/Idmap_test.cpp27
-rw-r--r--packages/InputDevices/res/raw/keyboard_layout_romanian.kcm357
-rw-r--r--packages/InputDevices/res/values/strings.xml3
-rw-r--r--packages/InputDevices/res/xml/keyboard_layouts.xml7
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatter.kt83
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatterTest.kt178
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java17
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java36
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java82
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java12
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java95
-rw-r--r--packages/SystemUI/aconfig/predictive_back.aconfig14
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig8
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/AnimationFeatureFlags.kt6
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt50
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt54
-rw-r--r--packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt60
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt13
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt61
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt6
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt13
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ContentTest.kt69
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt42
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt37
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt56
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt22
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt78
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt51
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt82
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt40
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt116
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java85
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java280
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt16
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt91
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/StateTransitionsTest.kt111
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt30
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModelTest.kt117
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModelTest.kt73
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java123
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java236
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java309
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt226
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt75
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderTouchesViewBinder.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderIconProvider.kt103
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ui/VolumeDialogResources.kt68
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt114
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt116
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt63
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java197
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java2
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java6
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java7
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateProvider.java5
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityService.java341
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java4
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java20
-rw-r--r--services/core/java/com/android/server/notification/ZenModeConditions.java9
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java47
-rw-r--r--services/core/java/com/android/server/notification/flags.aconfig12
-rw-r--r--services/core/java/com/android/server/pm/ResilientAtomicFile.java22
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackageItem.java2
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java10
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java20
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java12
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java9
-rw-r--r--services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java15
-rw-r--r--services/core/java/com/android/server/wm/AppCompatController.java46
-rw-r--r--services/core/java/com/android/server/wm/AppCompatOverrides.java11
-rw-r--r--services/core/java/com/android/server/wm/AppCompatResizeOverrides.java38
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java217
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java21
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java245
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java34
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java16
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java257
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java41
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java105
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java3
-rw-r--r--tools/aapt2/cmd/Command.cpp169
-rw-r--r--tools/aapt2/cmd/Command.h54
-rw-r--r--tools/aapt2/cmd/Command_test.cpp41
197 files changed, 4279 insertions, 3899 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 214e0402c8fc..b1c091bfa946 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -220,17 +220,6 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
-java_aconfig_library {
- name: "telephony_flags_core_java_exported_lib",
- aconfig_declarations: "telephony_flags",
- mode: "exported",
- min_sdk_version: "30",
- apex_available: [
- "com.android.wifi",
- ],
- defaults: ["framework-minus-apex-aconfig-java-defaults"],
-}
-
cc_aconfig_library {
name: "telephony_flags_c_lib",
aconfig_declarations: "telephony_flags",
diff --git a/apct-tests/perftests/aconfig/src/android/os/flagging/AconfigPackagePerfTest.java b/apct-tests/perftests/aconfig/src/android/os/flagging/AconfigPackagePerfTest.java
index df6e3c836256..e790874ebc61 100644
--- a/apct-tests/perftests/aconfig/src/android/os/flagging/AconfigPackagePerfTest.java
+++ b/apct-tests/perftests/aconfig/src/android/os/flagging/AconfigPackagePerfTest.java
@@ -43,7 +43,7 @@ public class AconfigPackagePerfTest {
@Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
- @Parameterized.Parameters(name = "isPlatform={0}")
+ @Parameterized.Parameters(name = "isPlatform_{0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{false}, {true}});
}
@@ -60,10 +60,9 @@ public class AconfigPackagePerfTest {
}
}
- @Parameterized.Parameter(0)
-
// if this variable is true, then the test query flags from system/product/vendor
// if this variable is false, then the test query flags from updatable partitions
+ @Parameterized.Parameter(0)
public boolean mIsPlatform;
@Test
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index f82aecbd6d44..1286851a6918 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1290,7 +1290,6 @@ package android.app {
public class WallpaperManager {
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void clearWallpaper(int, int);
- method @FlaggedApi("android.app.customization_packs_apis") @NonNull @RequiresPermission(android.Manifest.permission.READ_WALLPAPER_INTERNAL) public android.util.SparseArray<android.graphics.Rect> getBitmapCrops(int);
method @FlaggedApi("android.app.customization_packs_apis") public static int getOrientation(@NonNull android.graphics.Point);
method @FloatRange(from=0.0f, to=1.0f) @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public float getWallpaperDimAmount();
method @FlaggedApi("android.app.customization_packs_apis") @Nullable public android.os.ParcelFileDescriptor getWallpaperFile(int, boolean);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index cd2cc07b8cc3..33a06165c77a 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -536,6 +536,7 @@ package android.app {
method @Nullable public android.graphics.Bitmap getBitmap();
method @Nullable public android.graphics.Bitmap getBitmapAsUser(int, boolean, int);
method @FlaggedApi("com.android.window.flags.multi_crop") @NonNull @RequiresPermission(android.Manifest.permission.READ_WALLPAPER_INTERNAL) public java.util.List<android.graphics.Rect> getBitmapCrops(@NonNull java.util.List<android.graphics.Point>, int, boolean);
+ method @FlaggedApi("android.app.customization_packs_apis") @NonNull @RequiresPermission(android.Manifest.permission.READ_WALLPAPER_INTERNAL) public android.util.SparseArray<android.graphics.Rect> getBitmapCrops(int);
method @FlaggedApi("com.android.window.flags.multi_crop") @NonNull public java.util.List<android.graphics.Rect> getBitmapCrops(@NonNull android.graphics.Point, @NonNull java.util.List<android.graphics.Point>, @Nullable java.util.Map<android.graphics.Point,android.graphics.Rect>);
method public boolean isLockscreenLiveWallpaperEnabled();
method @Nullable public android.graphics.Rect peekBitmapDimensions();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 717a2acb4b4a..1f3e6559a695 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -105,6 +105,7 @@ import android.content.pm.ServiceInfo;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.ResourceTimer;
import android.content.res.Resources;
import android.content.res.ResourcesImpl;
import android.content.res.loader.ResourcesLoader;
@@ -5253,6 +5254,7 @@ public final class ActivityThread extends ClientTransactionHandler
Resources.dumpHistory(pw, "");
pw.flush();
+ ResourceTimer.dumpTimers(info.fd.getFileDescriptor(), "-refresh");
if (info.finishCallback != null) {
info.finishCallback.sendResult(null);
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 2e6f3e1c7f0a..57549847f05d 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -753,7 +753,7 @@ public class UiModeManager {
* <p>
* The mode can be one of:
* <ul>
- * <li><em>{@link #MODE_NIGHT_NO}<em> sets the device into
+ * <li><em>{@link #MODE_NIGHT_NO}</em> sets the device into
* {@code notnight} mode</li>
* <li><em>{@link #MODE_NIGHT_YES}</em> sets the device into
* {@code night} mode</li>
@@ -889,7 +889,7 @@ public class UiModeManager {
* <p>
* The mode can be one of:
* <ul>
- * <li><em>{@link #MODE_NIGHT_NO}<em> sets the device into
+ * <li><em>{@link #MODE_NIGHT_NO}</em> sets the device into
* {@code notnight} mode</li>
* <li><em>{@link #MODE_NIGHT_YES}</em> sets the device into
* {@code night} mode</li>
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 360376da618c..73ecc7199686 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1690,7 +1690,7 @@ public class WallpaperManager {
* @hide
*/
@FlaggedApi(FLAG_CUSTOMIZATION_PACKS_APIS)
- @SystemApi
+ @TestApi
@RequiresPermission(READ_WALLPAPER_INTERNAL)
@NonNull
public SparseArray<Rect> getBitmapCrops(@SetWallpaperFlags int which) {
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 46da4a3d99bc..f31e7d4c61cd 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -11,14 +11,6 @@ package: "android.companion.virtual.flags"
container: "system"
flag {
- name: "enable_native_vdm"
- namespace: "virtual_devices"
- description: "Enable native VDM service"
- bug: "303535376"
- is_fixed_read_only: true
-}
-
-flag {
name: "dynamic_policy"
is_exported: true
namespace: "virtual_devices"
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 0333942b7f3e..9d11710a2cad 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.Manifest;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -30,6 +31,7 @@ import android.os.Environment;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.AttributeSet;
import android.util.IntArray;
@@ -45,11 +47,11 @@ import com.android.internal.util.ArrayUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
-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;
@@ -94,6 +96,9 @@ public abstract class RegisteredServicesCache<V> {
@GuardedBy("mServicesLock")
private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>(2);
+ @GuardedBy("mServicesLock")
+ private final ArrayMap<String, ServiceInfo<V>> mServiceInfoCaches = new ArrayMap<>();
+
private static class UserServices<V> {
@GuardedBy("mServicesLock")
final Map<V, Integer> persistentServices = Maps.newHashMap();
@@ -323,13 +328,16 @@ public abstract class RegisteredServicesCache<V> {
public final ComponentName componentName;
@UnsupportedAppUsage
public final int uid;
+ public final long lastUpdateTime;
/** @hide */
- public ServiceInfo(V type, ComponentInfo componentInfo, ComponentName componentName) {
+ public ServiceInfo(V type, ComponentInfo componentInfo, ComponentName componentName,
+ long lastUpdateTime) {
this.type = type;
this.componentInfo = componentInfo;
this.componentName = componentName;
this.uid = (componentInfo != null) ? componentInfo.applicationInfo.uid : -1;
+ this.lastUpdateTime = lastUpdateTime;
}
@Override
@@ -490,7 +498,7 @@ public abstract class RegisteredServicesCache<V> {
final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
for (ResolveInfo resolveInfo : resolveInfos) {
try {
- ServiceInfo<V> info = parseServiceInfo(resolveInfo);
+ ServiceInfo<V> info = parseServiceInfo(resolveInfo, userId);
if (info == null) {
Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
continue;
@@ -638,13 +646,31 @@ public abstract class RegisteredServicesCache<V> {
}
@VisibleForTesting
- protected ServiceInfo<V> parseServiceInfo(ResolveInfo service)
+ protected ServiceInfo<V> parseServiceInfo(ResolveInfo service, int userId)
throws XmlPullParserException, IOException {
android.content.pm.ServiceInfo si = service.serviceInfo;
ComponentName componentName = new ComponentName(si.packageName, si.name);
PackageManager pm = mContext.getPackageManager();
+ // Check if the service has been in the service cache.
+ long lastUpdateTime = -1;
+ if (Flags.optimizeParsingInRegisteredServicesCache()) {
+ try {
+ PackageInfo packageInfo = pm.getPackageInfoAsUser(si.packageName,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ lastUpdateTime = packageInfo.lastUpdateTime;
+
+ ServiceInfo<V> serviceInfo = getServiceInfoFromServiceCache(si, lastUpdateTime);
+ if (serviceInfo != null) {
+ return serviceInfo;
+ }
+ } catch (NameNotFoundException | SecurityException e) {
+ Slog.d(TAG, "Fail to get the PackageInfo in parseServiceInfo: " + e);
+ }
+ }
+
XmlResourceParser parser = null;
try {
parser = si.loadXmlMetaData(pm, mMetaDataName);
@@ -670,8 +696,13 @@ public abstract class RegisteredServicesCache<V> {
if (v == null) {
return null;
}
- final android.content.pm.ServiceInfo serviceInfo = service.serviceInfo;
- return new ServiceInfo<V>(v, serviceInfo, componentName);
+ ServiceInfo<V> serviceInfo = new ServiceInfo<V>(v, si, componentName, lastUpdateTime);
+ if (Flags.optimizeParsingInRegisteredServicesCache()) {
+ synchronized (mServicesLock) {
+ mServiceInfoCaches.put(getServiceCacheKey(si), serviceInfo);
+ }
+ }
+ return serviceInfo;
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
"Unable to load resources for pacakge " + si.packageName);
@@ -841,4 +872,28 @@ public abstract class RegisteredServicesCache<V> {
mContext.unregisterReceiver(mExternalReceiver);
mContext.unregisterReceiver(mUserRemovedReceiver);
}
+
+ private static String getServiceCacheKey(@NonNull android.content.pm.ServiceInfo serviceInfo) {
+ StringBuilder sb = new StringBuilder(serviceInfo.packageName);
+ sb.append('-');
+ sb.append(serviceInfo.name);
+ return sb.toString();
+ }
+
+ private ServiceInfo<V> getServiceInfoFromServiceCache(
+ @NonNull android.content.pm.ServiceInfo serviceInfo, long lastUpdateTime) {
+ String serviceCacheKey = getServiceCacheKey(serviceInfo);
+ synchronized (mServicesLock) {
+ ServiceInfo<V> serviceCache = mServiceInfoCaches.get(serviceCacheKey);
+ if (serviceCache == null) {
+ return null;
+ }
+ if (serviceCache.lastUpdateTime == lastUpdateTime) {
+ return serviceCache;
+ }
+ // The service is not latest, remove it from the cache.
+ mServiceInfoCaches.remove(serviceCacheKey);
+ return null;
+ }
+ }
}
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 7bba06c87813..e4b8c90d381d 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -383,3 +383,11 @@ flag {
bug: "334024639"
description: "Feature flag to check whether a given UID can access a content provider"
}
+
+flag {
+ name: "optimize_parsing_in_registered_services_cache"
+ namespace: "package_manager_service"
+ description: "Feature flag to optimize RegisteredServicesCache ServiceInfo parsing by using caches."
+ bug: "319137634"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index 908999b64961..b938aac811fd 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -25,6 +25,7 @@ import android.content.res.loader.ResourcesProvider;
import android.ravenwood.annotation.RavenwoodClassLoadHook;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.text.TextUtils;
+import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -50,6 +51,7 @@ import java.util.Objects;
@RavenwoodKeepWholeClass
@RavenwoodClassLoadHook(RavenwoodClassLoadHook.LIBANDROID_LOADING_HOOK)
public final class ApkAssets {
+ private static final boolean DEBUG = false;
/**
* The apk assets contains framework resource values specified by the system.
@@ -134,6 +136,17 @@ public final class ApkAssets {
@Nullable
private final AssetsProvider mAssets;
+ @NonNull
+ private String mName;
+
+ private static final int UPTODATE_FALSE = 0;
+ private static final int UPTODATE_TRUE = 1;
+ private static final int UPTODATE_ALWAYS_TRUE = 2;
+
+ // Start with the only value that may change later and would force a native call to
+ // double check it.
+ private int mPreviousUpToDateResult = UPTODATE_TRUE;
+
/**
* Creates a new ApkAssets instance from the given path on disk.
*
@@ -304,7 +317,7 @@ public final class ApkAssets {
private ApkAssets(@FormatType int format, @NonNull String path, @PropertyFlags int flags,
@Nullable AssetsProvider assets) throws IOException {
- this(format, flags, assets);
+ this(format, flags, assets, path);
Objects.requireNonNull(path, "path");
mNativePtr = nativeLoad(format, path, flags, assets);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
@@ -313,7 +326,7 @@ public final class ApkAssets {
private ApkAssets(@FormatType int format, @NonNull FileDescriptor fd,
@NonNull String friendlyName, @PropertyFlags int flags, @Nullable AssetsProvider assets)
throws IOException {
- this(format, flags, assets);
+ this(format, flags, assets, friendlyName);
Objects.requireNonNull(fd, "fd");
Objects.requireNonNull(friendlyName, "friendlyName");
mNativePtr = nativeLoadFd(format, fd, friendlyName, flags, assets);
@@ -323,7 +336,7 @@ public final class ApkAssets {
private ApkAssets(@FormatType int format, @NonNull FileDescriptor fd,
@NonNull String friendlyName, long offset, long length, @PropertyFlags int flags,
@Nullable AssetsProvider assets) throws IOException {
- this(format, flags, assets);
+ this(format, flags, assets, friendlyName);
Objects.requireNonNull(fd, "fd");
Objects.requireNonNull(friendlyName, "friendlyName");
mNativePtr = nativeLoadFdOffsets(format, fd, friendlyName, offset, length, flags, assets);
@@ -331,16 +344,17 @@ public final class ApkAssets {
}
private ApkAssets(@PropertyFlags int flags, @Nullable AssetsProvider assets) {
- this(FORMAT_APK, flags, assets);
+ this(FORMAT_APK, flags, assets, "empty");
mNativePtr = nativeLoadEmpty(flags, assets);
mStringBlock = null;
}
private ApkAssets(@FormatType int format, @PropertyFlags int flags,
- @Nullable AssetsProvider assets) {
+ @Nullable AssetsProvider assets, @NonNull String name) {
mFlags = flags;
mAssets = assets;
mIsOverlay = format == FORMAT_IDMAP;
+ if (DEBUG) mName = name;
}
@UnsupportedAppUsage
@@ -421,13 +435,41 @@ public final class ApkAssets {
}
}
+ private static double intervalMs(long beginNs, long endNs) {
+ return (endNs - beginNs) / 1000000.0;
+ }
+
/**
* Returns false if the underlying APK was changed since this ApkAssets was loaded.
*/
public boolean isUpToDate() {
+ // This function is performance-critical - it's called multiple times on every Resources
+ // object creation, and on few other cache accesses - so it's important to avoid the native
+ // call when we know for sure what it will return (which is the case for both ALWAYS_TRUE
+ // and FALSE).
+ if (mPreviousUpToDateResult != UPTODATE_TRUE) {
+ return mPreviousUpToDateResult == UPTODATE_ALWAYS_TRUE;
+ }
+ final long beforeTs, afterLockTs, afterNativeTs, afterUnlockTs;
+ if (DEBUG) beforeTs = System.nanoTime();
+ final int res;
synchronized (this) {
- return nativeIsUpToDate(mNativePtr);
+ if (DEBUG) afterLockTs = System.nanoTime();
+ res = nativeIsUpToDate(mNativePtr);
+ if (DEBUG) afterNativeTs = System.nanoTime();
+ }
+ if (DEBUG) {
+ afterUnlockTs = System.nanoTime();
+ if (afterUnlockTs - beforeTs >= 10L * 1000000) {
+ Log.d("ApkAssets", "isUpToDate(" + mName + ") took "
+ + intervalMs(beforeTs, afterUnlockTs)
+ + " ms: " + intervalMs(beforeTs, afterLockTs)
+ + " / " + intervalMs(afterLockTs, afterNativeTs)
+ + " / " + intervalMs(afterNativeTs, afterUnlockTs));
+ }
}
+ mPreviousUpToDateResult = res;
+ return res != UPTODATE_FALSE;
}
public boolean isSystem() {
@@ -487,7 +529,7 @@ public final class ApkAssets {
private static native @NonNull String nativeGetAssetPath(long ptr);
private static native @NonNull String nativeGetDebugName(long ptr);
private static native long nativeGetStringBlock(long ptr);
- @CriticalNative private static native boolean nativeIsUpToDate(long ptr);
+ @CriticalNative private static native int nativeIsUpToDate(long ptr);
private static native long nativeOpenXml(long ptr, @NonNull String fileName) throws IOException;
private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr,
String overlayableName) throws IOException;
diff --git a/core/java/android/content/res/ResourceTimer.java b/core/java/android/content/res/ResourceTimer.java
index d51f64ce8106..2d1bf4d9d296 100644
--- a/core/java/android/content/res/ResourceTimer.java
+++ b/core/java/android/content/res/ResourceTimer.java
@@ -17,13 +17,10 @@
package android.content.res;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-
import android.app.AppProtoEnums;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.text.TextUtils;
@@ -33,6 +30,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
+import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -277,38 +275,40 @@ public final class ResourceTimer {
* Update the metrics information and dump it.
* @hide
*/
- public static void dumpTimers(@NonNull ParcelFileDescriptor pfd, @Nullable String[] args) {
- FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
- PrintWriter pw = new FastPrintWriter(fout);
- synchronized (sLock) {
- if (!sEnabled || (sConfig == null)) {
+ public static void dumpTimers(@NonNull FileDescriptor fd, String... args) {
+ try (PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd))) {
+ pw.println("\nDumping ResourceTimers");
+
+ final boolean enabled;
+ synchronized (sLock) {
+ enabled = sEnabled && sConfig != null;
+ }
+ if (!enabled) {
pw.println(" Timers are not enabled in this process");
- pw.flush();
return;
}
- }
- // Look for the --refresh switch. If the switch is present, then sTimers is updated.
- // Otherwise, the current value of sTimers is displayed.
- boolean refresh = Arrays.asList(args).contains("-refresh");
-
- synchronized (sLock) {
- update(refresh);
- long runtime = sLastUpdated - sProcessStart;
- pw.format(" config runtime=%d proc=%s\n", runtime, Process.myProcessName());
- for (int i = 0; i < sTimers.length; i++) {
- Timer t = sTimers[i];
- if (t.count != 0) {
- String name = sConfig.timers[i];
- pw.format(" stats timer=%s cnt=%d avg=%d min=%d max=%d pval=%s "
- + "largest=%s\n",
- name, t.count, t.total / t.count, t.mintime, t.maxtime,
- packedString(t.percentile),
- packedString(t.largest));
+ // Look for the --refresh switch. If the switch is present, then sTimers is updated.
+ // Otherwise, the current value of sTimers is displayed.
+ boolean refresh = Arrays.asList(args).contains("-refresh");
+
+ synchronized (sLock) {
+ update(refresh);
+ long runtime = sLastUpdated - sProcessStart;
+ pw.format(" config runtime=%d proc=%s\n", runtime, Process.myProcessName());
+ for (int i = 0; i < sTimers.length; i++) {
+ Timer t = sTimers[i];
+ if (t.count != 0) {
+ String name = sConfig.timers[i];
+ pw.format(" stats timer=%s cnt=%d avg=%d min=%d max=%d pval=%s "
+ + "largest=%s\n",
+ name, t.count, t.total / t.count, t.mintime, t.maxtime,
+ packedString(t.percentile),
+ packedString(t.largest));
+ }
}
}
}
- pw.flush();
}
// Enable (or disabled) the runtime timers. Note that timers are disabled by default. This
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 2d3d25217357..868429c30631 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,8 +16,6 @@
package android.hardware;
-import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
-import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
import static android.content.Context.DEVICE_ID_DEFAULT;
@@ -164,11 +162,7 @@ public class SystemSensorManager extends SensorManager {
// initialize the sensor list
for (int index = 0;; ++index) {
Sensor sensor = new Sensor();
- if (android.companion.virtual.flags.Flags.enableNativeVdm()) {
- if (!nativeGetDefaultDeviceSensorAtIndex(mNativeInstance, sensor, index)) break;
- } else {
- if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
- }
+ if (!nativeGetDefaultDeviceSensorAtIndex(mNativeInstance, sensor, index)) break;
mFullSensorsList.add(sensor);
mHandleToSensor.put(sensor.getHandle(), sensor);
}
@@ -555,11 +549,7 @@ public class SystemSensorManager extends SensorManager {
}
private List<Sensor> createRuntimeSensorListLocked(int deviceId) {
- if (android.companion.virtual.flags.Flags.vdmPublicApis()) {
- setupVirtualDeviceListener();
- } else {
- setupRuntimeSensorBroadcastReceiver();
- }
+ setupVirtualDeviceListener();
List<Sensor> list = new ArrayList<>();
nativeGetRuntimeSensors(mNativeInstance, deviceId, list);
mFullRuntimeSensorListByDevice.put(deviceId, list);
@@ -570,35 +560,6 @@ public class SystemSensorManager extends SensorManager {
return list;
}
- private void setupRuntimeSensorBroadcastReceiver() {
- if (mRuntimeSensorBroadcastReceiver == null) {
- mRuntimeSensorBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTION_VIRTUAL_DEVICE_REMOVED)) {
- synchronized (mFullRuntimeSensorListByDevice) {
- final int deviceId = intent.getIntExtra(
- EXTRA_VIRTUAL_DEVICE_ID, DEVICE_ID_DEFAULT);
- List<Sensor> removedSensors =
- mFullRuntimeSensorListByDevice.removeReturnOld(deviceId);
- if (removedSensors != null) {
- for (Sensor s : removedSensors) {
- cleanupSensorConnection(s);
- }
- }
- mRuntimeSensorListByDeviceByType.remove(deviceId);
- }
- }
- }
- };
-
- IntentFilter filter = new IntentFilter("virtual_device_removed");
- filter.addAction(ACTION_VIRTUAL_DEVICE_REMOVED);
- mContext.registerReceiver(mRuntimeSensorBroadcastReceiver, filter,
- Context.RECEIVER_NOT_EXPORTED);
- }
- }
-
private void setupVirtualDeviceListener() {
if (mVirtualDeviceListener != null) {
return;
diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java
index 0e2c05f92e7c..1d2f133ee759 100644
--- a/core/java/android/hardware/display/DisplayTopology.java
+++ b/core/java/android/hardware/display/DisplayTopology.java
@@ -679,8 +679,7 @@ public final class DisplayTopology implements Parcelable {
}
/**
- * Tests whether two brightness float values are within a small enough tolerance
- * of each other.
+ * Tests whether two float values are within a small enough tolerance of each other.
* @param a first float to compare
* @param b second float to compare
* @return whether the two values are within a small enough tolerance value
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c94526bcdcd7..0fe18a647f95 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -17395,13 +17395,6 @@ public final class Settings {
/**
- * Whether back preview animations are played when user does a back gesture or presses
- * the back button.
- * @hide
- */
- public static final String ENABLE_BACK_ANIMATION = "enable_back_animation";
-
- /**
* An allow list of packages for which the user has granted the permission to communicate
* across profiles.
*
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index 5c38a1597433..195896dc8edf 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -81,7 +81,7 @@ public final class InputEventConsistencyVerifier {
// Bitfield of pointer ids that are currently down.
// Assumes that the largest possible pointer id is 31, which is potentially subject to change.
- // (See MAX_POINTER_ID in frameworks/base/include/ui/Input.h)
+ // (See MAX_POINTER_ID in frameworks/native/include/input/input.h)
private int mTouchEventStreamPointers;
// The device id and source of the current stream of touch events.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 833f2d98554e..e665c08c63e4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -160,6 +160,10 @@ public final class SurfaceControl implements Parcelable {
float l, float t, float r, float b);
private static native void nativeSetCornerRadius(long transactionObj, long nativeObject,
float cornerRadius);
+ private static native void nativeSetClientDrawnCornerRadius(long transactionObj,
+ long nativeObject, float clientDrawnCornerRadius);
+ private static native void nativeSetClientDrawnShadows(long transactionObj,
+ long nativeObject, float clientDrawnShadows);
private static native void nativeSetBackgroundBlurRadius(long transactionObj, long nativeObject,
int blurRadius);
private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
@@ -3654,6 +3658,66 @@ public final class SurfaceControl implements Parcelable {
return this;
}
+
+ /**
+ * Disables corner radius of a {@link SurfaceControl}. When the radius set by
+ * {@link Transaction#setCornerRadius(SurfaceControl, float)} is equal to
+ * clientDrawnCornerRadius the corner radius drawn by SurfaceFlinger is disabled.
+ *
+ * @param sc SurfaceControl
+ * @param clientDrawnCornerRadius Corner radius drawn by the client
+ * @return Itself.
+ * @hide
+ */
+ @NonNull
+ public Transaction setClientDrawnCornerRadius(@NonNull SurfaceControl sc,
+ float clientDrawnCornerRadius) {
+ checkPreconditions(sc);
+ if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
+ SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
+ "setClientDrawnCornerRadius", this, sc, "clientDrawnCornerRadius="
+ + clientDrawnCornerRadius);
+ }
+ if (Flags.ignoreCornerRadiusAndShadows()) {
+ nativeSetClientDrawnCornerRadius(mNativeObject, sc.mNativeObject,
+ clientDrawnCornerRadius);
+ } else {
+ Log.w(TAG, "setClientDrawnCornerRadius was called but"
+ + "ignore_corner_radius_and_shadows flag is disabled");
+ }
+
+ return this;
+ }
+
+ /**
+ * Disables shadows of a {@link SurfaceControl}. When the radius set by
+ * {@link Transaction#setClientDrawnShadows(SurfaceControl, float)} is equal to
+ * clientDrawnShadowRadius the shadows drawn by SurfaceFlinger is disabled.
+ *
+ * @param sc SurfaceControl
+ * @param clientDrawnShadowRadius Shadow radius drawn by the client
+ * @return Itself.
+ * @hide
+ */
+ @NonNull
+ public Transaction setClientDrawnShadows(@NonNull SurfaceControl sc,
+ float clientDrawnShadowRadius) {
+ checkPreconditions(sc);
+ if (SurfaceControlRegistry.sCallStackDebuggingEnabled) {
+ SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging(
+ "setClientDrawnShadows", this, sc,
+ "clientDrawnShadowRadius=" + clientDrawnShadowRadius);
+ }
+ if (Flags.ignoreCornerRadiusAndShadows()) {
+ nativeSetClientDrawnShadows(mNativeObject, sc.mNativeObject,
+ clientDrawnShadowRadius);
+ } else {
+ Log.w(TAG, "setClientDrawnShadows was called but"
+ + "ignore_corner_radius_and_shadows flag is disabled");
+ }
+ return this;
+ }
+
/**
* Sets the background blur radius of the {@link SurfaceControl}.
*
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 1f341caa8ed3..6d2c0d0061dd 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -30,7 +30,8 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
public interface WindowManagerPolicyConstants {
- // Policy flags. These flags are also defined in frameworks/base/include/ui/Input.h and
+ // Policy flags. These flags are also defined in
+ // frameworks/native/include/input/Input.h and
// frameworks/native/libs/input/android/os/IInputConstants.aidl
int FLAG_WAKE = 0x00000001;
int FLAG_VIRTUAL = 0x00000002;
diff --git a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
index b3bd92b37357..c871d568e625 100644
--- a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
+++ b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
@@ -45,3 +45,10 @@ flag {
description: "If true, the APIs to manage content protection device policy will be enabled."
bug: "319477846"
}
+
+flag {
+ name: "exported_settings_activity_enabled"
+ namespace: "content_protection"
+ description: "If true, the content protection Settings Activity will be exported for launching externally."
+ bug: "385310141"
+}
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index bb4770768cb1..8ff2e6aebdd0 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -91,6 +91,14 @@ flag {
}
flag {
+ name: "ignore_corner_radius_and_shadows"
+ namespace: "window_surfaces"
+ description: "Ignore the corner radius and shadows of a SurfaceControl"
+ bug: "375624570"
+ is_fixed_read_only: true
+} # ignore_corner_radius_and_shadows
+
+flag {
name: "jank_api"
namespace: "window_surfaces"
description: "Adds the jank data listener to AttachedSurfaceControl"
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index a8641326b1f2..de3e0d3faf43 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -113,13 +113,6 @@ flag {
}
flag {
- name: "predictive_back_system_anims"
- namespace: "systemui"
- description: "Predictive back for system animations"
- bug: "320510464"
-}
-
-flag {
name: "remove_activity_starter_dream_callback"
namespace: "windowing_frontend"
description: "Avoid a race with DreamManagerService callbacks for isDreaming by checking Activity state directly"
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index d62c8f378af0..73c2265d5f6e 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -53,21 +53,21 @@ oneway interface IKeyguardService {
*
* @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the specific reason
* we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT.
- * @param cameraGestureTriggered whether the camera gesture was triggered between
- * {@link #onStartedGoingToSleep} and this method; if it's been
- * triggered, we shouldn't lock the device.
+ * @param powerButtonLaunchGestureTriggered whether the power button double tap gesture was
+ * triggered between {@link #onStartedGoingToSleep} and this
+ * method; if it's been triggered, we shouldn't lock the device.
*/
- void onFinishedGoingToSleep(int pmSleepReason, boolean cameraGestureTriggered);
+ void onFinishedGoingToSleep(int pmSleepReason, boolean powerButtonLaunchGestureTriggered);
/**
* Called when the device has started waking up.
* @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the reason we're waking up,
* such as WAKE_REASON_POWER_BUTTON or WAKE_REASON_GESTURE.
- * @param cameraGestureTriggered Whether we're waking up due to a power button double tap
- * gesture.
+ * @param powerButtonLaunchGestureTriggered Whether we're waking up due to a power button
+ * double tap gesture.
*/
- void onStartedWakingUp(int pmWakeReason, boolean cameraGestureTriggered);
+ void onStartedWakingUp(int pmWakeReason, boolean powerButtonLaunchGestureTriggered);
/**
* Called when the device has finished waking up.
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 1e7bfe32ba79..e6364a96bd9f 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -111,9 +111,8 @@ static void DeleteGuardedApkAssets(Guarded<AssetManager2::ApkAssetsPtr>& apk_ass
class LoaderAssetsProvider : public AssetsProvider {
public:
static std::unique_ptr<AssetsProvider> Create(JNIEnv* env, jobject assets_provider) {
- return (!assets_provider) ? EmptyAssetsProvider::Create()
- : std::unique_ptr<AssetsProvider>(new LoaderAssetsProvider(
- env, assets_provider));
+ return std::unique_ptr<AssetsProvider>{
+ assets_provider ? new LoaderAssetsProvider(env, assets_provider) : nullptr};
}
bool ForEachFile(const std::string& /* root_path */,
@@ -129,8 +128,8 @@ class LoaderAssetsProvider : public AssetsProvider {
return debug_name_;
}
- bool IsUpToDate() const override {
- return true;
+ UpToDate IsUpToDate() const override {
+ return UpToDate::Always;
}
~LoaderAssetsProvider() override {
@@ -212,7 +211,7 @@ class LoaderAssetsProvider : public AssetsProvider {
auto string_result = static_cast<jstring>(env->CallObjectMethod(
assets_provider_, gAssetsProviderOffsets.toString));
ScopedUtfChars str(env, string_result);
- debug_name_ = std::string(str.c_str(), str.size());
+ debug_name_ = std::string(str.c_str());
}
// The global reference to the AssetsProvider
@@ -243,10 +242,10 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma
apk_assets = ApkAssets::LoadOverlay(path.c_str(), property_flags);
break;
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFile(path.c_str()),
- std::move(loader_assets),
- property_flags);
- break;
+ apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFile(path.c_str()),
+ MultiAssetsProvider::Create(std::move(loader_assets)),
+ property_flags);
+ break;
case FORMAT_DIRECTORY: {
auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
DirectoryAssetsProvider::Create(path.c_str()));
@@ -316,10 +315,11 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t
break;
}
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTable(
- AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */),
- std::move(loader_assets), property_flags);
- break;
+ apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFd(std::move(dup_fd),
+ nullptr /* path */),
+ MultiAssetsProvider::Create(std::move(loader_assets)),
+ property_flags);
+ break;
default:
const std::string error_msg = base::StringPrintf("Unsupported format type %d", format);
jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
@@ -386,12 +386,15 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
break;
}
case FORMAT_ARSC:
- apk_assets = ApkAssets::LoadTable(
- AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */,
- static_cast<off64_t>(offset),
- static_cast<off64_t>(length)),
- std::move(loader_assets), property_flags);
- break;
+ apk_assets =
+ ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFd(std::move(dup_fd),
+ nullptr /* path */,
+ static_cast<off64_t>(offset),
+ static_cast<off64_t>(
+ length)),
+ MultiAssetsProvider::Create(std::move(loader_assets)),
+ property_flags);
+ break;
default:
const std::string error_msg = base::StringPrintf("Unsupported format type %d", format);
jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str());
@@ -408,13 +411,16 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
}
static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) {
- auto apk_assets = ApkAssets::Load(LoaderAssetsProvider::Create(env, assets_provider), flags);
- if (apk_assets == nullptr) {
- const std::string error_msg =
- base::StringPrintf("Failed to load empty assets with provider %p", (void*)assets_provider);
- jniThrowException(env, "java/io/IOException", error_msg.c_str());
- return 0;
- }
+ auto apk_assets = ApkAssets::Load(MultiAssetsProvider::Create(
+ LoaderAssetsProvider::Create(env, assets_provider)),
+ flags);
+ if (apk_assets == nullptr) {
+ const std::string error_msg =
+ base::StringPrintf("Failed to load empty assets with provider %p",
+ (void*)assets_provider);
+ jniThrowException(env, "java/io/IOException", error_msg.c_str());
+ return 0;
+ }
return CreateGuardedApkAssets(std::move(apk_assets));
}
@@ -443,10 +449,10 @@ static jlong NativeGetStringBlock(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr)
return reinterpret_cast<jlong>(apk_assets->GetLoadedArsc()->GetStringPool());
}
-static jboolean NativeIsUpToDate(CRITICAL_JNI_PARAMS_COMMA jlong ptr) {
+static jint NativeIsUpToDate(CRITICAL_JNI_PARAMS_COMMA jlong ptr) {
auto scoped_apk_assets = ScopedLock(ApkAssetsFromLong(ptr));
auto apk_assets = scoped_apk_assets->get();
- return apk_assets->IsUpToDate() ? JNI_TRUE : JNI_FALSE;
+ return (jint)apk_assets->IsUpToDate();
}
static jlong NativeOpenXml(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring file_name) {
@@ -558,7 +564,7 @@ static const JNINativeMethod gApkAssetsMethods[] = {
{"nativeGetDebugName", "(J)Ljava/lang/String;", (void*)NativeGetDebugName},
{"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
// @CriticalNative
- {"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
+ {"nativeIsUpToDate", "(J)I", (void*)NativeIsUpToDate},
{"nativeOpenXml", "(JLjava/lang/String;)J", (void*)NativeOpenXml},
{"nativeGetOverlayableInfo", "(JLjava/lang/String;)Landroid/content/om/OverlayableInfo;",
(void*)NativeGetOverlayableInfo},
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0c243d1dc185..6f69e4005b80 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1113,6 +1113,22 @@ static void nativeSetCornerRadius(JNIEnv* env, jclass clazz, jlong transactionOb
transaction->setCornerRadius(ctrl, cornerRadius);
}
+static void nativeSetClientDrawnCornerRadius(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat clientDrawnCornerRadius) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setClientDrawnCornerRadius(ctrl, clientDrawnCornerRadius);
+}
+
+static void nativeSetClientDrawnShadows(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat clientDrawnShadowRadius) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setClientDrawnShadowRadius(ctrl, clientDrawnShadowRadius);
+}
+
static void nativeSetBackgroundBlurRadius(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint blurRadius) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -2547,6 +2563,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetCrop },
{"nativeSetCornerRadius", "(JJF)V",
(void*)nativeSetCornerRadius },
+ {"nativeSetClientDrawnCornerRadius", "(JJF)V",
+ (void*) nativeSetClientDrawnCornerRadius },
+ {"nativeSetClientDrawnShadows", "(JJF)V",
+ (void*) nativeSetClientDrawnShadows },
{"nativeSetBackgroundBlurRadius", "(JJI)V",
(void*)nativeSetBackgroundBlurRadius },
{"nativeSetLayerStack", "(JJI)V",
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index 37ef6cba8814..939bf2ec4b0a 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -207,7 +207,8 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
final ComponentInfo info = new ComponentInfo();
info.applicationInfo = new ApplicationInfo();
info.applicationInfo.uid = uid;
- return new RegisteredServicesCache.ServiceInfo<>(type, info, null);
+ return new RegisteredServicesCache.ServiceInfo<>(type, info, null /* componentName */,
+ 0 /* lastUpdateTime */);
}
private void assertNotEmptyFileCreated(TestServicesCache cache, int userId) {
@@ -301,7 +302,7 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
@Override
protected ServiceInfo<TestServiceType> parseServiceInfo(
- ResolveInfo resolveInfo) throws XmlPullParserException, IOException {
+ ResolveInfo resolveInfo, int userId) throws XmlPullParserException, IOException {
int size = mServices.size();
for (int i = 0; i < size; i++) {
Map<ResolveInfo, ServiceInfo<TestServiceType>> map = mServices.valueAt(i);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index e96bc02c1198..cacfbfaac954 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -28,7 +28,6 @@ import static android.window.TransitionInfo.FLAG_MOVED_TO_TOP;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_HOME;
-import static com.android.window.flags.Flags.predictiveBackSystemAnims;
import static com.android.window.flags.Flags.unifyBackNavigationTransition;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
@@ -40,23 +39,17 @@ import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.TaskInfo;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Configuration;
-import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.input.InputManager;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings.Global;
import android.util.Log;
import android.view.IRemoteAnimationRunner;
import android.view.InputDevice;
@@ -92,7 +85,6 @@ import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.shared.TransitionUtil;
-import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellCommandHandler;
@@ -102,7 +94,6 @@ import com.android.wm.shell.transition.Transitions;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
/**
@@ -111,14 +102,7 @@ import java.util.function.Predicate;
public class BackAnimationController implements RemoteCallable<BackAnimationController>,
ConfigurationChangeListener {
private static final String TAG = "ShellBackPreview";
- private static final int SETTING_VALUE_OFF = 0;
- private static final int SETTING_VALUE_ON = 1;
- public static final boolean IS_ENABLED =
- SystemProperties.getInt("persist.wm.debug.predictive_back",
- SETTING_VALUE_ON) == SETTING_VALUE_ON;
-
- /** Predictive back animation developer option */
- private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
+
/**
* Max duration to wait for an animation to finish before triggering the real back.
*/
@@ -148,11 +132,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private boolean mReceivedNullNavigationInfo = false;
private final IActivityTaskManager mActivityTaskManager;
private final Context mContext;
- private final ContentResolver mContentResolver;
private final ShellController mShellController;
private final ShellCommandHandler mShellCommandHandler;
private final ShellExecutor mShellExecutor;
- private final Handler mBgHandler;
private final WindowManager mWindowManager;
private final Transitions mTransitions;
@VisibleForTesting
@@ -245,7 +227,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@NonNull @ShellMainThread ShellExecutor shellExecutor,
- @NonNull @ShellBackgroundThread Handler backgroundHandler,
Context context,
@NonNull BackAnimationBackground backAnimationBackground,
ShellBackAnimationRegistry shellBackAnimationRegistry,
@@ -256,10 +237,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
shellInit,
shellController,
shellExecutor,
- backgroundHandler,
ActivityTaskManager.getService(),
context,
- context.getContentResolver(),
backAnimationBackground,
shellBackAnimationRegistry,
shellCommandHandler,
@@ -272,10 +251,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@NonNull @ShellMainThread ShellExecutor shellExecutor,
- @NonNull @ShellBackgroundThread Handler bgHandler,
@NonNull IActivityTaskManager activityTaskManager,
Context context,
- ContentResolver contentResolver,
@NonNull BackAnimationBackground backAnimationBackground,
ShellBackAnimationRegistry shellBackAnimationRegistry,
ShellCommandHandler shellCommandHandler,
@@ -285,10 +262,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mShellExecutor = shellExecutor;
mActivityTaskManager = activityTaskManager;
mContext = context;
- mContentResolver = contentResolver;
mRequirePointerPilfer =
context.getResources().getBoolean(R.bool.config_backAnimationRequiresPointerPilfer);
- mBgHandler = bgHandler;
shellInit.addInitCallback(this::onInit, this);
mAnimationBackground = backAnimationBackground;
mShellBackAnimationRegistry = shellBackAnimationRegistry;
@@ -305,8 +280,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
private void onInit() {
- setupAnimationDeveloperSettingsObserver(mContentResolver, mBgHandler);
- updateEnableAnimationFromFlags();
createAdapter();
mShellController.addExternalInterface(IBackAnimation.DESCRIPTOR,
this::createExternalInterface, this);
@@ -314,42 +287,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mShellController.addConfigurationChangeListener(this);
}
- private void setupAnimationDeveloperSettingsObserver(
- @NonNull ContentResolver contentResolver,
- @NonNull @ShellBackgroundThread final Handler backgroundHandler) {
- if (predictiveBackSystemAnims()) {
- ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation aconfig flag is enabled, therefore "
- + "developer settings flag is ignored and no content observer registered");
- return;
- }
- ContentObserver settingsObserver = new ContentObserver(backgroundHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updateEnableAnimationFromFlags();
- }
- };
- contentResolver.registerContentObserver(
- Global.getUriFor(Global.ENABLE_BACK_ANIMATION),
- false, settingsObserver, UserHandle.USER_SYSTEM
- );
- }
-
- /**
- * Updates {@link BackAnimationController#mEnableAnimations} based on the current values of the
- * aconfig flag and the developer settings flag
- */
- @ShellBackgroundThread
- private void updateEnableAnimationFromFlags() {
- boolean isEnabled = predictiveBackSystemAnims() || isDeveloperSettingEnabled();
- mEnableAnimations.set(isEnabled);
- ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", isEnabled);
- }
-
- private boolean isDeveloperSettingEnabled() {
- return Global.getInt(mContext.getContentResolver(),
- Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF) == SETTING_VALUE_ON;
- }
-
public BackAnimation getBackAnimationImpl() {
return mBackAnimation;
}
@@ -617,14 +554,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
try {
startLatencyTracking();
- final BackAnimationAdapter adapter = mEnableAnimations.get()
- ? mBackAnimationAdapter : null;
- if (adapter != null && mShellBackAnimationRegistry.hasSupportedAnimatorsChanged()) {
- adapter.updateSupportedAnimators(
+ if (mBackAnimationAdapter != null
+ && mShellBackAnimationRegistry.hasSupportedAnimatorsChanged()) {
+ mBackAnimationAdapter.updateSupportedAnimators(
mShellBackAnimationRegistry.getSupportedAnimators());
}
mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
- mNavigationObserver, adapter);
+ mNavigationObserver, mBackAnimationAdapter);
onBackNavigationInfoReceived(mBackNavigationInfo, touchTracker);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -696,9 +632,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
private boolean shouldDispatchToAnimator() {
- return mEnableAnimations.get()
- && mBackNavigationInfo != null
- && mBackNavigationInfo.isPrepareRemoteAnimation();
+ return mBackNavigationInfo != null && mBackNavigationInfo.isPrepareRemoteAnimation();
}
private void tryPilferPointers() {
@@ -1194,7 +1128,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
*/
private void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "BackAnimationController state:");
- pw.println(prefix + " mEnableAnimations=" + mEnableAnimations.get());
pw.println(prefix + " mBackGestureStarted=" + mBackGestureStarted);
pw.println(prefix + " mPostCommitAnimationInProgress=" + mPostCommitAnimationInProgress);
pw.println(prefix + " mShouldStartOnNextMoveEvent=" + mShouldStartOnNextMoveEvent);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 1408b6efc7f9..2600bcc18f72 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -108,7 +108,6 @@ import com.android.wm.shell.recents.TaskStackTransitionObserver;
import com.android.wm.shell.shared.ShellTransitions;
import com.android.wm.shell.shared.TransactionPool;
import com.android.wm.shell.shared.annotations.ShellAnimationThread;
-import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.annotations.ShellSplashscreenThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -438,29 +437,24 @@ public abstract class WMShellBaseModule {
ShellInit shellInit,
ShellController shellController,
@ShellMainThread ShellExecutor shellExecutor,
- @ShellBackgroundThread Handler backgroundHandler,
BackAnimationBackground backAnimationBackground,
Optional<ShellBackAnimationRegistry> shellBackAnimationRegistry,
ShellCommandHandler shellCommandHandler,
Transitions transitions,
@ShellMainThread Handler handler
) {
- if (BackAnimationController.IS_ENABLED) {
return shellBackAnimationRegistry.map(
(animations) ->
new BackAnimationController(
shellInit,
shellController,
shellExecutor,
- backgroundHandler,
context,
backAnimationBackground,
animations,
shellCommandHandler,
transitions,
handler));
- }
- return Optional.empty();
}
@BindsOptionalOf
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index 03f388c9f1c9..9e2b9b20be16 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -117,6 +117,7 @@ public abstract class Pip2Module {
PipTouchHandler pipTouchHandler,
PipAppOpsListener pipAppOpsListener,
PhonePipMenuController pipMenuController,
+ PipUiEventLogger pipUiEventLogger,
@ShellMainThread ShellExecutor mainExecutor) {
if (!PipUtils.isPip2ExperimentEnabled()) {
return Optional.empty();
@@ -126,7 +127,7 @@ public abstract class Pip2Module {
displayInsetsController, pipBoundsState, pipBoundsAlgorithm,
pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer,
pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController,
- mainExecutor));
+ pipUiEventLogger, mainExecutor));
}
}
@@ -188,11 +189,11 @@ public abstract class Pip2Module {
FloatingContentCoordinator floatingContentCoordinator,
PipScheduler pipScheduler,
Optional<PipPerfHintController> pipPerfHintControllerOptional,
- PipBoundsAlgorithm pipBoundsAlgorithm,
- PipTransitionState pipTransitionState) {
+ PipTransitionState pipTransitionState,
+ PipUiEventLogger pipUiEventLogger) {
return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
floatingContentCoordinator, pipScheduler, pipPerfHintControllerOptional,
- pipBoundsAlgorithm, pipTransitionState);
+ pipTransitionState, pipUiEventLogger);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
index 8c6d5f5c6660..562b26014bf3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java
@@ -59,6 +59,7 @@ import com.android.wm.shell.common.pip.PipAppOpsListener;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
+import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -98,6 +99,7 @@ public class PipController implements ConfigurationChangeListener,
private final PipTouchHandler mPipTouchHandler;
private final PipAppOpsListener mPipAppOpsListener;
private final PhonePipMenuController mPipMenuController;
+ private final PipUiEventLogger mPipUiEventLogger;
private final ShellExecutor mMainExecutor;
private final PipImpl mImpl;
private final List<Consumer<Boolean>> mOnIsInPipStateChangedListeners = new ArrayList<>();
@@ -143,6 +145,7 @@ public class PipController implements ConfigurationChangeListener,
PipTouchHandler pipTouchHandler,
PipAppOpsListener pipAppOpsListener,
PhonePipMenuController pipMenuController,
+ PipUiEventLogger pipUiEventLogger,
ShellExecutor mainExecutor) {
mContext = context;
mShellCommandHandler = shellCommandHandler;
@@ -160,6 +163,7 @@ public class PipController implements ConfigurationChangeListener,
mPipTouchHandler = pipTouchHandler;
mPipAppOpsListener = pipAppOpsListener;
mPipMenuController = pipMenuController;
+ mPipUiEventLogger = pipUiEventLogger;
mMainExecutor = mainExecutor;
mImpl = new PipImpl();
@@ -187,6 +191,7 @@ public class PipController implements ConfigurationChangeListener,
PipTouchHandler pipTouchHandler,
PipAppOpsListener pipAppOpsListener,
PhonePipMenuController pipMenuController,
+ PipUiEventLogger pipUiEventLogger,
ShellExecutor mainExecutor) {
if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
@@ -197,7 +202,7 @@ public class PipController implements ConfigurationChangeListener,
displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm,
pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer,
pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController,
- mainExecutor);
+ pipUiEventLogger, mainExecutor);
}
public PipImpl getPipImpl() {
@@ -238,18 +243,6 @@ public class PipController implements ConfigurationChangeListener,
});
mPipAppOpsListener.setCallback(mPipTouchHandler.getMotionHelper());
- mPipTransitionState.addPipTransitionStateChangedListener(
- (oldState, newState, extra) -> {
- if (newState == PipTransitionState.ENTERED_PIP) {
- final TaskInfo taskInfo = mPipTransitionState.getPipTaskInfo();
- if (taskInfo != null && taskInfo.topActivity != null) {
- mPipAppOpsListener.onActivityPinned(
- taskInfo.topActivity.getPackageName());
- }
- } else if (newState == PipTransitionState.EXITED_PIP) {
- mPipAppOpsListener.onActivityUnpinned();
- }
- });
}
private ExternalInterfaceBinder createExternalInterface() {
@@ -446,14 +439,25 @@ public class PipController implements ConfigurationChangeListener,
mPipTransitionState.setSwipePipToHomeState(overlay, appBounds);
break;
case PipTransitionState.ENTERED_PIP:
+ final TaskInfo taskInfo = mPipTransitionState.getPipTaskInfo();
+ if (taskInfo != null && taskInfo.topActivity != null) {
+ mPipAppOpsListener.onActivityPinned(taskInfo.topActivity.getPackageName());
+ mPipUiEventLogger.setTaskInfo(taskInfo);
+ }
if (mPipTransitionState.isInSwipePipToHomeTransition()) {
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_AUTO_ENTER);
mPipTransitionState.resetSwipePipToHomeState();
+ } else {
+ mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
}
for (Consumer<Boolean> listener : mOnIsInPipStateChangedListeners) {
listener.accept(true /* inPip */);
}
break;
case PipTransitionState.EXITED_PIP:
+ mPipAppOpsListener.onActivityUnpinned();
+ mPipUiEventLogger.setTaskInfo(null);
for (Consumer<Boolean> listener : mOnIsInPipStateChangedListeners) {
listener.accept(false /* inPip */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
index 37296531ee34..9babe9e9e4eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
@@ -43,20 +43,20 @@ import com.android.wm.shell.R;
import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.pip.PipAppOpsListener;
-import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
+import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.pip2.animation.PipResizeAnimator;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.animation.PhysicsAnimator;
import com.android.wm.shell.shared.magnetictarget.MagnetizedObject;
+import java.util.Optional;
+
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
-import java.util.Optional;
-
/**
* A helper to animate and manipulate the PiP.
*/
@@ -80,12 +80,12 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private static final float DISMISS_CIRCLE_PERCENT = 0.85f;
private final Context mContext;
- private @NonNull PipBoundsState mPipBoundsState;
- private @NonNull PipBoundsAlgorithm mPipBoundsAlgorithm;
- private @NonNull PipScheduler mPipScheduler;
- private @NonNull PipTransitionState mPipTransitionState;
- private PhonePipMenuController mMenuController;
- private PipSnapAlgorithm mSnapAlgorithm;
+ @NonNull private final PipBoundsState mPipBoundsState;
+ @NonNull private final PipScheduler mPipScheduler;
+ @NonNull private final PipTransitionState mPipTransitionState;
+ @NonNull private final PipUiEventLogger mPipUiEventLogger;
+ private final PhonePipMenuController mMenuController;
+ private final PipSnapAlgorithm mSnapAlgorithm;
/** The region that all of PIP must stay within. */
private final Rect mFloatingAllowedArea = new Rect();
@@ -168,10 +168,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
PhonePipMenuController menuController, PipSnapAlgorithm snapAlgorithm,
FloatingContentCoordinator floatingContentCoordinator, PipScheduler pipScheduler,
Optional<PipPerfHintController> pipPerfHintControllerOptional,
- PipBoundsAlgorithm pipBoundsAlgorithm, PipTransitionState pipTransitionState) {
+ PipTransitionState pipTransitionState, PipUiEventLogger pipUiEventLogger) {
mContext = context;
mPipBoundsState = pipBoundsState;
- mPipBoundsAlgorithm = pipBoundsAlgorithm;
mPipScheduler = pipScheduler;
mMenuController = menuController;
mSnapAlgorithm = snapAlgorithm;
@@ -185,6 +184,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
};
mPipTransitionState = pipTransitionState;
mPipTransitionState.addPipTransitionStateChangedListener(this);
+ mPipUiEventLogger = pipUiEventLogger;
}
void init() {
@@ -850,9 +850,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
if (mPipBoundsState.getBounds().left < 0
&& mPipBoundsState.getStashedState() != STASH_TYPE_LEFT) {
mPipBoundsState.setStashed(STASH_TYPE_LEFT);
+ mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_LEFT);
} else if (mPipBoundsState.getBounds().left >= 0
&& mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) {
mPipBoundsState.setStashed(STASH_TYPE_RIGHT);
+ mPipUiEventLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_RIGHT);
}
mMenuController.hideMenu();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationController.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationController.aidl
index 964e5fd62a5f..af1679f2d175 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationController.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationController.aidl
@@ -36,12 +36,6 @@ import com.android.internal.os.IResultReceiver;
interface IRecentsAnimationController {
/**
- * Takes a screenshot of the task associated with the given {@param taskId}. Only valid for the
- * current set of task ids provided to the handler.
- */
- TaskSnapshot screenshotTask(int taskId);
-
- /**
* Sets the final surface transaction on a Task. This is used by Launcher to notify the system
* that animating Activity to PiP has completed and the associated task surface should be
* updated accordingly. This should be called before `finish`
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 032dac9ff3a2..76496b06a4dd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -1227,19 +1227,6 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler,
}
@Override
- public TaskSnapshot screenshotTask(int taskId) {
- try {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- "[%d] RecentsController.screenshotTask: taskId=%d", mInstanceId, taskId);
- return ActivityTaskManager.getService().takeTaskSnapshot(taskId,
- true /* updateCache */);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to screenshot task", e);
- }
- return null;
- }
-
- @Override
public void setInputConsumerEnabled(boolean enabled) {
mExecutor.execute(() -> {
if (mFinishCB == null || !enabled) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 47ee7bb20199..bbdb90f0a37c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -61,9 +61,7 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import android.provider.Settings;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableContentResolver;
import android.testing.TestableLooper;
import android.view.IRemoteAnimationRunner;
import android.view.KeyEvent;
@@ -84,7 +82,6 @@ import android.window.WindowContainerToken;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.internal.util.test.FakeSettingsProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
@@ -109,7 +106,6 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
public class BackAnimationControllerTest extends ShellTestCase {
- private static final String ANIMATION_ENABLED = "1";
private final TestShellExecutor mShellExecutor = new TestShellExecutor();
private ShellInit mShellInit;
@@ -148,8 +144,6 @@ public class BackAnimationControllerTest extends ShellTestCase {
private Transitions.TransitionHandler mTakeoverHandler;
private BackAnimationController mController;
- private TestableContentResolver mContentResolver;
- private TestableLooper mTestableLooper;
private DefaultCrossActivityBackAnimation mDefaultCrossActivityBackAnimation;
private CrossTaskBackAnimation mCrossTaskBackAnimation;
@@ -166,11 +160,6 @@ public class BackAnimationControllerTest extends ShellTestCase {
MockitoAnnotations.initMocks(this);
mContext.addMockSystemService(InputManager.class, mInputManager);
mContext.getApplicationInfo().privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
- mContentResolver = new TestableContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- Settings.Global.putString(mContentResolver, Settings.Global.ENABLE_BACK_ANIMATION,
- ANIMATION_ENABLED);
- mTestableLooper = TestableLooper.get(this);
mShellInit = spy(new ShellInit(mShellExecutor));
mDefaultCrossActivityBackAnimation = new DefaultCrossActivityBackAnimation(mContext,
mAnimationBackground, mRootTaskDisplayAreaOrganizer, mHandler);
@@ -187,10 +176,8 @@ public class BackAnimationControllerTest extends ShellTestCase {
mShellInit,
mShellController,
mShellExecutor,
- new Handler(mTestableLooper.getLooper()),
mActivityTaskManager,
mContext,
- mContentResolver,
mAnimationBackground,
mShellBackAnimationRegistry,
mShellCommandHandler,
@@ -342,47 +329,6 @@ public class BackAnimationControllerTest extends ShellTestCase {
}
@Test
- public void animationDisabledFromSettings() throws RemoteException {
- // Toggle the setting off
- Settings.Global.putString(mContentResolver, Settings.Global.ENABLE_BACK_ANIMATION, "0");
- ShellInit shellInit = new ShellInit(mShellExecutor);
- mController =
- new BackAnimationController(
- shellInit,
- mShellController,
- mShellExecutor,
- new Handler(mTestableLooper.getLooper()),
- mActivityTaskManager,
- mContext,
- mContentResolver,
- mAnimationBackground,
- mShellBackAnimationRegistry,
- mShellCommandHandler,
- mTransitions,
- mHandler);
- shellInit.init();
- registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
-
- ArgumentCaptor<BackMotionEvent> backEventCaptor =
- ArgumentCaptor.forClass(BackMotionEvent.class);
-
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
- /* enableAnimation = */ false,
- /* isAnimationCallback = */ false);
-
- triggerBackGesture();
- releaseBackGesture();
-
- verify(mAppCallback, times(1)).onBackInvoked();
-
- verify(mAnimatorCallback, never()).onBackStarted(any());
- verify(mAnimatorCallback, never()).onBackProgressed(backEventCaptor.capture());
- verify(mAnimatorCallback, never()).onBackInvoked();
- verify(mBackAnimationRunner, never()).onAnimationStart(
- anyInt(), any(), any(), any(), any());
- }
-
- @Test
public void gestureQueued_WhenPreviousTransitionHasNotYetEnded() throws RemoteException {
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index dbb891455ddd..e693fcfd3918 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -162,10 +162,13 @@ const std::string& ApkAssets::GetDebugName() const {
return assets_provider_->GetDebugName();
}
-bool ApkAssets::IsUpToDate() const {
+UpToDate ApkAssets::IsUpToDate() const {
// Loaders are invalidated by the app, not the system, so assume they are up to date.
- return IsLoader() || ((!loaded_idmap_ || loaded_idmap_->IsUpToDate())
- && assets_provider_->IsUpToDate());
+ if (IsLoader()) {
+ return UpToDate::Always;
+ }
+ const auto idmap_res = loaded_idmap_ ? loaded_idmap_->IsUpToDate() : UpToDate::Always;
+ return combine(idmap_res, [this] { return assets_provider_->IsUpToDate(); });
}
} // namespace android
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
index 2d3c06506a1f..11b12eb030a6 100644
--- a/libs/androidfw/AssetsProvider.cpp
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -24,9 +24,8 @@
#include <ziparchive/zip_archive.h>
namespace android {
-namespace {
-constexpr const char* kEmptyDebugString = "<empty>";
-} // namespace
+
+static constexpr std::string_view kEmptyDebugString = "<empty>";
std::unique_ptr<Asset> AssetsProvider::Open(const std::string& path, Asset::AccessMode mode,
bool* file_exists) const {
@@ -86,11 +85,9 @@ void ZipAssetsProvider::ZipCloser::operator()(ZipArchive* a) const {
}
ZipAssetsProvider::ZipAssetsProvider(ZipArchiveHandle handle, PathOrDebugName&& path,
- package_property_t flags, time_t last_mod_time)
- : zip_handle_(handle),
- name_(std::move(path)),
- flags_(flags),
- last_mod_time_(last_mod_time) {}
+ package_property_t flags, ModDate last_mod_time)
+ : zip_handle_(handle), name_(std::move(path)), flags_(flags), last_mod_time_(last_mod_time) {
+}
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
package_property_t flags,
@@ -104,10 +101,10 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
return {};
}
- struct stat sb{.st_mtime = -1};
+ ModDate mod_date = kInvalidModDate;
// Skip all up-to-date checks if the file won't ever change.
- if (!isReadonlyFilesystem(path.c_str())) {
- if ((released_fd < 0 ? stat(path.c_str(), &sb) : fstat(released_fd, &sb)) < 0) {
+ if (isKnownWritablePath(path.c_str()) || !isReadonlyFilesystem(GetFileDescriptor(handle))) {
+ if (mod_date = getFileModDate(GetFileDescriptor(handle)); mod_date == kInvalidModDate) {
// Stat requires execute permissions on all directories path to the file. If the process does
// not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
// always have to return true.
@@ -116,7 +113,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
}
return std::unique_ptr<ZipAssetsProvider>(
- new ZipAssetsProvider(handle, PathOrDebugName::Path(std::move(path)), flags, sb.st_mtime));
+ new ZipAssetsProvider(handle, PathOrDebugName::Path(std::move(path)), flags, mod_date));
}
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
@@ -137,10 +134,10 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
return {};
}
- struct stat sb{.st_mtime = -1};
+ ModDate mod_date = kInvalidModDate;
// Skip all up-to-date checks if the file won't ever change.
if (!isReadonlyFilesystem(released_fd)) {
- if (fstat(released_fd, &sb) < 0) {
+ if (mod_date = getFileModDate(released_fd); mod_date == kInvalidModDate) {
// Stat requires execute permissions on all directories path to the file. If the process does
// not have execute permissions on this file, allow the zip to be opened but IsUpToDate() will
// always have to return true.
@@ -150,7 +147,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
}
return std::unique_ptr<ZipAssetsProvider>(new ZipAssetsProvider(
- handle, PathOrDebugName::DebugName(std::move(friendly_name)), flags, sb.st_mtime));
+ handle, PathOrDebugName::DebugName(std::move(friendly_name)), flags, mod_date));
}
std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
@@ -282,21 +279,16 @@ const std::string& ZipAssetsProvider::GetDebugName() const {
return name_.GetDebugName();
}
-bool ZipAssetsProvider::IsUpToDate() const {
- if (last_mod_time_ == -1) {
- return true;
- }
- struct stat sb{};
- if (fstat(GetFileDescriptor(zip_handle_.get()), &sb) < 0) {
- // If fstat fails on the zip archive, return true so the zip archive the resource system does
- // attempt to refresh the ApkAsset.
- return true;
+UpToDate ZipAssetsProvider::IsUpToDate() const {
+ if (last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
}
- return last_mod_time_ == sb.st_mtime;
+ return fromBool(last_mod_time_ == getFileModDate(GetFileDescriptor(zip_handle_.get())));
}
-DirectoryAssetsProvider::DirectoryAssetsProvider(std::string&& path, time_t last_mod_time)
- : dir_(std::move(path)), last_mod_time_(last_mod_time) {}
+DirectoryAssetsProvider::DirectoryAssetsProvider(std::string&& path, ModDate last_mod_time)
+ : dir_(std::move(path)), last_mod_time_(last_mod_time) {
+}
std::unique_ptr<DirectoryAssetsProvider> DirectoryAssetsProvider::Create(std::string path) {
struct stat sb;
@@ -317,7 +309,7 @@ std::unique_ptr<DirectoryAssetsProvider> DirectoryAssetsProvider::Create(std::st
const bool isReadonly = isReadonlyFilesystem(path.c_str());
return std::unique_ptr<DirectoryAssetsProvider>(
- new DirectoryAssetsProvider(std::move(path), isReadonly ? -1 : sb.st_mtime));
+ new DirectoryAssetsProvider(std::move(path), isReadonly ? kInvalidModDate : getModDate(sb)));
}
std::unique_ptr<Asset> DirectoryAssetsProvider::OpenInternal(const std::string& path,
@@ -346,17 +338,11 @@ const std::string& DirectoryAssetsProvider::GetDebugName() const {
return dir_;
}
-bool DirectoryAssetsProvider::IsUpToDate() const {
- if (last_mod_time_ == -1) {
- return true;
- }
- struct stat sb;
- if (stat(dir_.c_str(), &sb) < 0) {
- // If stat fails on the zip archive, return true so the zip archive the resource system does
- // attempt to refresh the ApkAsset.
- return true;
+UpToDate DirectoryAssetsProvider::IsUpToDate() const {
+ if (last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
}
- return last_mod_time_ == sb.st_mtime;
+ return fromBool(last_mod_time_ == getFileModDate(dir_.c_str()));
}
MultiAssetsProvider::MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& primary,
@@ -369,8 +355,14 @@ MultiAssetsProvider::MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& prima
std::unique_ptr<AssetsProvider> MultiAssetsProvider::Create(
std::unique_ptr<AssetsProvider>&& primary, std::unique_ptr<AssetsProvider>&& secondary) {
- if (primary == nullptr || secondary == nullptr) {
- return nullptr;
+ if (primary == nullptr && secondary == nullptr) {
+ return EmptyAssetsProvider::Create();
+ }
+ if (!primary) {
+ return secondary;
+ }
+ if (!secondary) {
+ return primary;
}
return std::unique_ptr<MultiAssetsProvider>(new MultiAssetsProvider(std::move(primary),
std::move(secondary)));
@@ -397,8 +389,8 @@ const std::string& MultiAssetsProvider::GetDebugName() const {
return debug_name_;
}
-bool MultiAssetsProvider::IsUpToDate() const {
- return primary_->IsUpToDate() && secondary_->IsUpToDate();
+UpToDate MultiAssetsProvider::IsUpToDate() const {
+ return combine(primary_->IsUpToDate(), [this] { return secondary_->IsUpToDate(); });
}
EmptyAssetsProvider::EmptyAssetsProvider(std::optional<std::string>&& path) :
@@ -438,12 +430,12 @@ const std::string& EmptyAssetsProvider::GetDebugName() const {
if (path_.has_value()) {
return *path_;
}
- const static std::string kEmpty = kEmptyDebugString;
+ constexpr static std::string kEmpty{kEmptyDebugString};
return kEmpty;
}
-bool EmptyAssetsProvider::IsUpToDate() const {
- return true;
+UpToDate EmptyAssetsProvider::IsUpToDate() const {
+ return UpToDate::Always;
}
} // namespace android
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 3ecd82b074a1..262e7df185b7 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -22,9 +22,10 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
-#include "androidfw/misc.h"
+#include "androidfw/AssetManager.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
+#include "androidfw/misc.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"
@@ -268,11 +269,16 @@ LoadedIdmap::LoadedIdmap(const std::string& idmap_path, const Idmap_header* head
configurations_(configs),
overlay_entries_(overlay_entries),
string_pool_(std::move(string_pool)),
- idmap_fd_(
- android::base::utf8::open(idmap_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY | O_PATH)),
overlay_apk_path_(overlay_apk_path),
target_apk_path_(target_apk_path),
- idmap_last_mod_time_(getFileModDate(idmap_fd_.get())) {
+ idmap_last_mod_time_(kInvalidModDate) {
+ if (!isReadonlyFilesystem(std::string(overlay_apk_path_).c_str()) ||
+ !(target_apk_path_ == AssetManager::TARGET_APK_PATH ||
+ isReadonlyFilesystem(std::string(target_apk_path_).c_str()))) {
+ idmap_fd_.reset(
+ android::base::utf8::open(idmap_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY | O_PATH));
+ idmap_last_mod_time_ = getFileModDate(idmap_fd_);
+ }
}
std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPiece idmap_data) {
@@ -381,8 +387,11 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPie
overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
}
-bool LoadedIdmap::IsUpToDate() const {
- return idmap_last_mod_time_ == getFileModDate(idmap_fd_.get());
+UpToDate LoadedIdmap::IsUpToDate() const {
+ if (idmap_last_mod_time_ == kInvalidModDate) {
+ return UpToDate::Always;
+ }
+ return fromBool(idmap_last_mod_time_ == getFileModDate(idmap_fd_.get()));
}
} // namespace android
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index de9991a8be5e..a8eb062a2ece 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -152,12 +152,11 @@ static void fill9patchOffsets(Res_png_9patch* patch) {
patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
}
-void Res_value::copyFrom_dtoh(const Res_value& src)
-{
- size = dtohs(src.size);
- res0 = src.res0;
- dataType = src.dataType;
- data = dtohl(src.data);
+void Res_value::copyFrom_dtoh_slow(const Res_value& src) {
+ size = dtohs(src.size);
+ res0 = src.res0;
+ dataType = src.dataType;
+ data = dtohl(src.data);
}
void Res_png_9patch::deviceToFile()
@@ -2031,16 +2030,6 @@ status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const
// --------------------------------------------------------------------
// --------------------------------------------------------------------
-void ResTable_config::copyFromDeviceNoSwap(const ResTable_config& o) {
- const size_t size = dtohl(o.size);
- if (size >= sizeof(ResTable_config)) {
- *this = o;
- } else {
- memcpy(this, &o, size);
- memset(((uint8_t*)this)+size, 0, sizeof(ResTable_config)-size);
- }
-}
-
/* static */ size_t unpackLanguageOrRegion(const char in[2], const char base,
char out[4]) {
if (in[0] & 0x80) {
@@ -2105,34 +2094,33 @@ size_t ResTable_config::unpackRegion(char region[4]) const {
return unpackLanguageOrRegion(this->country, '0', region);
}
-
-void ResTable_config::copyFromDtoH(const ResTable_config& o) {
- copyFromDeviceNoSwap(o);
- size = sizeof(ResTable_config);
- mcc = dtohs(mcc);
- mnc = dtohs(mnc);
- density = dtohs(density);
- screenWidth = dtohs(screenWidth);
- screenHeight = dtohs(screenHeight);
- sdkVersion = dtohs(sdkVersion);
- minorVersion = dtohs(minorVersion);
- smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
- screenWidthDp = dtohs(screenWidthDp);
- screenHeightDp = dtohs(screenHeightDp);
-}
-
-void ResTable_config::swapHtoD() {
- size = htodl(size);
- mcc = htods(mcc);
- mnc = htods(mnc);
- density = htods(density);
- screenWidth = htods(screenWidth);
- screenHeight = htods(screenHeight);
- sdkVersion = htods(sdkVersion);
- minorVersion = htods(minorVersion);
- smallestScreenWidthDp = htods(smallestScreenWidthDp);
- screenWidthDp = htods(screenWidthDp);
- screenHeightDp = htods(screenHeightDp);
+void ResTable_config::copyFromDtoH_slow(const ResTable_config& o) {
+ copyFromDeviceNoSwap(o);
+ size = sizeof(ResTable_config);
+ mcc = dtohs(mcc);
+ mnc = dtohs(mnc);
+ density = dtohs(density);
+ screenWidth = dtohs(screenWidth);
+ screenHeight = dtohs(screenHeight);
+ sdkVersion = dtohs(sdkVersion);
+ minorVersion = dtohs(minorVersion);
+ smallestScreenWidthDp = dtohs(smallestScreenWidthDp);
+ screenWidthDp = dtohs(screenWidthDp);
+ screenHeightDp = dtohs(screenHeightDp);
+}
+
+void ResTable_config::swapHtoD_slow() {
+ size = htodl(size);
+ mcc = htods(mcc);
+ mnc = htods(mnc);
+ density = htods(density);
+ screenWidth = htods(screenWidth);
+ screenHeight = htods(screenHeight);
+ sdkVersion = htods(sdkVersion);
+ minorVersion = htods(minorVersion);
+ smallestScreenWidthDp = htods(smallestScreenWidthDp);
+ screenWidthDp = htods(screenWidthDp);
+ screenHeightDp = htods(screenHeightDp);
}
/* static */ inline int compareLocales(const ResTable_config &l, const ResTable_config &r) {
@@ -2145,7 +2133,7 @@ void ResTable_config::swapHtoD() {
// systems should happen very infrequently (if at all.)
// The comparison code relies on memcmp low-level optimizations that make it
// more efficient than strncmp.
- const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
+ static constexpr char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
index be55fe8b4bb6..86c459fb4647 100644
--- a/libs/androidfw/Util.cpp
+++ b/libs/androidfw/Util.cpp
@@ -32,13 +32,18 @@ namespace android {
namespace util {
void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out) {
- char buf[5];
- while (*src && len != 0) {
- char16_t c = static_cast<char16_t>(dtohs(*src));
- utf16_to_utf8(&c, 1, buf, sizeof(buf));
- out->append(buf, strlen(buf));
- ++src;
- --len;
+ static constexpr bool kDeviceEndiannessSame = dtohs(0x1001) == 0x1001;
+ if constexpr (kDeviceEndiannessSame) {
+ *out = Utf16ToUtf8({(const char16_t*)src, strnlen16((const char16_t*)src, len)});
+ } else {
+ char buf[5];
+ while (*src && len != 0) {
+ char16_t c = static_cast<char16_t>(dtohs(*src));
+ utf16_to_utf8(&c, 1, buf, sizeof(buf));
+ out->append(buf, strlen(buf));
+ ++src;
+ --len;
+ }
}
}
@@ -63,8 +68,10 @@ std::string Utf16ToUtf8(StringPiece16 utf16) {
}
std::string utf8;
- utf8.resize(utf8_length);
- utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8_length + 1);
+ utf8.resize_and_overwrite(utf8_length, [&utf16](char* data, size_t size) {
+ utf16_to_utf8(utf16.data(), utf16.length(), data, size + 1);
+ return size;
+ });
return utf8;
}
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 231808beb718..3f6f4661f2f7 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -116,7 +116,7 @@ class ApkAssets : public RefBase {
return resources_asset_ != nullptr && resources_asset_->isAllocated();
}
- bool IsUpToDate() const;
+ UpToDate IsUpToDate() const;
// DANGER!
// This is a destructive method that rips the assets provider out of ApkAssets object.
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
index d33c325ff369..e3b3ae41f7f4 100644
--- a/libs/androidfw/include/androidfw/AssetsProvider.h
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROIDFW_ASSETSPROVIDER_H
-#define ANDROIDFW_ASSETSPROVIDER_H
+#pragma once
#include <memory>
#include <string>
@@ -58,7 +57,7 @@ struct AssetsProvider {
WARN_UNUSED virtual const std::string& GetDebugName() const = 0;
// Returns whether the interface provides the most recent version of its files.
- WARN_UNUSED virtual bool IsUpToDate() const = 0;
+ WARN_UNUSED virtual UpToDate IsUpToDate() const = 0;
// Creates an Asset from a file on disk.
static std::unique_ptr<Asset> CreateAssetFromFile(const std::string& path);
@@ -95,7 +94,7 @@ struct ZipAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
WARN_UNUSED std::optional<uint32_t> GetCrc(std::string_view path) const;
~ZipAssetsProvider() override = default;
@@ -106,7 +105,7 @@ struct ZipAssetsProvider : public AssetsProvider {
private:
struct PathOrDebugName;
ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, package_property_t flags,
- time_t last_mod_time);
+ ModDate last_mod_time);
struct PathOrDebugName {
static PathOrDebugName Path(std::string value) {
@@ -135,7 +134,7 @@ struct ZipAssetsProvider : public AssetsProvider {
std::unique_ptr<ZipArchive, ZipCloser> zip_handle_;
PathOrDebugName name_;
package_property_t flags_;
- time_t last_mod_time_;
+ ModDate last_mod_time_;
};
// Supplies assets from a root directory.
@@ -147,7 +146,7 @@ struct DirectoryAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~DirectoryAssetsProvider() override = default;
protected:
@@ -156,23 +155,23 @@ struct DirectoryAssetsProvider : public AssetsProvider {
bool* file_exists) const override;
private:
- explicit DirectoryAssetsProvider(std::string&& path, time_t last_mod_time);
+ explicit DirectoryAssetsProvider(std::string&& path, ModDate last_mod_time);
std::string dir_;
- time_t last_mod_time_;
+ ModDate last_mod_time_;
};
// Supplies assets from a `primary` asset provider and falls back to supplying assets from the
// `secondary` asset provider if the asset cannot be found in the `primary`.
struct MultiAssetsProvider : public AssetsProvider {
static std::unique_ptr<AssetsProvider> Create(std::unique_ptr<AssetsProvider>&& primary,
- std::unique_ptr<AssetsProvider>&& secondary);
+ std::unique_ptr<AssetsProvider>&& secondary = {});
bool ForEachFile(const std::string& root_path,
base::function_ref<void(StringPiece, FileType)> f) const override;
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~MultiAssetsProvider() override = default;
protected:
@@ -199,7 +198,7 @@ struct EmptyAssetsProvider : public AssetsProvider {
WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
- WARN_UNUSED bool IsUpToDate() const override;
+ WARN_UNUSED UpToDate IsUpToDate() const override;
~EmptyAssetsProvider() override = default;
protected:
@@ -212,5 +211,3 @@ struct EmptyAssetsProvider : public AssetsProvider {
};
} // namespace android
-
-#endif /* ANDROIDFW_ASSETSPROVIDER_H */
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ac75eb3bb98c..87f3c9df9a91 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef IDMAP_H_
-#define IDMAP_H_
+#pragma once
#include <memory>
#include <string>
@@ -32,6 +31,31 @@
namespace android {
+// An enum that tracks more states than just 'up to date' or 'not' for a resources container:
+// there are several cases where we know for sure that the object can't change and won't get
+// out of date. Reporting those states to the managed layer allows it to stop checking here
+// completely, speeding up the cache lookups by dozens of milliseconds.
+enum class UpToDate : int { False, True, Always };
+
+// Combines two UpToDate values, and only accesses the second one if it matters to the result.
+template <class Getter>
+UpToDate combine(UpToDate first, Getter secondGetter) {
+ switch (first) {
+ case UpToDate::False:
+ return UpToDate::False;
+ case UpToDate::True: {
+ const auto second = secondGetter();
+ return second == UpToDate::False ? UpToDate::False : UpToDate::True;
+ }
+ case UpToDate::Always:
+ return secondGetter();
+ }
+}
+
+inline UpToDate fromBool(bool value) {
+ return value ? UpToDate::True : UpToDate::False;
+}
+
class LoadedIdmap;
class IdmapResMap;
struct Idmap_header;
@@ -196,7 +220,7 @@ class LoadedIdmap {
// Returns whether the idmap file on disk has not been modified since the construction of this
// LoadedIdmap.
- bool IsUpToDate() const;
+ UpToDate IsUpToDate() const;
protected:
// Exposed as protected so that tests can subclass and mock this class out.
@@ -231,5 +255,3 @@ class LoadedIdmap {
};
} // namespace android
-
-#endif // IDMAP_H_
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index e330410ed1a0..819fe4b38c87 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -47,6 +47,8 @@
namespace android {
+constexpr const bool kDeviceEndiannessSame = dtohs(0x1001) == 0x1001;
+
constexpr const uint32_t kIdmapMagic = 0x504D4449u;
constexpr const uint32_t kIdmapCurrentVersion = 0x0000000Au;
@@ -408,7 +410,16 @@ struct Res_value
typedef uint32_t data_type;
data_type data;
- void copyFrom_dtoh(const Res_value& src);
+ void copyFrom_dtoh(const Res_value& src) {
+ if constexpr (kDeviceEndiannessSame) {
+ *this = src;
+ } else {
+ copyFrom_dtoh_slow(src);
+ }
+ }
+
+ private:
+ void copyFrom_dtoh_slow(const Res_value& src);
};
/**
@@ -1254,11 +1265,32 @@ struct ResTable_config
// Varies in length from 3 to 8 chars. Zero-filled value.
char localeNumberingSystem[8];
- void copyFromDeviceNoSwap(const ResTable_config& o);
-
- void copyFromDtoH(const ResTable_config& o);
-
- void swapHtoD();
+ void copyFromDeviceNoSwap(const ResTable_config& o) {
+ const auto o_size = dtohl(o.size);
+ if (o_size >= sizeof(ResTable_config)) [[likely]] {
+ *this = o;
+ } else {
+ memcpy(this, &o, o_size);
+ memset(((uint8_t*)this) + o_size, 0, sizeof(ResTable_config) - o_size);
+ }
+ this->size = sizeof(*this);
+ }
+
+ void copyFromDtoH(const ResTable_config& o) {
+ if constexpr (kDeviceEndiannessSame) {
+ copyFromDeviceNoSwap(o);
+ } else {
+ copyFromDtoH_slow(o);
+ }
+ }
+
+ void swapHtoD() {
+ if constexpr (kDeviceEndiannessSame) {
+ ; // noop
+ } else {
+ swapHtoD_slow();
+ }
+ }
int compare(const ResTable_config& o) const;
int compareLogical(const ResTable_config& o) const;
@@ -1384,6 +1416,10 @@ struct ResTable_config
bool isBetterThanBeforeLocale(const ResTable_config& o, const ResTable_config* requested) const;
String8 toString() const;
+
+ private:
+ void copyFromDtoH_slow(const ResTable_config& o);
+ void swapHtoD_slow();
};
/**
diff --git a/libs/androidfw/include/androidfw/misc.h b/libs/androidfw/include/androidfw/misc.h
index c9ba8a01a5e9..d8ca64a174a2 100644
--- a/libs/androidfw/include/androidfw/misc.h
+++ b/libs/androidfw/include/androidfw/misc.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <sys/stat.h>
#include <time.h>
//
@@ -64,10 +65,15 @@ ModDate getFileModDate(const char* fileName);
/* same, but also returns -1 if the file has already been deleted */
ModDate getFileModDate(int fd);
+// Extract the modification date from the stat structure.
+ModDate getModDate(const struct ::stat& st);
+
// Check if |path| or |fd| resides on a readonly filesystem.
bool isReadonlyFilesystem(const char* path);
bool isReadonlyFilesystem(int fd);
+bool isKnownWritablePath(const char* path);
+
} // namespace android
// Whoever uses getFileModDate() will need this as well
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 32f3624a3aee..26eb320805c9 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -16,10 +16,10 @@
#define LOG_TAG "misc"
-//
-// Miscellaneous utility functions.
-//
-#include <androidfw/misc.h>
+#include "androidfw/misc.h"
+
+#include <errno.h>
+#include <sys/stat.h>
#include "android-base/logging.h"
@@ -28,9 +28,7 @@
#include <sys/vfs.h>
#endif // __linux__
-#include <errno.h>
-#include <sys/stat.h>
-
+#include <array>
#include <cstdio>
#include <cstring>
#include <tuple>
@@ -40,28 +38,26 @@ namespace android {
/*
* Get a file's type.
*/
-FileType getFileType(const char* fileName)
-{
- struct stat sb;
-
- if (stat(fileName, &sb) < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
- return kFileTypeNonexistent;
- else {
- PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
- return kFileTypeUnknown;
- }
- } else {
- if (S_ISREG(sb.st_mode))
- return kFileTypeRegular;
- else if (S_ISDIR(sb.st_mode))
- return kFileTypeDirectory;
- else if (S_ISCHR(sb.st_mode))
- return kFileTypeCharDev;
- else if (S_ISBLK(sb.st_mode))
- return kFileTypeBlockDev;
- else if (S_ISFIFO(sb.st_mode))
- return kFileTypeFifo;
+FileType getFileType(const char* fileName) {
+ struct stat sb;
+ if (stat(fileName, &sb) < 0) {
+ if (errno == ENOENT || errno == ENOTDIR)
+ return kFileTypeNonexistent;
+ else {
+ PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
+ return kFileTypeUnknown;
+ }
+ } else {
+ if (S_ISREG(sb.st_mode))
+ return kFileTypeRegular;
+ else if (S_ISDIR(sb.st_mode))
+ return kFileTypeDirectory;
+ else if (S_ISCHR(sb.st_mode))
+ return kFileTypeCharDev;
+ else if (S_ISBLK(sb.st_mode))
+ return kFileTypeBlockDev;
+ else if (S_ISFIFO(sb.st_mode))
+ return kFileTypeFifo;
#if defined(S_ISLNK)
else if (S_ISLNK(sb.st_mode))
return kFileTypeSymlink;
@@ -75,7 +71,7 @@ FileType getFileType(const char* fileName)
}
}
-static ModDate getModDate(const struct stat& st) {
+ModDate getModDate(const struct stat& st) {
#ifdef _WIN32
return st.st_mtime;
#elif defined(__APPLE__)
@@ -113,8 +109,14 @@ bool isReadonlyFilesystem(const char*) {
bool isReadonlyFilesystem(int) {
return false;
}
+bool isKnownWritablePath(const char*) {
+ return false;
+}
#else // __linux__
bool isReadonlyFilesystem(const char* path) {
+ if (isKnownWritablePath(path)) {
+ return false;
+ }
struct statfs sfs;
if (::statfs(path, &sfs)) {
PLOG(ERROR) << "isReadonlyFilesystem(): statfs(" << path << ") failed";
@@ -131,6 +133,13 @@ bool isReadonlyFilesystem(int fd) {
}
return (sfs.f_flags & ST_RDONLY) != 0;
}
+
+bool isKnownWritablePath(const char* path) {
+ // We know that all paths in /data/ are writable.
+ static constexpr char kRwPrefix[] = "/data/";
+ return strncmp(kRwPrefix, path, std::size(kRwPrefix) - 1) == 0;
+}
+
#endif // __linux__
} // namespace android
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index cb2e56f5f5e4..22b9e69500d9 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -218,10 +218,11 @@ TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
auto apk_assets = ApkAssets::LoadOverlay(temp_file.path);
ASSERT_NE(nullptr, apk_assets);
- ASSERT_TRUE(apk_assets->IsUpToDate());
+ ASSERT_TRUE(apk_assets->IsOverlay());
+ ASSERT_EQ(UpToDate::True, apk_assets->IsUpToDate());
unlink(temp_file.path);
- ASSERT_FALSE(apk_assets->IsUpToDate());
+ ASSERT_EQ(UpToDate::False, apk_assets->IsUpToDate());
const auto sleep_duration =
std::chrono::nanoseconds(std::max(kModDateResolutionNs, 1'000'000ull));
@@ -230,7 +231,27 @@ TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
base::WriteStringToFile("hello", temp_file.path);
std::this_thread::sleep_for(sleep_duration);
- ASSERT_FALSE(apk_assets->IsUpToDate());
+ ASSERT_EQ(UpToDate::False, apk_assets->IsUpToDate());
+}
+
+TEST(IdmapTestUpToDate, Combine) {
+ ASSERT_EQ(UpToDate::False, combine(UpToDate::False, [] {
+ ADD_FAILURE(); // Shouldn't get called at all.
+ return UpToDate::False;
+ }));
+
+ ASSERT_EQ(UpToDate::False, combine(UpToDate::True, [] { return UpToDate::False; }));
+
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::True, [] { return UpToDate::True; }));
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::True, [] { return UpToDate::Always; }));
+ ASSERT_EQ(UpToDate::True, combine(UpToDate::Always, [] { return UpToDate::True; }));
+
+ ASSERT_EQ(UpToDate::Always, combine(UpToDate::Always, [] { return UpToDate::Always; }));
+}
+
+TEST(IdmapTestUpToDate, FromBool) {
+ ASSERT_EQ(UpToDate::False, fromBool(false));
+ ASSERT_EQ(UpToDate::True, fromBool(true));
}
} // namespace
diff --git a/packages/InputDevices/res/raw/keyboard_layout_romanian.kcm b/packages/InputDevices/res/raw/keyboard_layout_romanian.kcm
new file mode 100644
index 000000000000..b384a2418ff2
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_romanian.kcm
@@ -0,0 +1,357 @@
+# Copyright (C) 2024 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.
+
+#
+# Romanian keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '\u201e'
+ base: '\u201e'
+ shift: '\u201d'
+ ralt: '`'
+ ralt+shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ ralt: '\u0303'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+ ralt: '\u030C'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+ ralt: '\u0302'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u0306'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ ralt: '\u030A'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+ ralt: '\u0328'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+ ralt: '\u0300'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+ ralt: '\u0307'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '\u0301'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: '\u030B'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '\u0308'
+ ralt+shift: '\u2013'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ ralt: '\u0327'
+ ralt+shift: '\u00b1'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base, capslock+shift: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base, capslock+shift: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base, capslock+shift: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base, capslock+shift: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base, capslock+shift: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base, capslock+shift: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base, capslock+shift: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base, capslock+shift: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base, capslock+shift: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base, capslock+shift: 'p'
+ shift, capslock: 'P'
+ ralt: '\u00a7'
+}
+
+key LEFT_BRACKET {
+ label: '\u0102'
+ base, capslock+shift: '\u0103'
+ shift, capslock: '\u0102'
+ ralt: '['
+ ralt+shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: '\u00ce'
+ base, capslock+shift: '\u00ee'
+ shift, capslock: '\u00ce'
+ ralt: ']'
+ ralt+shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base, capslock+shift: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base, capslock+shift: 's'
+ shift, capslock: 'S'
+ ralt: '\u00df'
+}
+
+key D {
+ label: 'D'
+ base, capslock+shift: 'd'
+ shift, capslock: 'D'
+ ralt: '\u0111'
+ ralt+shift, ralt+capslock: '\u0110'
+ ralt+shift+capslock: '\u0111'
+}
+
+key F {
+ label: 'F'
+ base, capslock+shift: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base, capslock+shift: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base, capslock+shift: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base, capslock+shift: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base, capslock+shift: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base, capslock+shift: 'l'
+ shift, capslock: 'L'
+ ralt: '\u0142'
+ ralt+shift, ralt+capslock: '\u0141'
+ ralt+shift+capslock: '\u0142'
+}
+
+key SEMICOLON {
+ label: '\u0218'
+ base, capslock+shift: '\u0219'
+ shift, capslock: '\u0218'
+ ralt: ';'
+ ralt+shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\u021a'
+ base, capslock+shift: '\u021b'
+ shift, capslock: '\u021a'
+ ralt: '\''
+ ralt+shift: '\u0022'
+}
+
+key BACKSLASH {
+ label: '\u00c2'
+ base, capslock+shift: '\u00e2'
+ shift, capslock: '\u00c2'
+ ralt: '\\'
+ ralt+shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+key Z {
+ label: 'Z'
+ base, capslock+shift: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base, capslock+shift: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base, capslock+shift: 'c'
+ shift, capslock: 'C'
+ ralt: '\u00a9'
+}
+
+key V {
+ label: 'V'
+ base, capslock+shift: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base, capslock+shift: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base, capslock+shift: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base, capslock+shift: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+ ralt: '<'
+ ralt+shift: '\u00ab'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+ ralt: '>'
+ ralt+shift: '\u00bb'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 5a911256d9be..bd7cdc481524 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -164,4 +164,7 @@
<!-- Montenegrin (Cyrillic) keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_montenegrin_cyrillic">Montenegrin (Cyrillic)</string>
+
+ <!-- Romanian keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_romanian">Romanian</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 93094890418d..9ce9a87a1f9f 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -360,4 +360,11 @@
android:keyboardLayout="@raw/keyboard_layout_serbian_and_montenegrin_cyrillic"
android:keyboardLocale="cnr-Cyrl-ME"
android:keyboardLayoutType="extended" />
+
+ <keyboard-layout
+ android:name="keyboard_layout_romanian"
+ android:label="@string/keyboard_layout_romanian"
+ android:keyboardLayout="@raw/keyboard_layout_romanian"
+ android:keyboardLocale="ro-Latn-RO"
+ android:keyboardLayoutType="qwerty" />
</keyboard-layouts>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatter.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatter.kt
new file mode 100644
index 000000000000..5b7e2a86135a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatter.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2025 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.settingslib.spaprivileged.framework.common
+
+import android.content.Context
+import android.content.res.Resources
+import android.icu.text.DecimalFormat
+import android.icu.text.MeasureFormat
+import android.icu.text.NumberFormat
+import android.icu.text.UnicodeSet
+import android.icu.text.UnicodeSetSpanner
+import android.icu.util.Measure
+import android.text.format.Formatter
+import android.text.format.Formatter.RoundedBytesResult
+import java.math.BigDecimal
+
+class BytesFormatter(resources: Resources) {
+
+ enum class UseCase(val flag: Int) {
+ FileSize(Formatter.FLAG_SI_UNITS),
+ DataUsage(Formatter.FLAG_IEC_UNITS),
+ }
+
+ data class Result(val number: String, val units: String)
+
+ constructor(context: Context) : this(context.resources)
+
+ private val locale = resources.configuration.locales[0]
+
+ fun format(bytes: Long, useCase: UseCase): String {
+ val rounded = RoundedBytesResult.roundBytes(bytes, useCase.flag)
+ val numberFormatter = getNumberFormatter(rounded.fractionDigits)
+ return numberFormatter.formatRoundedBytesResult(rounded)
+ }
+
+ fun formatWithUnits(bytes: Long, useCase: UseCase): Result {
+ val rounded = RoundedBytesResult.roundBytes(bytes, useCase.flag)
+ val numberFormatter = getNumberFormatter(rounded.fractionDigits)
+ val formattedString = numberFormatter.formatRoundedBytesResult(rounded)
+ val formattedNumber = numberFormatter.format(rounded.value)
+ return Result(
+ number = formattedNumber,
+ units = formattedString.removeFirst(formattedNumber),
+ )
+ }
+
+ private fun NumberFormat.formatRoundedBytesResult(rounded: RoundedBytesResult): String {
+ val measureFormatter =
+ MeasureFormat.getInstance(locale, MeasureFormat.FormatWidth.SHORT, this)
+ return measureFormatter.format(Measure(rounded.value, rounded.units))
+ }
+
+ private fun getNumberFormatter(fractionDigits: Int) =
+ NumberFormat.getInstance(locale).apply {
+ minimumFractionDigits = fractionDigits
+ maximumFractionDigits = fractionDigits
+ isGroupingUsed = false
+ if (this is DecimalFormat) {
+ setRoundingMode(BigDecimal.ROUND_HALF_UP)
+ }
+ }
+
+ private companion object {
+ fun String.removeFirst(removed: String): String =
+ SPACES_AND_CONTROLS.trim(replaceFirst(removed, "")).toString()
+
+ val SPACES_AND_CONTROLS = UnicodeSetSpanner(UnicodeSet("[[:Zs:][:Cf:]]").freeze())
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatterTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatterTest.kt
new file mode 100644
index 000000000000..7220848eebff
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BytesFormatterTest.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2025 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.settingslib.spaprivileged.framework.common
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class BytesFormatterTest {
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ private val formatter = BytesFormatter(context)
+
+ @Test
+ fun `Zero bytes`() {
+ // Given a byte value of 0, the formatted output should be "0 byte" for both FileSize
+ // and DataUsage UseCases. This verifies special handling of zero values.
+
+ val fileSizeResult = formatter.format(0, BytesFormatter.UseCase.FileSize)
+ assertThat(fileSizeResult).isEqualTo("0 byte")
+
+ val dataUsageResult = formatter.format(0, BytesFormatter.UseCase.DataUsage)
+ assertThat(dataUsageResult).isEqualTo("0 byte")
+ }
+
+ @Test
+ fun `Positive bytes`() {
+ // Given a positive byte value (e.g., 1000), the formatted output should be correctly
+ // displayed with appropriate units (e.g., '1.00 kB') for both UseCases.
+
+ val fileSizeResult = formatter.format(1000, BytesFormatter.UseCase.FileSize)
+ assertThat(fileSizeResult).isEqualTo("1.00 kB")
+
+ val dataUsageResult = formatter.format(1024, BytesFormatter.UseCase.DataUsage)
+ assertThat(dataUsageResult).isEqualTo("1.00 kB")
+ }
+
+ @Test
+ fun `Large bytes`() {
+ // Given a very large byte value (e.g., Long.MAX_VALUE), the formatted output should be
+ // correctly displayed with the largest unit (e.g., 'PB') for both UseCases.
+
+ val fileSizeResult = formatter.format(Long.MAX_VALUE, BytesFormatter.UseCase.FileSize)
+ assertThat(fileSizeResult).isEqualTo("9223 PB")
+
+ val dataUsageResult = formatter.format(Long.MAX_VALUE, BytesFormatter.UseCase.DataUsage)
+ assertThat(dataUsageResult).isEqualTo("8192 PB")
+ }
+
+ @Test
+ fun `Bytes requiring rounding`() {
+ // Given byte values that require rounding (e.g., 1512), the formatted output should be
+ // rounded to the appropriate number of decimal places (e.g., '1.51 kB').
+
+ val fileSizeResult = formatter.format(1512, BytesFormatter.UseCase.FileSize)
+ assertThat(fileSizeResult).isEqualTo("1.51 kB")
+
+ val dataUsageResult = formatter.format(1512, BytesFormatter.UseCase.DataUsage)
+ assertThat(dataUsageResult).isEqualTo("1.48 kB")
+ }
+
+ @Test
+ fun `FileSize UseCase`() {
+ // When the UseCase is FileSize, the correct units (byte, KB, kB, GB, TB, PB) should
+ // be used.
+ val values =
+ listOf(
+ 1L,
+ 1024L,
+ 1024L * 1024L,
+ 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L * 1024L * 1024L,
+ )
+ val expectedUnits = listOf("byte", "kB", "MB", "GB", "TB", "PB", "PB")
+
+ values.zip(expectedUnits).forEach { (value, expectedUnit) ->
+ val result = formatter.format(value, BytesFormatter.UseCase.FileSize)
+ assertThat(result).contains(expectedUnit)
+ }
+ }
+
+ @Test
+ fun `DataUsage UseCase`() {
+ // When the UseCase is DataUsage, the correct units (byte, kB, MB, GB, TB, PB) should
+ // be used.
+ val values =
+ listOf(
+ 1L,
+ 1024L,
+ 1024L * 1024L,
+ 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L * 1024L,
+ 1024L * 1024L * 1024L * 1024L * 1024L * 1024L,
+ )
+ val expectedUnits = listOf("byte", "kB", "MB", "GB", "TB", "PB", "PB")
+
+ values.zip(expectedUnits).forEach { (value, expectedUnit) ->
+ val result = formatter.format(value, BytesFormatter.UseCase.DataUsage)
+ assertThat(result).contains(expectedUnit)
+ }
+ }
+
+ @Test
+ fun `Fraction digits`() {
+ // The number of fraction digits in the output should be correctly determined based on
+ // the rounded byte value.
+
+ assertThat(formatter.format(1500, BytesFormatter.UseCase.FileSize)).isEqualTo("1.50 kB")
+ assertThat(formatter.format(1050, BytesFormatter.UseCase.FileSize)).isEqualTo("1.05 kB")
+ assertThat(formatter.format(999, BytesFormatter.UseCase.FileSize)).isEqualTo("1.00 kB")
+ }
+
+ @Test
+ fun `Rounding mode`() {
+ // The rounding mode used for formatting should be ROUND_HALF_UP.
+
+ val result = formatter.format(1006, BytesFormatter.UseCase.FileSize)
+
+ assertThat(result).isEqualTo("1.01 kB") // Ensure rounding mode is effective
+ }
+
+ @Test
+ fun `Grouping separator`() {
+ // Grouping separators should not be used in the formatted output.
+
+ val result = formatter.format(Long.MAX_VALUE, BytesFormatter.UseCase.FileSize)
+
+ assertThat(result).isEqualTo("9223 PB")
+ }
+
+ @Test
+ fun `Format with units`() {
+ // Verify that the `formatWithUnits` method correctly formats the given bytes with the
+ // specified units.
+
+ val resultByte = formatter.formatWithUnits(0, BytesFormatter.UseCase.FileSize)
+ assertThat(resultByte).isEqualTo(BytesFormatter.Result("0", "byte"))
+
+ val resultKb = formatter.formatWithUnits(1000, BytesFormatter.UseCase.FileSize)
+ assertThat(resultKb).isEqualTo(BytesFormatter.Result("1.00", "kB"))
+
+ val resultMb = formatter.formatWithUnits(479_999_999, BytesFormatter.UseCase.FileSize)
+ assertThat(resultMb).isEqualTo(BytesFormatter.Result("480", "MB"))
+
+ val resultGb = formatter.formatWithUnits(20_100_000_000, BytesFormatter.UseCase.FileSize)
+ assertThat(resultGb).isEqualTo(BytesFormatter.Result("20.10", "GB"))
+
+ val resultTb =
+ formatter.formatWithUnits(300_100_000_000_000, BytesFormatter.UseCase.FileSize)
+ assertThat(resultTb).isEqualTo(BytesFormatter.Result("300", "TB"))
+
+ val resultPb =
+ formatter.formatWithUnits(1000_000_000_000_000, BytesFormatter.UseCase.FileSize)
+ assertThat(resultPb).isEqualTo(BytesFormatter.Result("1.00", "PB"))
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 145b62cd12b5..68e9fe703090 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -73,6 +73,10 @@ public class BluetoothUtils {
private static final Set<Integer> SA_PROFILES =
ImmutableSet.of(
BluetoothProfile.A2DP, BluetoothProfile.LE_AUDIO, BluetoothProfile.HEARING_AID);
+ private static final List<Integer> BLUETOOTH_DEVICE_CLASS_HEADSET =
+ List.of(
+ BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES,
+ BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET);
private static final String TEMP_BOND_TYPE = "TEMP_BOND_TYPE";
private static final String TEMP_BOND_DEVICE_METADATA_VALUE = "le_audio_sharing";
@@ -390,6 +394,19 @@ public class BluetoothUtils {
return false;
}
+ /** Checks whether the bluetooth device is a headset. */
+ public static boolean isHeadset(@NonNull BluetoothDevice bluetoothDevice) {
+ String deviceType =
+ BluetoothUtils.getStringMetaData(
+ bluetoothDevice, BluetoothDevice.METADATA_DEVICE_TYPE);
+ if (!TextUtils.isEmpty(deviceType)) {
+ return BluetoothDevice.DEVICE_TYPE_HEADSET.equals(deviceType)
+ || BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.equals(deviceType);
+ }
+ BluetoothClass btClass = bluetoothDevice.getBluetoothClass();
+ return btClass != null && BLUETOOTH_DEVICE_CLASS_HEADSET.contains(btClass.getDeviceClass());
+ }
+
/** Create an Icon pointing to a drawable. */
public static IconCompat createIconWithDrawable(Drawable drawable) {
Bitmap bitmap;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index d49447f05011..cafe19ff9a9b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -80,7 +80,9 @@ public class BluetoothUtilsTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock private BluetoothDevice mBluetoothDevice;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private BluetoothDevice mBluetoothDevice;
+
@Mock private AudioManager mAudioManager;
@Mock private PackageManager mPackageManager;
@Mock private LeAudioProfile mA2dpProfile;
@@ -399,6 +401,38 @@ public class BluetoothUtilsTest {
}
@Test
+ public void isHeadset_metadataMatched_returnTrue() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE))
+ .thenReturn(BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.getBytes());
+
+ assertThat(BluetoothUtils.isHeadset(mBluetoothDevice)).isTrue();
+ }
+
+ @Test
+ public void isHeadset_metadataNotMatched_returnFalse() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE))
+ .thenReturn(BluetoothDevice.DEVICE_TYPE_CARKIT.getBytes());
+
+ assertThat(BluetoothUtils.isHeadset(mBluetoothDevice)).isFalse();
+ }
+
+ @Test
+ public void isHeadset_btClassMatched_returnTrue() {
+ when(mBluetoothDevice.getBluetoothClass().getDeviceClass())
+ .thenReturn(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+
+ assertThat(BluetoothUtils.isHeadset(mBluetoothDevice)).isTrue();
+ }
+
+ @Test
+ public void isHeadset_btClassNotMatched_returnFalse() {
+ when(mBluetoothDevice.getBluetoothClass().getDeviceClass())
+ .thenReturn(BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER);
+
+ assertThat(BluetoothUtils.isHeadset(mBluetoothDevice)).isFalse();
+ }
+
+ @Test
public void isAvailableMediaBluetoothDevice_isConnectedLeAudioDevice_returnTrue() {
when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5ddf005d9468..dafcc729b8f1 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -322,9 +322,6 @@
<!-- Whether vibrate icon is shown in the status bar by default. -->
<integer name="def_statusBarVibrateIconEnabled">0</integer>
- <!-- Whether predictive back animation is enabled by default. -->
- <bool name="def_enable_back_animation">false</bool>
-
<!-- Whether wifi is always requested by default. -->
<bool name="def_enable_wifi_always_requested">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index a2cc008843a4..ef0bc3b100e0 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -193,6 +193,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
"power_button_instantly_locks";
private static final String KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY =
"pin_enhanced_privacy";
+ private static final int NUM_LOCK_SETTINGS = 5;
// Error messages for logging metrics.
private static final String ERROR_COULD_NOT_READ_FROM_CURSOR =
@@ -208,6 +209,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private static final String ERROR_SKIPPED_DUE_TO_LARGE_SCREEN =
"skipped_due_to_large_screen";
private static final String ERROR_DID_NOT_PASS_VALIDATION = "did_not_pass_validation";
+ private static final String ERROR_IO_EXCEPTION = "io_exception";
+ private static final String ERROR_FAILED_TO_RESTORE_SOFTAP_CONFIG =
+ "failed_to_restore_softap_config";
+ private static final String ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES =
+ "failed_to_convert_network_policies";
+ private static final String ERROR_UNKNOWN_BACKUP_SERIALIZATION_VERSION =
+ "unknown_backup_serialization_version";
// Name of the temporary file we use during full backup/restore. This is
@@ -794,29 +802,44 @@ public class SettingsBackupAgent extends BackupAgentHelper {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
+ int backedUpSettingsCount = 0;
try {
out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED);
out.writeUTF(ownerInfoEnabled ? "1" : "0");
+ backedUpSettingsCount++;
if (ownerInfo != null) {
out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO);
out.writeUTF(ownerInfo != null ? ownerInfo : "");
+ backedUpSettingsCount++;
}
if (lockPatternUtils.isVisiblePatternEverChosen(userId)) {
out.writeUTF(KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED);
out.writeUTF(visiblePatternEnabled ? "1" : "0");
+ backedUpSettingsCount++;
}
if (lockPatternUtils.isPowerButtonInstantlyLocksEverChosen(userId)) {
out.writeUTF(KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS);
out.writeUTF(powerButtonInstantlyLocks ? "1" : "0");
+ backedUpSettingsCount++;
}
if (lockPatternUtils.isPinEnhancedPrivacyEverChosen(userId)) {
out.writeUTF(KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY);
out.writeUTF(lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) ? "1" : "0");
+ backedUpSettingsCount++;
}
// End marker
out.writeUTF("");
out.flush();
+ if (areAgentMetricsEnabled) {
+ numberOfSettingsPerKey.put(KEY_LOCK_SETTINGS, backedUpSettingsCount);
+ }
} catch (IOException ioe) {
+ if (areAgentMetricsEnabled) {
+ mBackupRestoreEventLogger.logItemsBackupFailed(
+ KEY_LOCK_SETTINGS,
+ NUM_LOCK_SETTINGS - backedUpSettingsCount,
+ ERROR_IO_EXCEPTION);
+ }
}
return baos.toByteArray();
}
@@ -1162,6 +1185,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes);
DataInputStream in = new DataInputStream(bais);
+ int restoredLockSettingsCount = 0;
try {
String key;
// Read until empty string marker
@@ -1187,9 +1211,20 @@ public class SettingsBackupAgent extends BackupAgentHelper {
lockPatternUtils.setPinEnhancedPrivacyEnabled("1".equals(value), userId);
break;
}
+ if (areAgentMetricsEnabled) {
+ mBackupRestoreEventLogger.logItemsRestored(KEY_LOCK_SETTINGS, /* count= */ 1);
+ restoredLockSettingsCount++;
+ }
+
}
in.close();
} catch (IOException ioe) {
+ if (areAgentMetricsEnabled) {
+ mBackupRestoreEventLogger.logItemsRestoreFailed(
+ KEY_LOCK_SETTINGS,
+ NUM_LOCK_SETTINGS - restoredLockSettingsCount,
+ ERROR_IO_EXCEPTION);
+ }
}
}
@@ -1309,12 +1344,31 @@ public class SettingsBackupAgent extends BackupAgentHelper {
mWifiManager.restoreSupplicantBackupData(supplicant_bytes, ipconfig_bytes);
}
- private byte[] getSoftAPConfiguration() {
- return mWifiManager.retrieveSoftApBackupData();
+ @VisibleForTesting
+ byte[] getSoftAPConfiguration() {
+ byte[] data = mWifiManager.retrieveSoftApBackupData();
+ if (areAgentMetricsEnabled) {
+ // We're unable to determine how many settings this includes, so we'll just log 1.
+ numberOfSettingsPerKey.put(KEY_SOFTAP_CONFIG, 1);
+ }
+ return data;
}
- private void restoreSoftApConfiguration(byte[] data) {
- SoftApConfiguration configInCloud = mWifiManager.restoreSoftApBackupData(data);
+ @VisibleForTesting
+ void restoreSoftApConfiguration(byte[] data) {
+ SoftApConfiguration configInCloud;
+ if (areAgentMetricsEnabled) {
+ try {
+ configInCloud = mWifiManager.restoreSoftApBackupData(data);
+ mBackupRestoreEventLogger.logItemsRestored(KEY_SOFTAP_CONFIG, /* count= */ 1);
+ } catch (Exception e) {
+ configInCloud = null;
+ mBackupRestoreEventLogger.logItemsRestoreFailed(
+ KEY_SOFTAP_CONFIG, /* count= */ 1, ERROR_FAILED_TO_RESTORE_SOFTAP_CONFIG);
+ }
+ } else {
+ configInCloud = mWifiManager.restoreSoftApBackupData(data);
+ }
if (configInCloud != null) {
if (DEBUG) Log.d(TAG, "Successfully unMarshaled SoftApConfiguration ");
// Depending on device hardware, we may need to notify the user of a setting change
@@ -1384,6 +1438,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
try {
out.writeInt(NETWORK_POLICIES_BACKUP_VERSION);
out.writeInt(policies.length);
+ int numberOfPoliciesBackedUp = 0;
for (NetworkPolicy policy : policies) {
// We purposefully only backup policies that the user has
// defined; any inferred policies might include
@@ -1393,13 +1448,23 @@ public class SettingsBackupAgent extends BackupAgentHelper {
out.writeByte(BackupUtils.NOT_NULL);
out.writeInt(marshaledPolicy.length);
out.write(marshaledPolicy);
+ if (areAgentMetricsEnabled) {
+ numberOfPoliciesBackedUp++;
+ }
} else {
out.writeByte(BackupUtils.NULL);
}
}
+ if (areAgentMetricsEnabled) {
+ numberOfSettingsPerKey.put(KEY_NETWORK_POLICIES, numberOfPoliciesBackedUp);
+ }
} catch (IOException ioe) {
Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage());
baos.reset();
+ mBackupRestoreEventLogger.logItemsBackupFailed(
+ KEY_NETWORK_POLICIES,
+ policies.length,
+ ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES);
}
}
return baos.toByteArray();
@@ -1433,6 +1498,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
try {
int version = in.readInt();
if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) {
+ mBackupRestoreEventLogger.logItemsRestoreFailed(
+ KEY_NETWORK_POLICIES,
+ /* count= */ 1,
+ ERROR_UNKNOWN_BACKUP_SERIALIZATION_VERSION);
throw new BackupUtils.BadVersionException(
"Unknown Backup Serialization Version");
}
@@ -1449,10 +1518,15 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
// Only set the policies if there was no error in the restore operation
networkPolicyManager.setNetworkPolicies(policies);
+ mBackupRestoreEventLogger.logItemsRestored(KEY_NETWORK_POLICIES, policies.length);
} catch (NullPointerException | IOException | BackupUtils.BadVersionException
| DateTimeException e) {
// NPE can be thrown when trying to instantiate a NetworkPolicy
Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage());
+ mBackupRestoreEventLogger.logItemsRestoreFailed(
+ KEY_NETWORK_POLICIES,
+ /* count= */ 1,
+ ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES);
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index ed193515b382..cb656bdd5d54 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -6122,17 +6122,7 @@ public class SettingsProvider extends ContentProvider {
}
if (currentVersion == 220) {
- final SettingsState globalSettings = getGlobalSettingsLocked();
- final Setting enableBackAnimation =
- globalSettings.getSettingLocked(Global.ENABLE_BACK_ANIMATION);
- if (enableBackAnimation.isNull()) {
- final boolean defEnableBackAnimation =
- getContext()
- .getResources()
- .getBoolean(R.bool.def_enable_back_animation);
- initGlobalSettingsDefaultValLocked(
- Settings.Global.ENABLE_BACK_ANIMATION, defEnableBackAnimation);
- }
+ // Version 221: Removed
currentVersion = 221;
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c88a7fd834d6..cbdb36fff98c 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -564,7 +564,6 @@ public class SettingsBackupTest {
Settings.Global.WATCHDOG_TIMEOUT_MILLIS,
Settings.Global.MANAGED_PROVISIONING_DEFER_PROVISIONING_TO_ROLE_HOLDER,
Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
- Settings.Global.ENABLE_BACK_ANIMATION, // Temporary for T, dev option only
Settings.Global.HEARING_DEVICE_LOCAL_AMBIENT_VOLUME, // cache per hearing device
Settings.Global.HEARING_DEVICE_LOCAL_NOTIFICATION, // cache per hearing device
Settings.Global.Wearable.COMBINED_LOCATION_ENABLE,
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index 18c43a704bcc..95dd0db40c0e 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -16,6 +16,8 @@
package com.android.providers.settings;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SOFTAP_CONFIG;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -28,6 +30,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.app.backup.BackupAnnotations.BackupDestination;
import android.app.backup.BackupAnnotations.OperationType;
import android.app.backup.BackupDataInput;
@@ -42,6 +45,8 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
+import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
@@ -126,6 +131,7 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
@Mock private BackupDataInput mBackupDataInput;
@Mock private BackupDataOutput mBackupDataOutput;
+ @Mock private static WifiManager mWifiManager;
private TestFriendlySettingsBackupAgent mAgentUnderTest;
private Context mContext;
@@ -754,6 +760,80 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
}
+ @Test
+ @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+ public void getSoftAPConfiguration_flagIsEnabled_numberOfSettingsInKeyAreRecorded() {
+ mAgentUnderTest.onCreate(
+ UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.BACKUP);
+ when(mWifiManager.retrieveSoftApBackupData()).thenReturn(null);
+
+ mAgentUnderTest.getSoftAPConfiguration();
+
+ assertEquals(mAgentUnderTest.getNumberOfSettingsPerKey(KEY_SOFTAP_CONFIG), 1);
+ }
+
+ @Test
+ @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+ public void getSoftAPConfiguration_flagIsNotEnabled_numberOfSettingsInKeyAreNotRecorded() {
+ mAgentUnderTest.onCreate(
+ UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.BACKUP);
+ when(mWifiManager.retrieveSoftApBackupData()).thenReturn(null);
+
+ mAgentUnderTest.getSoftAPConfiguration();
+
+ assertEquals(mAgentUnderTest.getNumberOfSettingsPerKey(KEY_SOFTAP_CONFIG), 0);
+ }
+
+ @Test
+ @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+ public void
+ restoreSoftApConfiguration_flagIsEnabled_restoreIsSuccessful_successMetricsAreLogged() {
+ mAgentUnderTest.onCreate(
+ UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+ SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid("test").build();
+ byte[] data = config.toString().getBytes();
+ when(mWifiManager.restoreSoftApBackupData(any())).thenReturn(null);
+
+ mAgentUnderTest.restoreSoftApConfiguration(data);
+
+ DataTypeResult loggingResult =
+ getLoggingResultForDatatype(KEY_SOFTAP_CONFIG, mAgentUnderTest);
+ assertNotNull(loggingResult);
+ assertEquals(loggingResult.getSuccessCount(), 1);
+ }
+
+ @Test
+ @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+ public void
+ restoreSoftApConfiguration_flagIsEnabled_restoreIsNotSuccessful_failureMetricsAreLogged() {
+ mAgentUnderTest.onCreate(
+ UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+ SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid("test").build();
+ byte[] data = config.toString().getBytes();
+ when(mWifiManager.restoreSoftApBackupData(any())).thenThrow(new RuntimeException());
+
+ mAgentUnderTest.restoreSoftApConfiguration(data);
+
+ DataTypeResult loggingResult =
+ getLoggingResultForDatatype(KEY_SOFTAP_CONFIG, mAgentUnderTest);
+ assertNotNull(loggingResult);
+ assertEquals(loggingResult.getFailCount(), 1);
+ }
+
+ @Test
+ @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+ public void restoreSoftApConfiguration_flagIsNotEnabled_metricsAreNotLogged() {
+ mAgentUnderTest.onCreate(
+ UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+ SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid("test").build();
+ byte[] data = config.toString().getBytes();
+ when(mWifiManager.restoreSoftApBackupData(any())).thenReturn(null);
+
+ mAgentUnderTest.restoreSoftApConfiguration(data);
+
+ assertNull(getLoggingResultForDatatype(KEY_SOFTAP_CONFIG, mAgentUnderTest));
+ }
+
private byte[] generateBackupData(Map<String, String> keyValueData) {
int totalBytes = 0;
for (String key : keyValueData.keySet()) {
@@ -890,6 +970,13 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
this.numberOfSettingsPerKey.put(key, numberOfSettings);
}
}
+
+ int getNumberOfSettingsPerKey(String key) {
+ if (numberOfSettingsPerKey == null || !numberOfSettingsPerKey.containsKey(key)) {
+ return 0;
+ }
+ return numberOfSettingsPerKey.get(key);
+ }
}
/** The TestSettingsHelper tracks which values have been backed up and/or restored. */
@@ -944,6 +1031,14 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
public ContentResolver getContentResolver() {
return mContentResolver;
}
+
+ @Override
+ public Object getSystemService(String name) {
+ if (name.equals(Context.WIFI_SERVICE)) {
+ return mWifiManager;
+ }
+ return super.getSystemService(name);
+ }
}
/** ContentProvider which returns a set of known test values. */
diff --git a/packages/SystemUI/aconfig/predictive_back.aconfig b/packages/SystemUI/aconfig/predictive_back.aconfig
index ad4a02764176..ee918c275b7b 100644
--- a/packages/SystemUI/aconfig/predictive_back.aconfig
+++ b/packages/SystemUI/aconfig/predictive_back.aconfig
@@ -7,17 +7,3 @@ flag {
description: "Enable Shade Animations"
bug: "327732946"
}
-
-flag {
- name: "predictive_back_animate_bouncer"
- namespace: "systemui"
- description: "Enable Predictive Back Animation in Bouncer"
- bug: "327733487"
-}
-
-flag {
- name: "predictive_back_animate_dialogs"
- namespace: "systemui"
- description: "Enable Predictive Back Animation for SysUI dialogs"
- bug: "327721544"
-}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 715d22328f2b..7d5fd903c01b 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -133,14 +133,6 @@ flag {
}
flag {
- name: "notifications_footer_view_refactor"
- namespace: "systemui"
- description: "Enables the refactored version of the footer view in the notification shade "
- "(containing the \"Clear all\" button). Should not bring any behavior changes"
- bug: "293167744"
-}
-
-flag {
name: "notifications_icon_container_refactor"
namespace: "systemui"
description: "Enables the refactored version of the notification icon container in StatusBar, "
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/AnimationFeatureFlags.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/AnimationFeatureFlags.kt
deleted file mode 100644
index 1c9dabbb0e07..000000000000
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/AnimationFeatureFlags.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.android.systemui.animation
-
-interface AnimationFeatureFlags {
- val isPredictiveBackQsDialogAnim: Boolean
- get() = false
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt
index 907c39d842ce..c88c4ebb1a8d 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogTransitionAnimator.kt
@@ -59,13 +59,8 @@ constructor(
private val mainExecutor: Executor,
private val callback: Callback,
private val interactionJankMonitor: InteractionJankMonitor,
- private val featureFlags: AnimationFeatureFlags,
private val transitionAnimator: TransitionAnimator =
- TransitionAnimator(
- mainExecutor,
- TIMINGS,
- INTERPOLATORS,
- ),
+ TransitionAnimator(mainExecutor, TIMINGS, INTERPOLATORS),
private val isForTesting: Boolean = false,
) {
private companion object {
@@ -219,7 +214,7 @@ constructor(
dialog: Dialog,
view: View,
cuj: DialogCuj? = null,
- animateBackgroundBoundsChange: Boolean = false
+ animateBackgroundBoundsChange: Boolean = false,
) {
val controller = Controller.fromView(view, cuj)
if (controller == null) {
@@ -245,7 +240,7 @@ constructor(
fun show(
dialog: Dialog,
controller: Controller,
- animateBackgroundBoundsChange: Boolean = false
+ animateBackgroundBoundsChange: Boolean = false,
) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw IllegalStateException(
@@ -263,15 +258,14 @@ constructor(
val controller =
animatedParent?.dialogContentWithBackground?.let {
Controller.fromView(it, controller.cuj)
- }
- ?: controller
+ } ?: controller
// Make sure we don't run the launch animation from the same source twice at the same time.
if (openedDialogs.any { it.controller.sourceIdentity == controller.sourceIdentity }) {
Log.e(
TAG,
"Not running dialog launch animation from source as it is already expanded into a" +
- " dialog"
+ " dialog",
)
dialog.show()
return
@@ -288,7 +282,6 @@ constructor(
animateBackgroundBoundsChange = animateBackgroundBoundsChange,
parentAnimatedDialog = animatedParent,
forceDisableSynchronization = isForTesting,
- featureFlags = featureFlags,
)
openedDialogs.add(animatedDialog)
@@ -305,7 +298,7 @@ constructor(
dialog: Dialog,
animateFrom: Dialog,
cuj: DialogCuj? = null,
- animateBackgroundBoundsChange: Boolean = false
+ animateBackgroundBoundsChange: Boolean = false,
) {
val view =
openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground
@@ -313,7 +306,7 @@ constructor(
Log.w(
TAG,
"Showing dialog $dialog normally as the dialog it is shown from was not shown " +
- "using DialogTransitionAnimator"
+ "using DialogTransitionAnimator",
)
dialog.show()
return
@@ -323,7 +316,7 @@ constructor(
dialog,
view,
animateBackgroundBoundsChange = animateBackgroundBoundsChange,
- cuj = cuj
+ cuj = cuj,
)
}
@@ -346,8 +339,7 @@ constructor(
val animatedDialog =
openedDialogs.firstOrNull {
it.dialog.window?.decorView?.viewRootImpl == view.viewRootImpl
- }
- ?: return null
+ } ?: return null
return createActivityTransitionController(animatedDialog, cujType)
}
@@ -373,7 +365,7 @@ constructor(
private fun createActivityTransitionController(
animatedDialog: AnimatedDialog,
- cujType: Int? = null
+ cujType: Int? = null,
): ActivityTransitionAnimator.Controller? {
// At this point, we know that the intent of the caller is to dismiss the dialog to show
// an app, so we disable the exit animation into the source because we will never want to
@@ -440,7 +432,7 @@ constructor(
}
private fun disableDialogDismiss() {
- dialog.setDismissOverride { /* Do nothing */}
+ dialog.setDismissOverride { /* Do nothing */ }
}
private fun enableDialogDismiss() {
@@ -530,7 +522,6 @@ private class AnimatedDialog(
* Whether synchronization should be disabled, which can be useful if we are running in a test.
*/
private val forceDisableSynchronization: Boolean,
- private val featureFlags: AnimationFeatureFlags,
) {
/**
* The DecorView of this dialog window.
@@ -643,8 +634,7 @@ private class AnimatedDialog(
originalDialogBackgroundColor =
GhostedViewTransitionAnimatorController.findGradientDrawable(background)
?.color
- ?.defaultColor
- ?: Color.BLACK
+ ?.defaultColor ?: Color.BLACK
// Make the background view invisible until we start the animation. We use the transition
// visibility like GhostView does so that we don't mess up with the accessibility tree (see
@@ -700,7 +690,7 @@ private class AnimatedDialog(
oldLeft: Int,
oldTop: Int,
oldRight: Int,
- oldBottom: Int
+ oldBottom: Int,
) {
dialogContentWithBackground.removeOnLayoutChangeListener(this)
@@ -717,9 +707,7 @@ private class AnimatedDialog(
// the dialog.
dialog.setDismissOverride(this::onDialogDismissed)
- if (featureFlags.isPredictiveBackQsDialogAnim) {
- dialog.registerAnimationOnBackInvoked(targetView = dialogContentWithBackground)
- }
+ dialog.registerAnimationOnBackInvoked(targetView = dialogContentWithBackground)
// Show the dialog.
dialog.show()
@@ -815,7 +803,7 @@ private class AnimatedDialog(
if (hasInstrumentedJank) {
interactionJankMonitor.end(controller.cuj!!.cujType)
}
- }
+ },
)
}
@@ -888,14 +876,14 @@ private class AnimatedDialog(
onAnimationFinished(true /* instantDismiss */)
onDialogDismissed(this@AnimatedDialog)
}
- }
+ },
)
}
private fun startAnimation(
isLaunching: Boolean,
onLaunchAnimationStart: () -> Unit = {},
- onLaunchAnimationEnd: () -> Unit = {}
+ onLaunchAnimationEnd: () -> Unit = {},
) {
// Create 2 controllers to animate both the dialog and the source.
val startController =
@@ -969,7 +957,7 @@ private class AnimatedDialog(
override fun onTransitionAnimationProgress(
state: TransitionAnimator.State,
progress: Float,
- linearProgress: Float
+ linearProgress: Float,
) {
startController.onTransitionAnimationProgress(state, progress, linearProgress)
@@ -1026,7 +1014,7 @@ private class AnimatedDialog(
oldLeft: Int,
oldTop: Int,
oldRight: Int,
- oldBottom: Int
+ oldBottom: Int,
) {
// Don't animate if bounds didn't actually change.
if (left == oldLeft && top == oldTop && right == oldRight && bottom == oldBottom) {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
index e02e8b483543..5f1f588bb2b5 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
@@ -37,6 +37,7 @@ import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerInputScope
+import androidx.compose.ui.input.pointer.PointerType
import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
import androidx.compose.ui.input.pointer.changedToDownIgnoreConsumed
import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
@@ -52,7 +53,6 @@ import androidx.compose.ui.node.currentValueOf
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.Velocity
-import androidx.compose.ui.util.fastSumBy
import com.android.compose.modifiers.thenIf
import kotlin.math.sign
import kotlinx.coroutines.CompletableDeferred
@@ -81,7 +81,13 @@ interface NestedDraggable {
* in the direction given by [sign], with the given number of [pointersDown] when the touch slop
* was detected.
*/
- fun onDragStarted(position: Offset, sign: Float, pointersDown: Int): Controller
+ fun onDragStarted(
+ position: Offset,
+ sign: Float,
+ pointersDown: Int,
+ // TODO(b/382665591): Make this non-nullable.
+ pointerType: PointerType?,
+ ): Controller
/**
* Whether this draggable should consume any scroll amount with the given [sign] coming from a
@@ -184,8 +190,8 @@ private class NestedDraggableNode(
*/
private var lastFirstDown: Offset? = null
- /** The number of pointers down. */
- private var pointersDownCount = 0
+ /** The pointers currently down, in order of which they were done and mapping to their type. */
+ private val pointersDown = linkedMapOf<PointerId, PointerType>()
init {
delegate(nestedScrollModifierNode(this, nestedScrollDispatcher))
@@ -256,7 +262,9 @@ private class NestedDraggableNode(
check(down.position == lastFirstDown) {
"Position from detectDrags() is not the same as position in trackDownPosition()"
}
- check(pointersDownCount == 1) { "pointersDownCount is equal to $pointersDownCount" }
+ check(pointersDown.size == 1 && pointersDown.keys.first() == down.id) {
+ "pointersDown should only contain $down but it contains $pointersDown"
+ }
var overSlop = 0f
val onTouchSlopReached = { change: PointerInputChange, over: Float ->
@@ -295,8 +303,9 @@ private class NestedDraggableNode(
}
}
- check(pointersDownCount > 0) { "pointersDownCount is equal to $pointersDownCount" }
- val controller = draggable.onDragStarted(down.position, sign, pointersDownCount)
+ check(pointersDown.size > 0) { "pointersDown is empty" }
+ val controller =
+ draggable.onDragStarted(down.position, sign, pointersDown.size, drag.type)
if (overSlop != 0f) {
onDrag(controller, drag, overSlop, velocityTracker)
}
@@ -450,20 +459,24 @@ private class NestedDraggableNode(
private suspend fun PointerInputScope.trackDownPosition() {
awaitEachGesture {
- val down = awaitFirstDown(requireUnconsumed = false)
- lastFirstDown = down.position
- pointersDownCount = 1
+ try {
+ val down = awaitFirstDown(requireUnconsumed = false)
+ lastFirstDown = down.position
+ pointersDown[down.id] = down.type
- do {
- pointersDownCount +=
- awaitPointerEvent().changes.fastSumBy { change ->
+ do {
+ awaitPointerEvent().changes.forEach { change ->
when {
- change.changedToDownIgnoreConsumed() -> 1
- change.changedToUpIgnoreConsumed() -> -1
- else -> 0
+ change.changedToDownIgnoreConsumed() -> {
+ pointersDown[change.id] = change.type
+ }
+ change.changedToUpIgnoreConsumed() -> pointersDown.remove(change.id)
}
}
- } while (pointersDownCount > 0)
+ } while (pointersDown.size > 0)
+ } finally {
+ pointersDown.clear()
+ }
}
}
@@ -491,12 +504,13 @@ private class NestedDraggableNode(
if (nestedScrollController == null && draggable.shouldConsumeNestedScroll(sign)) {
val startedPosition = checkNotNull(lastFirstDown) { "lastFirstDown is not set" }
- // TODO(b/382665591): Replace this by check(pointersDownCount > 0).
- val pointersDown = pointersDownCount.coerceAtLeast(1)
+ // TODO(b/382665591): Ensure that there is at least one pointer down.
+ val pointersDownCount = pointersDown.size.coerceAtLeast(1)
+ val pointerType = pointersDown.entries.firstOrNull()?.value
nestedScrollController =
NestedScrollController(
overscrollEffect,
- draggable.onDragStarted(startedPosition, sign, pointersDown),
+ draggable.onDragStarted(startedPosition, sign, pointersDownCount, pointerType),
)
}
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
index 9c49090916e3..7f70e97411f4 100644
--- a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
+++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
@@ -33,10 +33,12 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.PointerInputChange
+import androidx.compose.ui.input.pointer.PointerType
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performMouseInput
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeDown
import androidx.compose.ui.test.swipeLeft
@@ -653,6 +655,61 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
assertThat(flingIsDone).isTrue()
}
+ @Test
+ fun pointerType() {
+ val draggable = TestDraggable()
+ val touchSlop =
+ rule.setContentWithTouchSlop {
+ Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+ }
+
+ rule.onRoot().performTouchInput {
+ down(center)
+ moveBy(touchSlop.toOffset())
+ }
+
+ assertThat(draggable.onDragStartedPointerType).isEqualTo(PointerType.Touch)
+ }
+
+ @Test
+ fun pointerType_mouse() {
+ val draggable = TestDraggable()
+ val touchSlop =
+ rule.setContentWithTouchSlop {
+ Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+ }
+
+ rule.onRoot().performMouseInput {
+ moveTo(center)
+ press()
+ moveBy(touchSlop.toOffset())
+ release()
+ }
+
+ assertThat(draggable.onDragStartedPointerType).isEqualTo(PointerType.Mouse)
+ }
+
+ @Test
+ fun pointersDown_clearedWhenDisabled() {
+ val draggable = TestDraggable()
+ var enabled by mutableStateOf(true)
+ rule.setContent {
+ Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation, enabled = enabled))
+ }
+
+ rule.onRoot().performTouchInput { down(center) }
+
+ enabled = false
+ rule.waitForIdle()
+
+ rule.onRoot().performTouchInput { up() }
+
+ enabled = true
+ rule.waitForIdle()
+
+ rule.onRoot().performTouchInput { down(center) }
+ }
+
private fun ComposeContentTestRule.setContentWithTouchSlop(
content: @Composable () -> Unit
): Float {
@@ -688,6 +745,7 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
var onDragStartedPosition = Offset.Zero
var onDragStartedSign = 0f
var onDragStartedPointersDown = 0
+ var onDragStartedPointerType: PointerType? = null
var onDragDelta = 0f
override fun shouldStartDrag(change: PointerInputChange): Boolean = shouldStartDrag
@@ -696,11 +754,13 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
position: Offset,
sign: Float,
pointersDown: Int,
+ pointerType: PointerType?,
): NestedDraggable.Controller {
onDragStartedCalled = true
onDragStartedPosition = position
onDragStartedSign = sign
onDragStartedPointersDown = pointersDown
+ onDragStartedPointerType = pointerType
onDragDelta = 0f
onDragStarted.invoke(position, sign)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index c704a3e96467..de428a7d3548 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -35,6 +35,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
+import com.android.compose.gesture.NestedScrollableBound
import com.android.compose.gesture.effect.ContentOverscrollEffect
/**
@@ -238,6 +239,18 @@ interface BaseContentScope : ElementStateScope {
fun Modifier.noResizeDuringTransitions(): Modifier
/**
+ * Temporarily disable this content swipe actions when any scrollable below this modifier has
+ * consumed any amount of scroll delta, until the scroll gesture is finished.
+ *
+ * This can for instance be used to ensure that a scrollable list is overscrolled once it
+ * reached its bounds instead of directly starting a scene transition from the same scroll
+ * gesture.
+ */
+ fun Modifier.disableSwipesWhenScrolling(
+ bounds: NestedScrollableBound = NestedScrollableBound.Any
+ ): Modifier
+
+ /**
* A [NestedSceneTransitionLayout] will share its elements with its ancestor STLs therefore
* enabling sharedElement transitions between them.
*/
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index 607e4fadc256..ba92f9bea07d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -315,16 +315,10 @@ internal class SwipeAnimation<T : ContentKey>(
val skipAnimation =
hasReachedTargetContent && !contentTransition.isWithinProgressRange(initialProgress)
- val targetOffset =
- if (targetContent == fromContent) {
- 0f
- } else {
- val distance = distance()
- check(distance != DistanceUnspecified) {
- "distance is equal to $DistanceUnspecified"
- }
- distance
- }
+ val distance = distance()
+ check(distance != DistanceUnspecified) { "distance is equal to $DistanceUnspecified" }
+
+ val targetOffset = if (targetContent == fromContent) 0f else distance
// If the effective current content changed, it should be reflected right now in the
// current state, even before the settle animation is ongoing. That way all the
@@ -343,7 +337,16 @@ internal class SwipeAnimation<T : ContentKey>(
}
val animatable =
- Animatable(initialOffset, OffsetVisibilityThreshold).also { offsetAnimation = it }
+ Animatable(initialOffset, OffsetVisibilityThreshold).also {
+ offsetAnimation = it
+
+ // We should animate when the progress value is between [0, 1].
+ if (distance > 0) {
+ it.updateBounds(0f, distance)
+ } else {
+ it.updateBounds(distance, 0f)
+ }
+ }
check(isAnimatingOffset())
@@ -370,42 +373,26 @@ internal class SwipeAnimation<T : ContentKey>(
val velocityConsumed = CompletableDeferred<Float>()
offsetAnimationRunnable.complete {
- try {
+ val result =
animatable.animateTo(
targetValue = targetOffset,
animationSpec = swipeSpec,
initialVelocity = initialVelocity,
- ) {
- // Immediately stop this transition if we are bouncing on a content that
- // does not bounce.
- if (!contentTransition.isWithinProgressRange(progress)) {
- // We are no longer able to consume the velocity, the rest can be
- // consumed by another component in the hierarchy.
- velocityConsumed.complete(initialVelocity - velocity)
- throw SnapException()
- }
- }
- } catch (_: SnapException) {
- /* Ignore. */
- } finally {
- if (!velocityConsumed.isCompleted) {
- // The animation consumed the whole available velocity
- velocityConsumed.complete(initialVelocity)
- }
+ )
- // Wait for overscroll to finish so that the transition is removed from the STLState
- // only after the overscroll is done, to avoid dropping frame right when the user
- // lifts their finger and overscroll is animated to 0.
- overscrollCompletable?.await()
- }
+ // We are no longer able to consume the velocity, the rest can be consumed by another
+ // component in the hierarchy.
+ velocityConsumed.complete(initialVelocity - result.endState.velocity)
+
+ // Wait for overscroll to finish so that the transition is removed from the STLState
+ // only after the overscroll is done, to avoid dropping frame right when the user
+ // lifts their finger and overscroll is animated to 0.
+ overscrollCompletable?.await()
}
return velocityConsumed.await()
}
- /** An exception thrown during the animation to stop it immediately. */
- private class SnapException : Exception()
-
private fun canChangeContent(targetContent: ContentKey): Boolean {
return when (val transition = contentTransition) {
is TransitionState.Transition.ChangeScene ->
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index c5b3df222855..3f6bce724b1b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -54,7 +54,7 @@ private fun DraggableHandlerImpl.contentForSwipes(): Content {
/** Whether swipe should be enabled in the given [orientation]. */
internal fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
- if (userActions.isEmpty()) {
+ if (userActions.isEmpty() || !areSwipesAllowed()) {
return false
}
@@ -69,6 +69,10 @@ internal fun Content.shouldEnableSwipes(orientation: Orientation): Boolean {
* @return The best matching [UserActionResult], or `null` if no match is found.
*/
internal fun Content.findActionResultBestMatch(swipe: Swipe.Resolved): UserActionResult? {
+ if (!areSwipesAllowed()) {
+ return null
+ }
+
var bestPoints = Int.MIN_VALUE
var bestMatch: UserActionResult? = null
userActions.forEach { (actionSwipe, actionResult) ->
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 4c15f7a4534f..59b4a09385f5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -56,7 +56,10 @@ import com.android.compose.animation.scene.effect.GestureEffect
import com.android.compose.animation.scene.effect.VisualEffect
import com.android.compose.animation.scene.element
import com.android.compose.animation.scene.modifiers.noResizeDuringTransitions
+import com.android.compose.gesture.NestedScrollControlState
+import com.android.compose.gesture.NestedScrollableBound
import com.android.compose.gesture.effect.OffsetOverscrollEffect
+import com.android.compose.gesture.nestedScrollController
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.graphics.ContainerState
import com.android.compose.ui.graphics.container
@@ -70,7 +73,8 @@ internal sealed class Content(
actions: Map<UserAction.Resolved, UserActionResult>,
zIndex: Float,
) {
- internal val scope = ContentScopeImpl(layoutImpl, content = this)
+ private val nestedScrollControlState = NestedScrollControlState()
+ internal val scope = ContentScopeImpl(layoutImpl, content = this, nestedScrollControlState)
val containerState = ContainerState()
var content by mutableStateOf(content)
@@ -101,11 +105,14 @@ internal sealed class Content(
scope.content()
}
}
+
+ fun areSwipesAllowed(): Boolean = nestedScrollControlState.isOuterScrollAllowed
}
internal class ContentScopeImpl(
private val layoutImpl: SceneTransitionLayoutImpl,
private val content: Content,
+ private val nestedScrollControlState: NestedScrollControlState,
) : ContentScope, ElementStateScope by layoutImpl.elementStateScope {
override val contentKey: ContentKey
get() = content.key
@@ -176,6 +183,10 @@ internal class ContentScopeImpl(
return noResizeDuringTransitions(layoutState = layoutImpl.state)
}
+ override fun Modifier.disableSwipesWhenScrolling(bounds: NestedScrollableBound): Modifier {
+ return nestedScrollController(nestedScrollControlState, bounds)
+ }
+
@Composable
override fun NestedSceneTransitionLayout(
state: SceneTransitionLayoutState,
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ContentTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ContentTest.kt
new file mode 100644
index 000000000000..06a9735d97e2
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ContentTest.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 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.compose.animation.scene
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.rememberScrollableState
+import androidx.compose.foundation.gestures.scrollable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performTouchInput
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ContentTest {
+ @get:Rule val rule = createComposeRule()
+
+ @Test
+ fun disableSwipesWhenScrolling() {
+ lateinit var layoutImpl: SceneTransitionLayoutImpl
+ rule.setContent {
+ SceneTransitionLayoutForTesting(
+ remember { MutableSceneTransitionLayoutState(SceneA) },
+ onLayoutImpl = { layoutImpl = it },
+ ) {
+ scene(SceneA) {
+ Box(
+ Modifier.fillMaxSize()
+ .disableSwipesWhenScrolling()
+ .scrollable(rememberScrollableState { it }, Orientation.Vertical)
+ )
+ }
+ }
+ }
+
+ val content = layoutImpl.content(SceneA)
+ assertThat(content.areSwipesAllowed()).isTrue()
+ rule.onRoot().performTouchInput {
+ down(topLeft)
+ moveBy(bottomLeft)
+ }
+
+ assertThat(content.areSwipesAllowed()).isFalse()
+ rule.onRoot().performTouchInput { up() }
+ assertThat(content.areSwipesAllowed()).isTrue()
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 7c8c6e5f6c12..e580e3c40690 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -21,6 +21,7 @@ import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
@@ -33,6 +34,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.assertHeightIsEqualTo
@@ -43,6 +45,9 @@ import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChild
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.test.swipeDown
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.IntOffset
@@ -469,4 +474,41 @@ class SceneTransitionLayoutTest {
assertThat(layoutImpl.overlaysOrNullForTest()).isNull()
}
+
+ @Test
+ fun transitionProgressBoundedBetween0And1() {
+ val layoutWidth = 200.dp
+ val layoutHeight = 400.dp
+
+ // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
+ // detected as a drag event.
+ var touchSlop = 0f
+ val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(initialScene = SceneA) }
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ SceneTransitionLayout(state, Modifier.size(layoutWidth, layoutHeight)) {
+ scene(SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
+ Spacer(Modifier.fillMaxSize())
+ }
+ scene(SceneB) { Spacer(Modifier.fillMaxSize()) }
+ }
+ }
+ assertThat(state.transitionState).isIdle()
+
+ rule.mainClock.autoAdvance = false
+
+ // Swipe the verticalSwipeDistance.
+ rule.onRoot().performTouchInput {
+ swipeDown(endY = bottom + touchSlop, durationMillis = 50)
+ }
+
+ rule.mainClock.advanceTimeBy(16)
+ val transition = assertThat(state.transitionState).isSceneTransition()
+ assertThat(transition).isNotNull()
+ assertThat(transition).hasProgress(1f, tolerance = 0.01f)
+
+ rule.mainClock.advanceTimeBy(16)
+ // Fling animation, we are overscrolling now. Progress should always be between [0, 1].
+ assertThat(transition).hasProgress(1f)
+ }
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
index 0f8ca947479b..2b0825f39243 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt
@@ -30,7 +30,6 @@ import android.util.AttributeSet
import android.util.Log
import android.util.MathUtils
import android.util.TypedValue
-import android.view.View.MeasureSpec.AT_MOST
import android.view.View.MeasureSpec.EXACTLY
import android.view.animation.Interpolator
import android.widget.TextView
@@ -77,7 +76,6 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
var maxSingleDigitWidth = -1
var digitTranslateAnimator: DigitTranslateAnimator? = null
var aodFontSizePx: Float = -1F
- var isVertical: Boolean = false
// Store the font size when there's no height constraint as a reference when adjusting font size
private var lastUnconstrainedTextSize: Float = Float.MAX_VALUE
@@ -148,16 +146,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
logger.d("onMeasure()")
- if (isVertical) {
- // use at_most to avoid apply measuredWidth from last measuring to measuredHeight
- // cause we use max to setMeasuredDimension
- super.onMeasure(
- MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), AT_MOST),
- MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), AT_MOST),
- )
- } else {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
- }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val layout = this.layout
if (layout != null) {
@@ -213,18 +202,10 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
)
}
- if (isVertical) {
- expectedWidth = expectedHeight.also { expectedHeight = expectedWidth }
- }
setMeasuredDimension(expectedWidth, expectedHeight)
}
override fun onDraw(canvas: Canvas) {
- if (isVertical) {
- canvas.save()
- canvas.translate(0F, measuredHeight.toFloat())
- canvas.rotate(-90F)
- }
logger.d({ "onDraw(); ls: $str1" }) { str1 = textAnimator.textInterpolator.shapedText }
val translation = getLocalTranslation()
canvas.translate(translation.x.toFloat(), translation.y.toFloat())
@@ -238,9 +219,6 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
canvas.translate(-it.updatedTranslate.x.toFloat(), -it.updatedTranslate.y.toFloat())
}
canvas.translate(-translation.x.toFloat(), -translation.y.toFloat())
- if (isVertical) {
- canvas.restore()
- }
}
override fun invalidate() {
@@ -353,18 +331,20 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
}
private fun updateXtranslation(inPoint: Point, interpolatedTextBounds: Rect): Point {
- val viewWidth = if (isVertical) measuredHeight else measuredWidth
when (horizontalAlignment) {
HorizontalAlignment.LEFT -> {
inPoint.x = lockScreenPaint.strokeWidth.toInt() - interpolatedTextBounds.left
}
HorizontalAlignment.RIGHT -> {
inPoint.x =
- viewWidth - interpolatedTextBounds.right - lockScreenPaint.strokeWidth.toInt()
+ measuredWidth -
+ interpolatedTextBounds.right -
+ lockScreenPaint.strokeWidth.toInt()
}
HorizontalAlignment.CENTER -> {
inPoint.x =
- (viewWidth - interpolatedTextBounds.width()) / 2 - interpolatedTextBounds.left
+ (measuredWidth - interpolatedTextBounds.width()) / 2 -
+ interpolatedTextBounds.left
}
}
return inPoint
@@ -373,7 +353,6 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
// translation of reference point of text
// used for translation when calling textInterpolator
private fun getLocalTranslation(): Point {
- val viewHeight = if (isVertical) measuredWidth else measuredHeight
val interpolatedTextBounds = updateInterpolatedTextBounds()
val localTranslation = Point(0, 0)
val correctedBaseline = if (baseline != -1) baseline else baselineFromMeasure
@@ -381,7 +360,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
when (verticalAlignment) {
VerticalAlignment.CENTER -> {
localTranslation.y =
- ((viewHeight - interpolatedTextBounds.height()) / 2 -
+ ((measuredHeight - interpolatedTextBounds.height()) / 2 -
interpolatedTextBounds.top -
correctedBaseline)
}
@@ -392,7 +371,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe
}
VerticalAlignment.BOTTOM -> {
localTranslation.y =
- viewHeight -
+ measuredHeight -
interpolatedTextBounds.bottom -
lockScreenPaint.strokeWidth.toInt() -
correctedBaseline
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 2c1dacdfae73..4d2a6d9bd57a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -232,7 +232,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun testOnViewAttached_withAutoPinConfirmationFailedPasswordAttemptsLessThan5() {
val pinViewController = constructPinViewController(mockKeyguardPinView)
- `when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
`when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(3)
@@ -249,7 +248,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun testOnViewAttached_withAutoPinConfirmationFailedPasswordAttemptsMoreThan5() {
val pinViewController = constructPinViewController(mockKeyguardPinView)
- `when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
`when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(6)
@@ -275,7 +273,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun onUserInput_autoConfirmation_attemptsUnlock() {
val pinViewController = constructPinViewController(mockKeyguardPinView)
- whenever(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
whenever(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
whenever(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
whenever(passwordTextView.text).thenReturn("000000")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
index e659ef274980..698fac107a1d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepositoryTest.kt
@@ -18,7 +18,9 @@ package com.android.systemui.keyboard.shortcut.data.repository
import android.content.Context
import android.content.Context.INPUT_SERVICE
+import android.content.Intent
import android.hardware.input.InputGestureData
+import android.hardware.input.InputManager
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
import android.hardware.input.fakeInputManager
import android.platform.test.annotations.EnableFlags
@@ -27,9 +29,12 @@ import androidx.test.filters.SmallTest
import com.android.hardware.input.Flags.FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES
import com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER
import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyboard.shortcut.customInputGesturesRepository
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allAppsInputGestureData
+import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.goHomeInputGestureData
+import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.userTracker
@@ -48,18 +53,41 @@ import org.mockito.kotlin.whenever
@EnableFlags(FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES, FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
class CustomInputGesturesRepositoryTest : SysuiTestCase() {
- private val mockUserContext: Context = mock()
+ private val primaryUserContext: Context = mock()
+ private val secondaryUserContext: Context = mock()
+ private var activeUserContext: Context = primaryUserContext
+
private val kosmos = testKosmos().also {
- it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext })
+ it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { activeUserContext })
}
private val inputManager = kosmos.fakeInputManager.inputManager
+ private val broadcastDispatcher = kosmos.broadcastDispatcher
+ private val inputManagerForSecondaryUser: InputManager = mock()
private val testScope = kosmos.testScope
+ private val testHelper = kosmos.shortcutHelperTestHelper
private val customInputGesturesRepository = kosmos.customInputGesturesRepository
@Before
- fun setup(){
- whenever(mockUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager)
+ fun setup() {
+ activeUserContext = primaryUserContext
+ whenever(primaryUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager)
+ whenever(secondaryUserContext.getSystemService(INPUT_SERVICE))
+ .thenReturn(inputManagerForSecondaryUser)
+ }
+
+ @Test
+ fun customInputGestures_emitsNewUsersInputGesturesWhenUserIsSwitch() {
+ testScope.runTest {
+ setCustomInputGesturesForPrimaryUser(allAppsInputGestureData)
+ setCustomInputGesturesForSecondaryUser(goHomeInputGestureData)
+
+ val inputGestures by collectLastValue(customInputGesturesRepository.customInputGestures)
+ assertThat(inputGestures).containsExactly(allAppsInputGestureData)
+
+ switchToSecondaryUser()
+ assertThat(inputGestures).containsExactly(goHomeInputGestureData)
+ }
}
@Test
@@ -115,4 +143,24 @@ class CustomInputGesturesRepositoryTest : SysuiTestCase() {
}
}
+ private fun setCustomInputGesturesForPrimaryUser(vararg inputGesture: InputGestureData) {
+ whenever(
+ inputManager.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
+ ).thenReturn(inputGesture.toList())
+ }
+
+ private fun setCustomInputGesturesForSecondaryUser(vararg inputGesture: InputGestureData) {
+ whenever(
+ inputManagerForSecondaryUser.getCustomInputGestures(/* filter= */ InputGestureData.Filter.KEY)
+ ).thenReturn(inputGesture.toList())
+ }
+
+ private fun switchToSecondaryUser() {
+ activeUserContext = secondaryUserContext
+ broadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_USER_SWITCHED)
+ )
+ }
+
} \ No newline at end of file
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
index 2e9d6e85d0aa..49cbb5a924f1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplTest.java
@@ -53,7 +53,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -365,7 +364,6 @@ public class QuickSettingsControllerImplTest extends QuickSettingsControllerImpl
}
@Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
public void updateExpansion_partiallyExpanded_fullscreenFalse() {
// WHEN QS are only partially expanded
mQsController.setExpanded(true);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
index 83fb14aaf792..6b2c4b260806 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
@@ -9,9 +9,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -25,7 +24,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
@Before
fun setUp() {
- testScope = TestScope(StandardTestDispatcher())
+ testScope = TestScope(UnconfinedTestDispatcher())
}
@Test
@@ -34,11 +33,9 @@ class ConditionExtensionsTest : SysuiTestCase() {
val flow = flowOf(true)
val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
- runCurrent()
assertThat(condition.isConditionSet).isFalse()
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isTrue()
}
@@ -49,11 +46,9 @@ class ConditionExtensionsTest : SysuiTestCase() {
val flow = flowOf(false)
val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
- runCurrent()
assertThat(condition.isConditionSet).isFalse()
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
}
@@ -65,7 +60,6 @@ class ConditionExtensionsTest : SysuiTestCase() {
val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isFalse()
assertThat(condition.isConditionMet).isFalse()
}
@@ -78,11 +72,10 @@ class ConditionExtensionsTest : SysuiTestCase() {
flow.toCondition(
scope = this,
strategy = Condition.START_EAGERLY,
- initialValue = true
+ initialValue = true,
)
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isTrue()
}
@@ -95,11 +88,10 @@ class ConditionExtensionsTest : SysuiTestCase() {
flow.toCondition(
scope = this,
strategy = Condition.START_EAGERLY,
- initialValue = false
+ initialValue = false,
)
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
}
@@ -111,16 +103,13 @@ class ConditionExtensionsTest : SysuiTestCase() {
val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
condition.start()
- runCurrent()
assertThat(condition.isConditionSet).isTrue()
assertThat(condition.isConditionMet).isFalse()
flow.value = true
- runCurrent()
assertThat(condition.isConditionMet).isTrue()
flow.value = false
- runCurrent()
assertThat(condition.isConditionMet).isFalse()
condition.stop()
@@ -131,15 +120,12 @@ class ConditionExtensionsTest : SysuiTestCase() {
testScope.runTest {
val flow = MutableSharedFlow<Boolean>()
val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
- runCurrent()
assertThat(flow.subscriptionCount.value).isEqualTo(0)
condition.start()
- runCurrent()
assertThat(flow.subscriptionCount.value).isEqualTo(1)
condition.stop()
- runCurrent()
assertThat(flow.subscriptionCount.value).isEqualTo(0)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index a62d9d5ce62f..0061c4142e8b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -132,7 +132,7 @@ class CallChipViewModelTest : SysuiTestCase() {
val latest by collectLastValue(underTest.chip)
repo.setOngoingCallState(
- inCallModel(startTimeMs = 1000, notificationIcon = mock<StatusBarIconView>())
+ inCallModel(startTimeMs = 1000, notificationIcon = createStatusBarIconViewOrNull())
)
assertThat((latest as OngoingActivityChipModel.Shown).icon)
@@ -147,11 +147,12 @@ class CallChipViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun chip_positiveStartTime_notifIconFlagOn_iconIsNotifIcon() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- val notifIcon = mock<StatusBarIconView>()
+ val notifIcon = createStatusBarIconViewOrNull()
repo.setOngoingCallState(inCallModel(startTimeMs = 1000, notificationIcon = notifIcon))
assertThat((latest as OngoingActivityChipModel.Shown).icon)
@@ -165,6 +166,24 @@ class CallChipViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun chip_positiveStartTime_notifIconFlagOn_cdFlagOn_iconIsNotifKeyIcon() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(
+ inCallModel(
+ startTimeMs = 1000,
+ notificationIcon = createStatusBarIconViewOrNull(),
+ notificationKey = "notifKey",
+ )
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon("notifKey"))
+ }
+
+ @Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
fun chip_positiveStartTime_notifIconAndConnectedDisplaysFlagOn_iconIsNotifIcon() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -192,7 +211,7 @@ class CallChipViewModelTest : SysuiTestCase() {
val latest by collectLastValue(underTest.chip)
repo.setOngoingCallState(
- inCallModel(startTimeMs = 0, notificationIcon = mock<StatusBarIconView>())
+ inCallModel(startTimeMs = 0, notificationIcon = createStatusBarIconViewOrNull())
)
assertThat((latest as OngoingActivityChipModel.Shown).icon)
@@ -207,11 +226,12 @@ class CallChipViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
- fun chip_zeroStartTime_notifIconFlagOn_iconIsNotifIcon() =
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun chip_zeroStartTime_notifIconFlagOn_cdFlagOff_iconIsNotifIcon() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
- val notifIcon = mock<StatusBarIconView>()
+ val notifIcon = createStatusBarIconViewOrNull()
repo.setOngoingCallState(inCallModel(startTimeMs = 0, notificationIcon = notifIcon))
assertThat((latest as OngoingActivityChipModel.Shown).icon)
@@ -224,8 +244,27 @@ class CallChipViewModelTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun chip_zeroStartTime_notifIconFlagOn_cdFlagOn_iconIsNotifKeyIcon() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(
+ inCallModel(
+ startTimeMs = 0,
+ notificationIcon = createStatusBarIconViewOrNull(),
+ notificationKey = "notifKey",
+ )
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon("notifKey"))
+ }
+
+ @Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
- fun chip_notifIconFlagOn_butNullNotifIcon_iconIsPhone() =
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun chip_notifIconFlagOn_butNullNotifIcon_cdFlagOff_iconIsPhone() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -242,6 +281,24 @@ class CallChipViewModelTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun chip_notifIconFlagOn_butNullNotifIcon_iconNotifKey() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.chip)
+
+ repo.setOngoingCallState(
+ inCallModel(
+ startTimeMs = 1000,
+ notificationIcon = null,
+ notificationKey = "notifKey",
+ )
+ )
+
+ assertThat((latest as OngoingActivityChipModel.Shown).icon)
+ .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon("notifKey"))
+ }
+
+ @Test
fun chip_positiveStartTime_colorsAreThemed() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
@@ -330,4 +387,13 @@ class CallChipViewModelTest : SysuiTestCase() {
verify(kosmos.activityStarter).postStartActivityDismissingKeyguard(intent, null)
}
+
+ companion object {
+ fun createStatusBarIconViewOrNull(): StatusBarIconView? =
+ if (StatusBarConnectedDisplays.isEnabled) {
+ null
+ } else {
+ mock<StatusBarIconView>()
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt
index 0d033a4098ec..fe15eac46e2d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.chips.notification.domain.interactor
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -148,7 +149,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
}
@Test
- fun notificationChip_missingStatusBarIconChipView_inConstructor_emitsNull() =
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChip_missingStatusBarIconChipView_cdFlagDisabled_inConstructor_emitsNull() =
kosmos.runTest {
val underTest =
factory.create(
@@ -167,6 +169,25 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
@Test
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChip_missingStatusBarIconChipView_cdFlagEnabled_inConstructor_emitsNotNull() =
+ kosmos.runTest {
+ val underTest =
+ factory.create(
+ activeNotificationModel(
+ key = "notif1",
+ statusBarChipIcon = null,
+ promotedContent = PROMOTED_CONTENT,
+ ),
+ 32L,
+ )
+
+ val latest by collectLastValue(underTest.notificationChip)
+
+ assertThat(latest).isNotNull()
+ }
+
+ @Test
+ @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun notificationChip_cdEnabled_missingStatusBarIconChipView_inConstructor_emitsNotNull() =
kosmos.runTest {
val underTest =
@@ -186,7 +207,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
}
@Test
- fun notificationChip_missingStatusBarIconChipView_inSet_emitsNull() =
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChip_cdFlagDisabled_missingStatusBarIconChipView_inSet_emitsNull() =
kosmos.runTest {
val startingNotif =
activeNotificationModel(
@@ -211,6 +233,31 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() {
@Test
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChip_cdFlagEnabled_missingStatusBarIconChipView_inSet_emitsNotNull() =
+ kosmos.runTest {
+ val startingNotif =
+ activeNotificationModel(
+ key = "notif1",
+ statusBarChipIcon = mock(),
+ promotedContent = PROMOTED_CONTENT,
+ )
+ val underTest = factory.create(startingNotif, 123L)
+ val latest by collectLastValue(underTest.notificationChip)
+ assertThat(latest).isNotNull()
+
+ underTest.setNotification(
+ activeNotificationModel(
+ key = "notif1",
+ statusBarChipIcon = null,
+ promotedContent = PROMOTED_CONTENT,
+ )
+ )
+
+ assertThat(latest).isNotNull()
+ }
+
+ @Test
+ @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
fun notificationChip_missingStatusBarIconChipView_inSet_cdEnabled_emitsNotNull() =
kosmos.runTest {
val startingNotif =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt
index f703d785ceac..ee4a52d35d68 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
@@ -83,7 +84,8 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() {
@Test
@EnableFlags(StatusBarNotifChips.FLAG_NAME)
- fun notificationChips_notifMissingStatusBarChipIconView_empty() =
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChips_notifMissingStatusBarChipIconView_cdFlagOff_empty() =
kosmos.runTest {
val latest by collectLastValue(underTest.notificationChips)
@@ -101,6 +103,25 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(StatusBarNotifChips.FLAG_NAME, StatusBarConnectedDisplays.FLAG_NAME)
+ fun notificationChips_notifMissingStatusBarChipIconView_cdFlagOn_notEmpty() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.notificationChips)
+
+ setNotifs(
+ listOf(
+ activeNotificationModel(
+ key = "notif",
+ statusBarChipIcon = null,
+ promotedContent = PromotedNotificationContentModel.Builder("notif").build(),
+ )
+ )
+ )
+
+ assertThat(latest).isNotEmpty()
+ }
+
+ @Test
@EnableFlags(StatusBarNotifChips.FLAG_NAME)
fun notificationChips_onePromotedNotif_statusBarIconViewMatches() =
kosmos.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 17076b4d7505..e561e3ea27d7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -23,7 +23,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.kosmos.collectLastValue
@@ -31,6 +30,7 @@ import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.chips.call.ui.viewmodel.CallChipViewModelTest.Companion.createStatusBarIconViewOrNull
import com.android.systemui.statusbar.chips.notification.domain.interactor.statusBarNotificationChipsInteractor
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
@@ -48,7 +48,6 @@ import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
@@ -84,8 +83,8 @@ class NotifChipsViewModelTest : SysuiTestCase() {
}
@Test
- @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
- fun chips_notifMissingStatusBarChipIconView_empty() =
+ @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY, StatusBarConnectedDisplays.FLAG_NAME)
+ fun chips_notifMissingStatusBarChipIconView_cdFlagDisabled_empty() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
@@ -104,11 +103,31 @@ class NotifChipsViewModelTest : SysuiTestCase() {
@Test
@DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+ @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun chips_notifMissingStatusBarChipIconView_cdFlagEnabled_notEmpty() =
+ kosmos.runTest {
+ val latest by collectLastValue(underTest.chips)
+
+ setNotifs(
+ listOf(
+ activeNotificationModel(
+ key = "notif",
+ statusBarChipIcon = null,
+ promotedContent = PromotedNotificationContentModel.Builder("notif").build(),
+ )
+ )
+ )
+
+ assertThat(latest).isNotEmpty()
+ }
+
+ @Test
+ @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
fun chips_onePromotedNotif_statusBarIconViewMatches() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
- val icon = mock<StatusBarIconView>()
+ val icon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -121,8 +140,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
assertThat(latest).hasSize(1)
val chip = latest!![0]
- assertThat(chip).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
- assertThat(chip.icon).isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarView(icon))
+ assertIsNotifChip(chip, icon, "notif")
}
@Test
@@ -168,7 +186,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -187,8 +205,8 @@ class NotifChipsViewModelTest : SysuiTestCase() {
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
- val firstIcon = mock<StatusBarIconView>()
- val secondIcon = mock<StatusBarIconView>()
+ val firstIcon = createStatusBarIconViewOrNull()
+ val secondIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -203,15 +221,15 @@ class NotifChipsViewModelTest : SysuiTestCase() {
),
activeNotificationModel(
key = "notif3",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = null,
),
)
)
assertThat(latest).hasSize(2)
- assertIsNotifChip(latest!![0], firstIcon)
- assertIsNotifChip(latest!![1], secondIcon)
+ assertIsNotifChip(latest!![0], firstIcon, "notif1")
+ assertIsNotifChip(latest!![1], secondIcon, "notif2")
}
@Test
@@ -269,7 +287,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -293,7 +311,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -323,7 +341,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -353,7 +371,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -382,7 +400,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -411,7 +429,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -439,7 +457,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -467,7 +485,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -499,7 +517,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = promotedContentBuilder.build(),
)
)
@@ -531,7 +549,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
listOf(
activeNotificationModel(
key = "clickTest",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent =
PromotedNotificationContentModel.Builder("clickTest").build(),
)
@@ -552,9 +570,21 @@ class NotifChipsViewModelTest : SysuiTestCase() {
}
companion object {
- fun assertIsNotifChip(latest: OngoingActivityChipModel?, expectedIcon: StatusBarIconView) {
- assertThat((latest as OngoingActivityChipModel.Shown).icon)
- .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarView(expectedIcon))
+ fun assertIsNotifChip(
+ latest: OngoingActivityChipModel?,
+ expectedIcon: StatusBarIconView?,
+ notificationKey: String,
+ ) {
+ val shown = latest as OngoingActivityChipModel.Shown
+ if (StatusBarConnectedDisplays.isEnabled) {
+ assertThat(shown.icon)
+ .isEqualTo(
+ OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon(notificationKey)
+ )
+ } else {
+ assertThat(latest.icon)
+ .isEqualTo(OngoingActivityChipModel.ChipIcon.StatusBarView(expectedIcon!!))
+ }
}
fun assertIsNotifKey(latest: OngoingActivityChipModel?, expectedKey: String) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index 4fb42e94adb2..42358cce59a2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.Me
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.phone.mockSystemUIDialogFactory
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.ongoingCallRepository
@@ -169,29 +170,35 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
@Test
fun primaryChip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
testScope.runTest {
+ val notificationKey = "call"
screenRecordState.value = ScreenRecordModel.DoingNothing
// MediaProjection covers both share-to-app and cast-to-other-device
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = notificationKey)
+ )
val latest by collectLastValue(underTest.primaryChip)
- assertIsCallChip(latest)
+ assertIsCallChip(latest, notificationKey)
}
@Test
fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
testScope.runTest {
// Start with just the lowest priority chip shown
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ val callNotificationKey = "call"
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
// And everything else hidden
mediaProjectionState.value = MediaProjectionState.NotProjecting
screenRecordState.value = ScreenRecordModel.DoingNothing
val latest by collectLastValue(underTest.primaryChip)
- assertIsCallChip(latest)
+ assertIsCallChip(latest, callNotificationKey)
// WHEN the higher priority media projection chip is added
mediaProjectionState.value =
@@ -218,7 +225,10 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ val callNotificationKey = "call"
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
val latest by collectLastValue(underTest.primaryChip)
@@ -235,7 +245,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
mediaProjectionState.value = MediaProjectionState.NotProjecting
// THEN the lower priority call is used
- assertIsCallChip(latest)
+ assertIsCallChip(latest, callNotificationKey)
}
/** Regression test for b/347726238. */
@@ -364,13 +374,27 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
assertThat(icon.res).isEqualTo(R.drawable.ic_present_to_all)
}
- fun assertIsCallChip(latest: OngoingActivityChipModel?) {
- assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java)
+ fun assertIsCallChip(latest: OngoingActivityChipModel?, notificationKey: String) {
+ assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Timer::class.java)
+ if (StatusBarConnectedDisplays.isEnabled) {
+ assertNotificationIcon(latest, notificationKey)
+ return
+ }
val icon =
(((latest as OngoingActivityChipModel.Shown).icon)
as OngoingActivityChipModel.ChipIcon.SingleColorIcon)
.impl as Icon.Resource
assertThat(icon.res).isEqualTo(com.android.internal.R.drawable.ic_phone)
}
+
+ private fun assertNotificationIcon(
+ latest: OngoingActivityChipModel?,
+ notificationKey: String,
+ ) {
+ val shown = latest as OngoingActivityChipModel.Shown
+ val notificationIcon =
+ shown.icon as OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon
+ assertThat(notificationIcon.notificationKey).isEqualTo(notificationKey)
+ }
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
index 0050ebee64d6..0f42f29e76ee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt
@@ -34,7 +34,7 @@ import com.android.systemui.mediaprojection.taskswitcher.FakeActivityTaskManager
import com.android.systemui.res.R
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.screenRecordRepository
-import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.chips.call.ui.viewmodel.CallChipViewModelTest.Companion.createStatusBarIconViewOrNull
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.NORMAL_PACKAGE
import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.setUpPackageManagerForMediaProjection
import com.android.systemui.statusbar.chips.notification.domain.interactor.statusBarNotificationChipsInteractor
@@ -186,13 +186,16 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
@Test
fun chips_screenRecordShowAndCallShow_primaryIsScreenRecordSecondaryIsCall() =
testScope.runTest {
+ val callNotificationKey = "call"
screenRecordState.value = ScreenRecordModel.Recording
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
val latest by collectLastValue(underTest.chips)
assertIsScreenRecordChip(latest!!.primary)
- assertIsCallChip(latest!!.secondary)
+ assertIsCallChip(latest!!.secondary, callNotificationKey)
}
@Test
@@ -240,15 +243,18 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
@Test
fun chips_shareToAppShowAndCallShow_primaryIsShareToAppSecondaryIsCall() =
testScope.runTest {
+ val callNotificationKey = "call"
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
val latest by collectLastValue(underTest.chips)
assertIsShareToAppChip(latest!!.primary)
- assertIsCallChip(latest!!.secondary)
+ assertIsCallChip(latest!!.secondary, callNotificationKey)
}
@Test
@@ -258,25 +264,31 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
// MediaProjection covers both share-to-app and cast-to-other-device
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ val callNotificationKey = "call"
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
val latest by collectLastValue(underTest.primaryChip)
- assertIsCallChip(latest)
+ assertIsCallChip(latest, callNotificationKey)
}
@Test
fun chips_onlyCallShown_primaryIsCallSecondaryIsHidden() =
testScope.runTest {
+ val callNotificationKey = "call"
screenRecordState.value = ScreenRecordModel.DoingNothing
// MediaProjection covers both share-to-app and cast-to-other-device
mediaProjectionState.value = MediaProjectionState.NotProjecting
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
val latest by collectLastValue(underTest.chips)
- assertIsCallChip(latest!!.primary)
+ assertIsCallChip(latest!!.primary, callNotificationKey)
assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
}
@@ -285,7 +297,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
testScope.runTest {
val latest by collectLastValue(underTest.chips)
- val icon = mock<StatusBarIconView>()
+ val icon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -296,7 +308,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
)
)
- assertIsNotifChip(latest!!.primary, icon)
+ assertIsNotifChip(latest!!.primary, icon, "notif")
assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
}
@@ -305,8 +317,8 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
testScope.runTest {
val latest by collectLastValue(underTest.chips)
- val firstIcon = mock<StatusBarIconView>()
- val secondIcon = mock<StatusBarIconView>()
+ val firstIcon = createStatusBarIconViewOrNull()
+ val secondIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -324,8 +336,8 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
)
)
- assertIsNotifChip(latest!!.primary, firstIcon)
- assertIsNotifChip(latest!!.secondary, secondIcon)
+ assertIsNotifChip(latest!!.primary, firstIcon, "firstNotif")
+ assertIsNotifChip(latest!!.secondary, secondIcon, "secondNotif")
}
@Test
@@ -333,9 +345,9 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
testScope.runTest {
val latest by collectLastValue(underTest.chips)
- val firstIcon = mock<StatusBarIconView>()
- val secondIcon = mock<StatusBarIconView>()
- val thirdIcon = mock<StatusBarIconView>()
+ val firstIcon = createStatusBarIconViewOrNull()
+ val secondIcon = createStatusBarIconViewOrNull()
+ val thirdIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -359,8 +371,8 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
)
)
- assertIsNotifChip(latest!!.primary, firstIcon)
- assertIsNotifChip(latest!!.secondary, secondIcon)
+ assertIsNotifChip(latest!!.primary, firstIcon, "firstNotif")
+ assertIsNotifChip(latest!!.secondary, secondIcon, "secondNotif")
}
@Test
@@ -368,8 +380,12 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
testScope.runTest {
val latest by collectLastValue(underTest.chips)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val firstIcon = mock<StatusBarIconView>()
+ val callNotificationKey = "call"
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
+
+ val firstIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -380,43 +396,47 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
),
activeNotificationModel(
key = "secondNotif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent =
PromotedNotificationContentModel.Builder("secondNotif").build(),
),
)
)
- assertIsCallChip(latest!!.primary)
- assertIsNotifChip(latest!!.secondary, firstIcon)
+ assertIsCallChip(latest!!.primary, callNotificationKey)
+ assertIsNotifChip(latest!!.secondary, firstIcon, "firstNotif")
}
@Test
fun chips_screenRecordAndCallAndPromotedNotifs_notifsNotShown() =
testScope.runTest {
+ val callNotificationKey = "call"
val latest by collectLastValue(underTest.chips)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
screenRecordState.value = ScreenRecordModel.Recording
setNotifs(
listOf(
activeNotificationModel(
key = "notif",
- statusBarChipIcon = mock<StatusBarIconView>(),
+ statusBarChipIcon = createStatusBarIconViewOrNull(),
promotedContent = PromotedNotificationContentModel.Builder("notif").build(),
)
)
)
assertIsScreenRecordChip(latest!!.primary)
- assertIsCallChip(latest!!.secondary)
+ assertIsCallChip(latest!!.secondary, callNotificationKey)
}
@Test
fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
testScope.runTest {
+ val callNotificationKey = "call"
// Start with just the lowest priority chip shown
- val notifIcon = mock<StatusBarIconView>()
+ val notifIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -433,13 +453,15 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
val latest by collectLastValue(underTest.primaryChip)
- assertIsNotifChip(latest, notifIcon)
+ assertIsNotifChip(latest, notifIcon, "notif")
// WHEN the higher priority call chip is added
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
// THEN the higher priority call chip is used
- assertIsCallChip(latest)
+ assertIsCallChip(latest, callNotificationKey)
// WHEN the higher priority media projection chip is added
mediaProjectionState.value =
@@ -462,12 +484,15 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
@Test
fun primaryChip_highestPriorityChipRemoved_showsNextPriorityChip() =
testScope.runTest {
+ val callNotificationKey = "call"
// WHEN all chips are active
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val notifIcon = mock<StatusBarIconView>()
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
+ val notifIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -493,20 +518,21 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
mediaProjectionState.value = MediaProjectionState.NotProjecting
// THEN the lower priority call is used
- assertIsCallChip(latest)
+ assertIsCallChip(latest, callNotificationKey)
// WHEN the higher priority call is removed
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
// THEN the lower priority notif is used
- assertIsNotifChip(latest, notifIcon)
+ assertIsNotifChip(latest, notifIcon, "notif")
}
@Test
fun chips_movesChipsAroundAccordingToPriority() =
testScope.runTest {
+ val callNotificationKey = "call"
// Start with just the lowest priority chip shown
- val notifIcon = mock<StatusBarIconView>()
+ val notifIcon = createStatusBarIconViewOrNull()
setNotifs(
listOf(
activeNotificationModel(
@@ -523,16 +549,18 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
val latest by collectLastValue(underTest.chips)
- assertIsNotifChip(latest!!.primary, notifIcon)
+ assertIsNotifChip(latest!!.primary, notifIcon, "notif")
assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
// WHEN the higher priority call chip is added
- callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
+ callRepo.setOngoingCallState(
+ inCallModel(startTimeMs = 34, notificationKey = callNotificationKey)
+ )
// THEN the higher priority call chip is used as primary and notif is demoted to
// secondary
- assertIsCallChip(latest!!.primary)
- assertIsNotifChip(latest!!.secondary, notifIcon)
+ assertIsCallChip(latest!!.primary, callNotificationKey)
+ assertIsNotifChip(latest!!.secondary, notifIcon, "notif")
// WHEN the higher priority media projection chip is added
mediaProjectionState.value =
@@ -545,7 +573,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
// THEN the higher priority media projection chip is used as primary and call is demoted
// to secondary (and notif is dropped altogether)
assertIsShareToAppChip(latest!!.primary)
- assertIsCallChip(latest!!.secondary)
+ assertIsCallChip(latest!!.secondary, callNotificationKey)
// WHEN the higher priority screen record chip is added
screenRecordState.value = ScreenRecordModel.Recording
@@ -559,13 +587,13 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
// THEN media projection and notif remain
assertIsShareToAppChip(latest!!.primary)
- assertIsNotifChip(latest!!.secondary, notifIcon)
+ assertIsNotifChip(latest!!.secondary, notifIcon, "notif")
// WHEN media projection is dropped
mediaProjectionState.value = MediaProjectionState.NotProjecting
// THEN notif is promoted to primary
- assertIsNotifChip(latest!!.primary, notifIcon)
+ assertIsNotifChip(latest!!.primary, notifIcon, "notif")
assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
index a70d24efada7..912633c874ed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
@@ -28,11 +28,11 @@ import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+import com.android.systemui.util.mockito.withArgCaptor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
-import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.inOrder
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
@@ -59,10 +59,9 @@ class RenderStageManagerTest : SysuiTestCase() {
fun setUp() {
renderStageManager = RenderStageManager()
renderStageManager.attach(shadeListBuilder)
-
- val captor = argumentCaptor<ShadeListBuilder.OnRenderListListener>()
- verify(shadeListBuilder).setOnRenderListListener(captor.capture())
- onRenderListListener = captor.lastValue
+ onRenderListListener = withArgCaptor {
+ verify(shadeListBuilder).setOnRenderListListener(capture())
+ }
}
private fun setUpRenderer() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
index 34f46088ad79..3d5d1eddf581 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
@@ -33,7 +33,6 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.policy.data.repository.zenModeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -48,7 +47,6 @@ import platform.test.runner.parameterized.Parameters
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(ParameterizedAndroidJunit4::class)
@SmallTest
-@EnableFlags(FooterViewRefactor.FLAG_NAME)
class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
index 615f4b01df9b..daa1db2d49fa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification.footer.ui.view;
-import static com.android.systemui.log.LogAssertKt.assertLogsWtf;
-
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
@@ -34,7 +32,6 @@ import static org.mockito.Mockito.verify;
import android.content.Context;
import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,7 +41,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter;
import org.junit.Before;
@@ -62,8 +58,7 @@ public class FooterViewTest extends SysuiTestCase {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getFlags() {
- return FlagsParameterization.progressionOf(FooterViewRefactor.FLAG_NAME,
- NotifRedesignFooter.FLAG_NAME);
+ return FlagsParameterization.allCombinationsOf(NotifRedesignFooter.FLAG_NAME);
}
public FooterViewTest(FlagsParameterization flags) {
@@ -106,24 +101,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void setHistoryShown() {
- mView.showHistory(true);
- assertTrue(mView.isHistoryShown());
- assertTrue(((TextView) mView.findViewById(R.id.manage_text))
- .getText().toString().contains("History"));
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void setHistoryNotShown() {
- mView.showHistory(false);
- assertFalse(mView.isHistoryShown());
- assertTrue(((TextView) mView.findViewById(R.id.manage_text))
- .getText().toString().contains("Manage"));
- }
-
- @Test
public void testPerformVisibilityAnimation() {
mView.setVisible(false /* visible */, false /* animate */);
assertFalse(mView.isVisible());
@@ -140,7 +117,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
@DisableFlags(NotifRedesignFooter.FLAG_NAME)
public void testSetManageOrHistoryButtonText_resourceOnlyFetchedOnce() {
int resId = R.string.manage_notifications_history_text;
@@ -160,16 +136,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetManageOrHistoryButtonText_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.string.manage_notifications_history_text;
- assertLogsWtf(() -> mView.setManageOrHistoryButtonText(resId));
- verify(mSpyContext, never()).getString(anyInt());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
@DisableFlags(NotifRedesignFooter.FLAG_NAME)
public void testSetManageOrHistoryButtonDescription_resourceOnlyFetchedOnce() {
int resId = R.string.manage_notifications_history_text;
@@ -189,16 +155,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetManageOrHistoryButtonDescription_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.string.accessibility_clear_all;
- assertLogsWtf(() -> mView.setManageOrHistoryButtonDescription(resId));
- verify(mSpyContext, never()).getString(anyInt());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
public void testSetClearAllButtonText_resourceOnlyFetchedOnce() {
int resId = R.string.clear_all_notifications_text;
mView.setClearAllButtonText(resId);
@@ -217,16 +173,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetClearAllButtonText_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.string.clear_all_notifications_text;
- assertLogsWtf(() -> mView.setClearAllButtonText(resId));
- verify(mSpyContext, never()).getString(anyInt());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
public void testSetClearAllButtonDescription_resourceOnlyFetchedOnce() {
int resId = R.string.accessibility_clear_all;
mView.setClearAllButtonDescription(resId);
@@ -245,16 +191,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetClearAllButtonDescription_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.string.accessibility_clear_all;
- assertLogsWtf(() -> mView.setClearAllButtonDescription(resId));
- verify(mSpyContext, never()).getString(anyInt());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
public void testSetMessageString_resourceOnlyFetchedOnce() {
int resId = R.string.unlock_to_see_notif_text;
mView.setMessageString(resId);
@@ -273,16 +209,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetMessageString_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.string.unlock_to_see_notif_text;
- assertLogsWtf(() -> mView.setMessageString(resId));
- verify(mSpyContext, never()).getString(anyInt());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
public void testSetMessageIcon_resourceOnlyFetchedOnce() {
int resId = R.drawable.ic_friction_lock_closed;
mView.setMessageIcon(resId);
@@ -298,15 +224,6 @@ public class FooterViewTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testSetMessageIcon_expectsFlagEnabled() {
- clearInvocations(mSpyContext);
- int resId = R.drawable.ic_friction_lock_closed;
- assertLogsWtf(() -> mView.setMessageIcon(resId));
- verify(mSpyContext, never()).getDrawable(anyInt());
- }
-
- @Test
public void testSetFooterLabelVisible() {
mView.setFooterLabelVisible(true);
assertThat(mView.findViewById(R.id.unlock_prompt_footer).getVisibility())
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
index 1adfc2b72214..06b1c432955a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -40,7 +40,6 @@ import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRe
import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter
import com.android.systemui.testKosmos
import com.android.systemui.util.ui.isAnimating
@@ -57,7 +56,6 @@ import platform.test.runner.parameterized.Parameters
@RunWith(ParameterizedAndroidJunit4::class)
@SmallTest
-@EnableFlags(FooterViewRefactor.FLAG_NAME)
class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index c6cffa9da13b..20cd6c7517e2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -25,14 +25,10 @@ import static com.android.systemui.statusbar.notification.stack.NotificationStac
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -45,7 +41,6 @@ import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.testing.TestableLooper;
import android.view.MotionEvent;
-import android.view.View;
import android.view.ViewTreeObserver;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -57,15 +52,12 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.ExpandHelper;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.DisableSceneContainer;
import com.android.systemui.flags.EnableSceneContainer;
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
-import com.android.systemui.keyguard.shared.model.KeyguardState;
-import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.media.controls.ui.controller.KeyguardMediaController;
import com.android.systemui.plugins.ActivityStarter;
@@ -78,23 +70,18 @@ import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
-import com.android.systemui.statusbar.notification.collection.render.NotifStats;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
-import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
-import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -106,11 +93,8 @@ import com.android.systemui.statusbar.notification.stack.ui.viewbinder.Notificat
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
@@ -145,16 +129,13 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
@Mock private Provider<IStatusBarService> mStatusBarService;
@Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@Mock private TunerService mTunerService;
- @Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private ConfigurationController mConfigurationController;
@Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock private ZenModeController mZenModeController;
@Mock private KeyguardMediaController mKeyguardMediaController;
@Mock private SysuiStatusBarStateController mSysuiStatusBarStateController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private PowerInteractor mPowerInteractor;
- @Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
@Mock private WallpaperInteractor mWallpaperInteractor;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private MetricsLogger mMetricsLogger;
@@ -164,12 +145,10 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
private NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
@Mock private GroupExpansionManager mGroupExpansionManager;
- @Mock private SectionHeaderController mSilentHeaderController;
@Mock private NotifPipeline mNotifPipeline;
@Mock private NotifCollection mNotifCollection;
@Mock private UiEventLogger mUiEventLogger;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
@Mock private ShadeController mShadeController;
@Mock private Provider<WindowRootView> mWindowRootView;
@@ -193,9 +172,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
- private final SeenNotificationsInteractor mSeenNotificationsInteractor =
- mKosmos.getSeenNotificationsInteractor();
-
private NotificationStackScrollLayoutController mController;
private NotificationTestHelper mNotificationTestHelper;
@@ -279,114 +255,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
}
@Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateEmptyShadeView_notificationsVisible_zenHiding() {
- when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(true);
- initController(/* viewIsAttached= */ true);
-
- setupShowEmptyShadeViewState(true);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ true,
- /* notifVisibleInShade= */ true);
-
- setupShowEmptyShadeViewState(false);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ false,
- /* notifVisibleInShade= */ true);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateEmptyShadeView_notificationsHidden_zenNotHiding() {
- when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
- initController(/* viewIsAttached= */ true);
-
- setupShowEmptyShadeViewState(true);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ true,
- /* notifVisibleInShade= */ false);
-
- setupShowEmptyShadeViewState(false);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ false,
- /* notifVisibleInShade= */ false);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateEmptyShadeView_splitShadeMode_alwaysShowEmptyView() {
- when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
- initController(/* viewIsAttached= */ true);
-
- verify(mSysuiStatusBarStateController).addCallback(
- mStateListenerArgumentCaptor.capture(), anyInt());
- StatusBarStateController.StateListener stateListener =
- mStateListenerArgumentCaptor.getValue();
- stateListener.onStateChanged(SHADE);
- mController.getView().removeAllViews();
-
- mController.setQsFullScreen(false);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ true,
- /* notifVisibleInShade= */ false);
-
- mController.setQsFullScreen(true);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ true,
- /* notifVisibleInShade= */ false);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateEmptyShadeView_bouncerShowing_hideEmptyView() {
- when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
- initController(/* viewIsAttached= */ true);
-
- when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(true);
-
- setupShowEmptyShadeViewState(true);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
-
- // THEN the PrimaryBouncerInteractor value is used. Since the bouncer is showing, we
- // hide the empty view.
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ false,
- /* areNotificationsHiddenInShade= */ false);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateEmptyShadeView_bouncerNotShowing_showEmptyView() {
- when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
- initController(/* viewIsAttached= */ true);
-
- when(mPrimaryBouncerInteractor.isBouncerShowing()).thenReturn(false);
-
- setupShowEmptyShadeViewState(true);
- reset(mNotificationStackScrollLayout);
- mController.updateShowEmptyShadeView();
-
- // THEN the PrimaryBouncerInteractor value is used. Since the bouncer isn't showing, we
- // can show the empty view.
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(
- /* visible= */ true,
- /* areNotificationsHiddenInShade= */ false);
- }
-
- @Test
public void testOnUserChange_verifyNotSensitive() {
when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false);
initController(/* viewIsAttached= */ true);
@@ -788,31 +656,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
}
@Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testUpdateFooter_remoteInput() {
- ArgumentCaptor<RemoteInputController.Callback> callbackCaptor =
- ArgumentCaptor.forClass(RemoteInputController.Callback.class);
- doNothing().when(mRemoteInputManager).addControllerCallback(callbackCaptor.capture());
- when(mRemoteInputManager.isRemoteInputActive()).thenReturn(false);
- initController(/* viewIsAttached= */ true);
- verify(mNotificationStackScrollLayout).setIsRemoteInputActive(false);
- RemoteInputController.Callback callback = callbackCaptor.getValue();
- callback.onRemoteInputActive(true);
- verify(mNotificationStackScrollLayout).setIsRemoteInputActive(true);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void testSetNotifStats_updatesHasFilteredOutSeenNotifications() {
- initController(/* viewIsAttached= */ true);
- mSeenNotificationsInteractor.setHasFilteredOutSeenNotifications(true);
- mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
- verify(mNotificationStackScrollLayout).setHasFilteredOutSeenNotifications(true);
- verify(mNotificationStackScrollLayout).updateFooter();
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
- }
-
- @Test
public void testAttach_updatesViewStatusBarState() {
// GIVEN: Controller is attached
initController(/* viewIsAttached= */ true);
@@ -844,98 +687,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
}
@Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateImportantForAccessibility_noChild_onKeyGuard_notImportantForA11y() {
- // GIVEN: Controller is attached, active notifications is empty,
- // and mNotificationStackScrollLayout.onKeyguard() is true
- initController(/* viewIsAttached= */ true);
- when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(true);
- mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
-
- // THEN: mNotificationStackScrollLayout should not be important for A11y
- verify(mNotificationStackScrollLayout)
- .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateImportantForAccessibility_hasChild_onKeyGuard_importantForA11y() {
- // GIVEN: Controller is attached, active notifications is not empty,
- // and mNotificationStackScrollLayout.onKeyguard() is true
- initController(/* viewIsAttached= */ true);
- when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(true);
- mController.getNotifStackController().setNotifStats(
- new NotifStats(
- /* numActiveNotifs = */ 1,
- /* hasNonClearableAlertingNotifs = */ false,
- /* hasClearableAlertingNotifs = */ false,
- /* hasNonClearableSilentNotifs = */ false,
- /* hasClearableSilentNotifs = */ false)
- );
-
- // THEN: mNotificationStackScrollLayout should be important for A11y
- verify(mNotificationStackScrollLayout)
- .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateImportantForAccessibility_hasChild_notOnKeyGuard_importantForA11y() {
- // GIVEN: Controller is attached, active notifications is not empty,
- // and mNotificationStackScrollLayout.onKeyguard() is false
- initController(/* viewIsAttached= */ true);
- when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(false);
- mController.getNotifStackController().setNotifStats(
- new NotifStats(
- /* numActiveNotifs = */ 1,
- /* hasNonClearableAlertingNotifs = */ false,
- /* hasClearableAlertingNotifs = */ false,
- /* hasNonClearableSilentNotifs = */ false,
- /* hasClearableSilentNotifs = */ false)
- );
-
- // THEN: mNotificationStackScrollLayout should be important for A11y
- verify(mNotificationStackScrollLayout)
- .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateImportantForAccessibility_noChild_notOnKeyGuard_importantForA11y() {
- // GIVEN: Controller is attached, active notifications is empty,
- // and mNotificationStackScrollLayout.onKeyguard() is false
- initController(/* viewIsAttached= */ true);
- when(mNotificationStackScrollLayout.onKeyguard()).thenReturn(false);
- mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
-
- // THEN: mNotificationStackScrollLayout should be important for A11y
- verify(mNotificationStackScrollLayout)
- .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateEmptyShadeView_onKeyguardTransitionToAod_hidesView() {
- initController(/* viewIsAttached= */ true);
- mController.onKeyguardTransitionChanged(
- new TransitionStep(
- /* from= */ KeyguardState.GONE,
- /* to= */ KeyguardState.AOD));
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(eq(false), anyBoolean());
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- public void updateEmptyShadeView_onKeyguardOccludedTransitionToAod_hidesView() {
- initController(/* viewIsAttached= */ true);
- mController.onKeyguardTransitionChanged(
- new TransitionStep(
- /* from= */ KeyguardState.OCCLUDED,
- /* to= */ KeyguardState.AOD));
- verify(mNotificationStackScrollLayout).updateEmptyShadeView(eq(false), anyBoolean());
- }
-
- @Test
@DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
public void sensitiveNotificationProtectionControllerListenerNotRegistered() {
initController(/* viewIsAttached= */ true);
@@ -996,24 +747,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
return argThat(new LogMatcher(category, type));
}
- private void setupShowEmptyShadeViewState(boolean toShow) {
- if (toShow) {
- mController.onKeyguardTransitionChanged(
- new TransitionStep(
- /* from= */ KeyguardState.LOCKSCREEN,
- /* to= */ KeyguardState.GONE));
- mController.setQsFullScreen(false);
- mController.getView().removeAllViews();
- } else {
- mController.onKeyguardTransitionChanged(
- new TransitionStep(
- /* from= */ KeyguardState.GONE,
- /* to= */ KeyguardState.AOD));
- mController.setQsFullScreen(true);
- mController.getView().addContainerView(mock(ExpandableNotificationRow.class));
- }
- }
-
private void initController(boolean viewIsAttached) {
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(viewIsAttached);
ViewTreeObserver viewTreeObserver = mock(ViewTreeObserver.class);
@@ -1033,16 +766,12 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
mStatusBarService,
mNotificationRoundnessManager,
mTunerService,
- mDeviceProvisionedController,
mDynamicPrivacyController,
mConfigurationController,
mSysuiStatusBarStateController,
mKeyguardMediaController,
mKeyguardBypassController,
mPowerInteractor,
- mPrimaryBouncerInteractor,
- mKeyguardTransitionRepo,
- mZenModeController,
mNotificationLockscreenUserManager,
mMetricsLogger,
mColorUpdateLogger,
@@ -1051,14 +780,11 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
new FalsingManagerFake(),
mNotificationSwipeHelperBuilder,
mGroupExpansionManager,
- mSilentHeaderController,
mNotifPipeline,
mNotifCollection,
mLockscreenShadeTransitionController,
mUiEventLogger,
- mRemoteInputManager,
mVisibilityLocationProviderDelegator,
- mSeenNotificationsInteractor,
mViewBinder,
mShadeController,
mWindowRootView,
@@ -1076,7 +802,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
}
static class LogMatcher implements ArgumentMatcher<LogMaker> {
- private int mCategory, mType;
+ private final int mCategory, mType;
LogMatcher(int category, int type) {
mCategory = category;
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index dcac2941b48b..39cff63f363e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -2,12 +2,10 @@ package com.android.systemui.statusbar.notification.stack
import android.annotation.DimenRes
import android.content.pm.PackageManager
-import android.platform.test.annotations.DisableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
-import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
import com.android.systemui.dump.DumpManager
@@ -740,20 +738,6 @@ class StackScrollAlgorithmTest(flags: FlagsParameterization) : SysuiTestCase() {
assertThat((footerView.viewState as FooterViewState).hideContent).isTrue()
}
- @DisableFlags(Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR)
- @Test
- fun resetViewStates_clearAllInProgress_allRowsRemoved_emptyShade_footerHidden() {
- ambientState.isClearAllInProgress = true
- ambientState.isShadeExpanded = true
- ambientState.stackEndHeight = maxPanelHeight // plenty space for the footer in the stack
- hostView.removeAllViews() // remove all rows
- hostView.addView(footerView)
-
- stackScrollAlgorithm.resetViewStates(ambientState, 0)
-
- assertThat((footerView.viewState as FooterViewState).hideContent).isTrue()
- }
-
@Test
fun getGapForLocation_onLockscreen_returnsSmallGap() {
val gap =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
index e592e4b319e3..1b4f9a79557d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
@@ -18,7 +18,6 @@
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -41,7 +40,6 @@ import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRo
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
import com.android.systemui.statusbar.policy.data.repository.fakeUserSetupRepository
@@ -63,7 +61,6 @@ import platform.test.runner.parameterized.Parameters
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
-@EnableFlags(FooterViewRefactor.FLAG_NAME)
class NotificationListViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
private val kosmos =
testKosmos().apply {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index d174484219ff..2e12336f6e93 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -40,7 +40,6 @@ import static org.mockito.Mockito.when;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.testing.TestableLooper;
@@ -610,7 +609,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_registration() {
/* verify that a predictive back callback is registered when the bouncer becomes visible */
mBouncerExpansionCallback.onVisibilityChanged(true);
@@ -625,7 +623,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_invocationHidesBouncer() {
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
@@ -643,7 +640,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_noBackAnimationForFullScreenBouncer() {
when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
.thenReturn(KeyguardSecurityModel.SecurityMode.SimPin);
@@ -663,7 +659,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- @RequiresFlagsEnabled(com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_ANIMATE_BOUNCER)
public void testPredictiveBackCallback_forwardsBackDispatches() {
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
index 0652a835cb7c..650fa7ce46de 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIDialogTest.java
@@ -31,7 +31,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.ravenwood.RavenwoodRule;
@@ -41,7 +40,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.systemui.Dependency;
-import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.animation.back.BackAnimationSpec;
@@ -137,7 +135,6 @@ public class SystemUIDialogTest extends SysuiTestCase {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_ANIMATE_DIALOGS)
public void usePredictiveBackAnimFlag() {
final SystemUIDialog dialog = new SystemUIDialog(mContext);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
index 3d6882c3fdaf..c6bae197ad76 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
@@ -18,9 +18,8 @@ package com.android.systemui.statusbar.policy.domain.interactor
import android.app.AutomaticZenRule
import android.app.Flags
-import android.app.NotificationManager.INTERRUPTION_FILTER_NONE
-import android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY
import android.app.NotificationManager.Policy
+import android.media.AudioManager
import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import android.provider.Settings.Secure.ZEN_DURATION
@@ -34,6 +33,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
import com.android.settingslib.notification.modes.TestModeBuilder
+import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
@@ -402,115 +402,124 @@ class ZenModeInteractorTest : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_MODES_UI)
- fun activeModesBlockingEverything_hasModesWithFilterNone() =
+ fun activeModesBlockingMedia_hasModesWithPolicyBlockingMedia() =
testScope.runTest {
- val blockingEverything by collectLastValue(underTest.activeModesBlockingEverything)
+ val blockingMedia by
+ collectLastValue(
+ underTest.activeModesBlockingStream(AudioStream(AudioManager.STREAM_MUSIC))
+ )
zenModeRepository.addModes(
listOf(
TestModeBuilder()
- .setName("Filter=None, Not active")
- .setInterruptionFilter(INTERRUPTION_FILTER_NONE)
+ .setName("Blocks media, Not active")
+ .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
.setActive(false)
.build(),
TestModeBuilder()
- .setName("Filter=Priority, Active")
- .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setName("Allows media, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowMedia(true).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Filter=None, Active")
- .setInterruptionFilter(INTERRUPTION_FILTER_NONE)
+ .setName("Blocks media, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Filter=None, Active Too")
- .setInterruptionFilter(INTERRUPTION_FILTER_NONE)
+ .setName("Blocks media, Active Too")
+ .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
.setActive(true)
.build(),
)
)
runCurrent()
- assertThat(blockingEverything!!.mainMode!!.name).isEqualTo("Filter=None, Active")
- assertThat(blockingEverything!!.modeNames)
- .containsExactly("Filter=None, Active", "Filter=None, Active Too")
+ assertThat(blockingMedia!!.mainMode!!.name).isEqualTo("Blocks media, Active")
+ assertThat(blockingMedia!!.modeNames)
+ .containsExactly("Blocks media, Active", "Blocks media, Active Too")
.inOrder()
}
@Test
@EnableFlags(Flags.FLAG_MODES_UI)
- fun activeModesBlockingMedia_hasModesWithPolicyBlockingMedia() =
+ fun activeModesBlockingAlarms_hasModesWithPolicyBlockingAlarms() =
testScope.runTest {
- val blockingMedia by collectLastValue(underTest.activeModesBlockingMedia)
+ val blockingAlarms by
+ collectLastValue(
+ underTest.activeModesBlockingStream(AudioStream(AudioManager.STREAM_ALARM))
+ )
zenModeRepository.addModes(
listOf(
TestModeBuilder()
- .setName("Blocks media, Not active")
- .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
+ .setName("Blocks alarms, Not active")
+ .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
.setActive(false)
.build(),
TestModeBuilder()
- .setName("Allows media, Active")
- .setZenPolicy(ZenPolicy.Builder().allowMedia(true).build())
+ .setName("Allows alarms, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowAlarms(true).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Blocks media, Active")
- .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
+ .setName("Blocks alarms, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Blocks media, Active Too")
- .setZenPolicy(ZenPolicy.Builder().allowMedia(false).build())
+ .setName("Blocks alarms, Active Too")
+ .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
.setActive(true)
.build(),
)
)
runCurrent()
- assertThat(blockingMedia!!.mainMode!!.name).isEqualTo("Blocks media, Active")
- assertThat(blockingMedia!!.modeNames)
- .containsExactly("Blocks media, Active", "Blocks media, Active Too")
+ assertThat(blockingAlarms!!.mainMode!!.name).isEqualTo("Blocks alarms, Active")
+ assertThat(blockingAlarms!!.modeNames)
+ .containsExactly("Blocks alarms, Active", "Blocks alarms, Active Too")
.inOrder()
}
@Test
@EnableFlags(Flags.FLAG_MODES_UI)
- fun activeModesBlockingAlarms_hasModesWithPolicyBlockingAlarms() =
+ fun activeModesBlockingAlarms_hasModesWithPolicyBlockingSystem() =
testScope.runTest {
- val blockingAlarms by collectLastValue(underTest.activeModesBlockingAlarms)
+ val blockingSystem by
+ collectLastValue(
+ underTest.activeModesBlockingStream(AudioStream(AudioManager.STREAM_SYSTEM))
+ )
zenModeRepository.addModes(
listOf(
TestModeBuilder()
- .setName("Blocks alarms, Not active")
- .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
+ .setName("Blocks system, Not active")
+ .setZenPolicy(ZenPolicy.Builder().allowSystem(false).build())
.setActive(false)
.build(),
TestModeBuilder()
- .setName("Allows alarms, Active")
- .setZenPolicy(ZenPolicy.Builder().allowAlarms(true).build())
+ .setName("Allows system, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowSystem(true).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Blocks alarms, Active")
- .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
+ .setName("Blocks system, Active")
+ .setZenPolicy(ZenPolicy.Builder().allowSystem(false).build())
.setActive(true)
.build(),
TestModeBuilder()
- .setName("Blocks alarms, Active Too")
- .setZenPolicy(ZenPolicy.Builder().allowAlarms(false).build())
+ .setName("Blocks system, Active Too")
+ .setZenPolicy(ZenPolicy.Builder().allowSystem(false).build())
.setActive(true)
.build(),
)
)
runCurrent()
- assertThat(blockingAlarms!!.mainMode!!.name).isEqualTo("Blocks alarms, Active")
- assertThat(blockingAlarms!!.modeNames)
- .containsExactly("Blocks alarms, Active", "Blocks alarms, Active Too")
+ assertThat(blockingSystem!!.mainMode!!.name).isEqualTo("Blocks system, Active")
+ assertThat(blockingSystem!!.modeNames)
+ .containsExactly("Blocks system, Active", "Blocks system, Active Too")
.inOrder()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/StateTransitionsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/StateTransitionsTest.kt
deleted file mode 100644
index 2ad1124d72d4..000000000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/StateTransitionsTest.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2024 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.touchpad.tutorial.ui
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgressAfterError
-import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted
-import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.toTutorialActionState
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class StateTransitionsTest : SysuiTestCase() {
-
- companion object {
- private const val START_MARKER = "startMarker"
- private const val END_MARKER = "endMarker"
- private const val SUCCESS_ANIMATION = 0
- }
-
- // needed to simulate caching last state as it's used to create new state
- private var lastState: TutorialActionState = NotStarted
-
- private fun GestureState.toTutorialActionState(): TutorialActionState {
- val newState =
- this.toGestureUiState(
- progressStartMarker = START_MARKER,
- progressEndMarker = END_MARKER,
- successAnimation = SUCCESS_ANIMATION,
- )
- .toTutorialActionState(lastState)
- lastState = newState
- return lastState
- }
-
- @Test
- fun gestureStateProducesEquivalentTutorialActionStateInHappyPath() {
- val happyPath =
- listOf(
- GestureState.NotStarted,
- GestureState.InProgress(0f),
- GestureState.InProgress(0.5f),
- GestureState.InProgress(1f),
- GestureState.Finished,
- )
-
- val resultingStates = mutableListOf<TutorialActionState>()
- happyPath.forEach { resultingStates.add(it.toTutorialActionState()) }
-
- assertThat(resultingStates)
- .containsExactly(
- NotStarted,
- InProgress(0f, START_MARKER, END_MARKER),
- InProgress(0.5f, START_MARKER, END_MARKER),
- InProgress(1f, START_MARKER, END_MARKER),
- Finished(SUCCESS_ANIMATION),
- )
- .inOrder()
- }
-
- @Test
- fun gestureStateProducesEquivalentTutorialActionStateInErrorPath() {
- val errorPath =
- listOf(
- GestureState.NotStarted,
- GestureState.InProgress(0f),
- GestureState.Error,
- GestureState.InProgress(0.5f),
- GestureState.InProgress(1f),
- GestureState.Finished,
- )
-
- val resultingStates = mutableListOf<TutorialActionState>()
- errorPath.forEach { resultingStates.add(it.toTutorialActionState()) }
-
- assertThat(resultingStates)
- .containsExactly(
- NotStarted,
- InProgress(0f, START_MARKER, END_MARKER),
- Error,
- InProgressAfterError(InProgress(0.5f, START_MARKER, END_MARKER)),
- InProgressAfterError(InProgress(1f, START_MARKER, END_MARKER)),
- Finished(SUCCESS_ANIMATION),
- )
- .inOrder()
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt
index 4aec88e8497b..d752046f4791 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt
@@ -23,16 +23,16 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.inputdevice.tutorial.inputDeviceTutorialLogger
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.res.R
import com.android.systemui.testKosmos
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
import com.android.systemui.touchpad.ui.gesture.touchpadGestureResources
@@ -71,8 +71,8 @@ class BackGestureScreenViewModelTest : SysuiTestCase() {
expected =
InProgress(
progress = 1f,
- progressStartMarker = "gesture to L",
- progressEndMarker = "end progress L",
+ startMarker = "gesture to L",
+ endMarker = "end progress L",
),
)
}
@@ -85,8 +85,8 @@ class BackGestureScreenViewModelTest : SysuiTestCase() {
expected =
InProgress(
progress = 1f,
- progressStartMarker = "gesture to R",
- progressEndMarker = "end progress R",
+ startMarker = "gesture to R",
+ endMarker = "end progress R",
),
)
}
@@ -114,7 +114,7 @@ class BackGestureScreenViewModelTest : SysuiTestCase() {
kosmos.runTest {
fun performBackGesture() =
ThreeFingerGesture.swipeLeft().forEach { viewModel.handleEvent(it) }
- val state by collectLastValue(viewModel.gestureUiState)
+ val state by collectLastValue(viewModel.tutorialState)
performBackGesture()
assertThat(state).isInstanceOf(Finished::class.java)
@@ -134,15 +134,21 @@ class BackGestureScreenViewModelTest : SysuiTestCase() {
fakeConfigRepository.onAnyConfigurationChange()
}
- private fun Kosmos.assertProgressWhileMovingFingers(deltaX: Float, expected: GestureUiState) {
+ private fun Kosmos.assertProgressWhileMovingFingers(
+ deltaX: Float,
+ expected: TutorialActionState,
+ ) {
assertStateAfterEvents(
events = ThreeFingerGesture.eventsForGestureInProgress { move(deltaX = deltaX) },
expected = expected,
)
}
- private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
- val state by collectLastValue(viewModel.gestureUiState)
+ private fun Kosmos.assertStateAfterEvents(
+ events: List<MotionEvent>,
+ expected: TutorialActionState,
+ ) {
+ val state by collectLastValue(viewModel.tutorialState)
events.forEach { viewModel.handleEvent(it) }
assertThat(state).isEqualTo(expected)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt
index 65a995dcd043..7862fd32ca04 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt
@@ -23,16 +23,16 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.inputdevice.tutorial.inputDeviceTutorialLogger
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.res.R
import com.android.systemui.testKosmos
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
import com.android.systemui.touchpad.tutorial.ui.gesture.Velocity
@@ -86,8 +86,8 @@ class HomeGestureScreenViewModelTest : SysuiTestCase() {
expected =
InProgress(
progress = 1f,
- progressStartMarker = "drag with gesture",
- progressEndMarker = "release playback realtime",
+ startMarker = "drag with gesture",
+ endMarker = "release playback realtime",
),
)
}
@@ -108,7 +108,7 @@ class HomeGestureScreenViewModelTest : SysuiTestCase() {
@Test
fun gestureRecognitionTakesLatestDistanceThresholdIntoAccount() =
kosmos.runTest {
- val state by collectLastValue(viewModel.gestureUiState)
+ val state by collectLastValue(viewModel.tutorialState)
performHomeGesture()
assertThat(state).isInstanceOf(Finished::class.java)
@@ -121,7 +121,7 @@ class HomeGestureScreenViewModelTest : SysuiTestCase() {
@Test
fun gestureRecognitionTakesLatestVelocityThresholdIntoAccount() =
kosmos.runTest {
- val state by collectLastValue(viewModel.gestureUiState)
+ val state by collectLastValue(viewModel.tutorialState)
performHomeGesture()
assertThat(state).isInstanceOf(Finished::class.java)
@@ -147,8 +147,11 @@ class HomeGestureScreenViewModelTest : SysuiTestCase() {
fakeConfigRepository.onAnyConfigurationChange()
}
- private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
- val state by collectLastValue(viewModel.gestureUiState)
+ private fun Kosmos.assertStateAfterEvents(
+ events: List<MotionEvent>,
+ expected: TutorialActionState,
+ ) {
+ val state by collectLastValue(viewModel.tutorialState)
events.forEach { viewModel.handleEvent(it) }
assertThat(state).isEqualTo(expected)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt
index 1bc60b67095e..6180fa98b1cd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt
@@ -23,16 +23,16 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.inputdevice.tutorial.inputDeviceTutorialLogger
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.res.R
import com.android.systemui.testKosmos
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
import com.android.systemui.touchpad.tutorial.ui.gesture.Velocity
@@ -89,8 +89,8 @@ class RecentAppsGestureScreenViewModelTest : SysuiTestCase() {
expected =
InProgress(
progress = 1f,
- progressStartMarker = "drag with gesture",
- progressEndMarker = "onPause",
+ startMarker = "drag with gesture",
+ endMarker = "onPause",
),
)
}
@@ -111,7 +111,7 @@ class RecentAppsGestureScreenViewModelTest : SysuiTestCase() {
@Test
fun gestureRecognitionTakesLatestDistanceThresholdIntoAccount() =
kosmos.runTest {
- val state by collectLastValue(viewModel.gestureUiState)
+ val state by collectLastValue(viewModel.tutorialState)
performRecentAppsGesture()
assertThat(state).isInstanceOf(Finished::class.java)
@@ -124,7 +124,7 @@ class RecentAppsGestureScreenViewModelTest : SysuiTestCase() {
@Test
fun gestureRecognitionTakesLatestVelocityThresholdIntoAccount() =
kosmos.runTest {
- val state by collectLastValue(viewModel.gestureUiState)
+ val state by collectLastValue(viewModel.tutorialState)
performRecentAppsGesture()
assertThat(state).isInstanceOf(Finished::class.java)
@@ -150,8 +150,11 @@ class RecentAppsGestureScreenViewModelTest : SysuiTestCase() {
fakeConfigRepository.onAnyConfigurationChange()
}
- private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
- val state by collectLastValue(viewModel.gestureUiState)
+ private fun Kosmos.assertStateAfterEvents(
+ events: List<MotionEvent>,
+ expected: TutorialActionState,
+ ) {
+ val state by collectLastValue(viewModel.tutorialState)
events.forEach { viewModel.handleEvent(it) }
assertThat(state).isEqualTo(expected)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModelTest.kt
new file mode 100644
index 000000000000..c113dd9e1eff
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModelTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 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.touchpad.tutorial.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgressAfterError
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.asFlow
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TouchpadTutorialScreenViewModelTest : SysuiTestCase() {
+
+ companion object {
+ private const val START_MARKER = "startMarker"
+ private const val END_MARKER = "endMarker"
+ private const val SUCCESS_ANIMATION = 0
+ }
+
+ private val kosmos = testKosmos()
+ private val animationProperties =
+ TutorialAnimationProperties(
+ progressStartMarker = START_MARKER,
+ progressEndMarker = END_MARKER,
+ successAnimation = SUCCESS_ANIMATION,
+ )
+
+ @Before
+ fun before() {
+ kosmos.useUnconfinedTestDispatcher()
+ }
+
+ @Test
+ fun gestureStateProducesEquivalentTutorialActionStateInHappyPath() =
+ kosmos.runTest {
+ val happyPath: Flow<Pair<GestureState, TutorialAnimationProperties>> =
+ listOf(
+ GestureState.NotStarted,
+ GestureState.InProgress(0f),
+ GestureState.InProgress(0.5f),
+ GestureState.InProgress(1f),
+ GestureState.Finished,
+ )
+ .map { it to animationProperties }
+ .asFlow()
+
+ val resultingStates by collectValues(happyPath.mapToTutorialState())
+
+ assertThat(resultingStates)
+ .containsExactly(
+ NotStarted,
+ InProgress(0f, START_MARKER, END_MARKER),
+ InProgress(0.5f, START_MARKER, END_MARKER),
+ InProgress(1f, START_MARKER, END_MARKER),
+ Finished(SUCCESS_ANIMATION),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun gestureStateProducesEquivalentTutorialActionStateInErrorPath() =
+ kosmos.runTest {
+ val errorPath: Flow<Pair<GestureState, TutorialAnimationProperties>> =
+ listOf(
+ GestureState.NotStarted,
+ GestureState.InProgress(0f),
+ GestureState.Error,
+ GestureState.InProgress(0.5f),
+ GestureState.InProgress(1f),
+ GestureState.Finished,
+ )
+ .map { it to animationProperties }
+ .asFlow()
+
+ val resultingStates by collectValues(errorPath.mapToTutorialState())
+
+ assertThat(resultingStates)
+ .containsExactly(
+ NotStarted,
+ InProgress(0f, START_MARKER, END_MARKER),
+ Error,
+ InProgressAfterError(InProgress(0.5f, START_MARKER, END_MARKER)),
+ InProgressAfterError(InProgress(1f, START_MARKER, END_MARKER)),
+ Finished(SUCCESS_ANIMATION),
+ )
+ .inOrder()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModelTest.kt
index d3071f87f744..51cac6976362 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModelTest.kt
@@ -23,66 +23,40 @@ import android.platform.test.annotations.EnableFlags
import android.service.notification.ZenPolicy
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.internal.logging.uiEventLogger
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.haptics.slider.sliderHapticsViewModelFactory
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runCurrent
+import com.android.systemui.kosmos.runTest
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
-import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.testKosmos
-import com.android.systemui.volume.domain.interactor.audioVolumeInteractor
-import com.android.systemui.volume.shared.volumePanelLogger
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class AudioStreamSliderViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
private val zenModeRepository = kosmos.fakeZenModeRepository
- private lateinit var mediaStream: AudioStreamSliderViewModel
- private lateinit var alarmsStream: AudioStreamSliderViewModel
- private lateinit var notificationStream: AudioStreamSliderViewModel
- private lateinit var otherStream: AudioStreamSliderViewModel
-
- @Before
- fun setUp() {
- mediaStream = audioStreamSliderViewModel(AudioManager.STREAM_MUSIC)
- alarmsStream = audioStreamSliderViewModel(AudioManager.STREAM_ALARM)
- notificationStream = audioStreamSliderViewModel(AudioManager.STREAM_NOTIFICATION)
- otherStream = audioStreamSliderViewModel(AudioManager.STREAM_VOICE_CALL)
- }
-
- private fun audioStreamSliderViewModel(stream: Int): AudioStreamSliderViewModel {
- return AudioStreamSliderViewModel(
+ private fun Kosmos.audioStreamSliderViewModel(stream: Int): AudioStreamSliderViewModel {
+ return audioStreamSliderViewModelFactory.create(
AudioStreamSliderViewModel.FactoryAudioStreamWrapper(AudioStream(stream)),
- testScope.backgroundScope,
- context,
- kosmos.audioVolumeInteractor,
- kosmos.zenModeInteractor,
- kosmos.uiEventLogger,
- kosmos.volumePanelLogger,
- kosmos.sliderHapticsViewModelFactory,
+ applicationCoroutineScope,
)
}
@Test
@EnableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS)
fun slider_media_hasDisabledByModesText() =
- testScope.runTest {
- val mediaSlider by collectLastValue(mediaStream.slider)
+ kosmos.runTest {
+ val mediaSlider by
+ collectLastValue(audioStreamSliderViewModel(AudioManager.STREAM_MUSIC).slider)
zenModeRepository.addMode(
TestModeBuilder()
@@ -112,8 +86,9 @@ class AudioStreamSliderViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS)
fun slider_alarms_hasDisabledByModesText() =
- testScope.runTest {
- val alarmsSlider by collectLastValue(alarmsStream.slider)
+ kosmos.runTest {
+ val alarmsSlider by
+ collectLastValue(audioStreamSliderViewModel(AudioManager.STREAM_ALARM).slider)
zenModeRepository.addMode(
TestModeBuilder()
@@ -141,9 +116,10 @@ class AudioStreamSliderViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS)
- fun slider_other_hasDisabledByModesText() =
- testScope.runTest {
- val otherSlider by collectLastValue(otherStream.slider)
+ fun slider_other_hasDisabledText() =
+ kosmos.runTest {
+ val otherSlider by
+ collectLastValue(audioStreamSliderViewModel(AudioManager.STREAM_VOICE_CALL).slider)
zenModeRepository.addMode(
TestModeBuilder()
@@ -154,20 +130,17 @@ class AudioStreamSliderViewModelTest : SysuiTestCase() {
)
runCurrent()
- assertThat(otherSlider!!.disabledMessage)
- .isEqualTo("Unavailable because Everything blocked is on")
-
- zenModeRepository.clearModes()
- runCurrent()
-
assertThat(otherSlider!!.disabledMessage).isEqualTo("Unavailable")
}
@Test
@EnableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS)
fun slider_notification_hasSpecialDisabledText() =
- testScope.runTest {
- val notificationSlider by collectLastValue(notificationStream.slider)
+ kosmos.runTest {
+ val notificationSlider by
+ collectLastValue(
+ audioStreamSliderViewModel(AudioManager.STREAM_NOTIFICATION).slider
+ )
runCurrent()
assertThat(notificationSlider!!.disabledMessage)
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cd37c22c8bc3..a01ff3d5258f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3798,7 +3798,7 @@
<!-- Title at the top of the keyboard shortcut helper UI when in customize mode. The helper
is a component that shows the user which keyboard shortcuts they can use.
[CHAR LIMIT=NONE] -->
- <string name="shortcut_helper_customize_mode_title">Customize keyboard shortcuts</string>
+ <string name="shortcut_helper_customize_mode_title">Customize shortcuts</string>
<!-- Title at the top of the keyboard shortcut helper remove shortcut dialog.
The helper is a component that shows the user which keyboard shortcuts they can use. Also
allows the user to add/remove custom shortcuts.[CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 7d220b505aa0..6e23a0783c9d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -21,11 +21,9 @@ import android.util.Log;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
-import android.window.TaskSnapshot;
import android.window.WindowAnimationState;
import com.android.internal.os.IResultReceiver;
-import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.wm.shell.recents.IRecentsAnimationController;
public class RecentsAnimationControllerCompat {
@@ -40,18 +38,6 @@ public class RecentsAnimationControllerCompat {
mAnimationController = animationController;
}
- public ThumbnailData screenshotTask(int taskId) {
- try {
- final TaskSnapshot snapshot = mAnimationController.screenshotTask(taskId);
- if (snapshot != null) {
- return ThumbnailData.fromSnapshot(snapshot);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to screenshot task", e);
- }
- return new ThumbnailData();
- }
-
public void setInputConsumerEnabled(boolean enabled) {
try {
mAnimationController.setInputConsumerEnabled(enabled);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index d3c02e6f6449..b159a70066ce 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -29,7 +29,6 @@ import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
@@ -93,10 +92,8 @@ public class KeyguardPinViewController
mPasswordEntry.setUserActivityListener(this::onUserInput);
mView.onDevicePostureChanged(mPostureController.getDevicePosture());
mPostureController.addCallback(mPostureCallback);
- if (mFeatureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)) {
- mPasswordEntry.setUsePinShapes(true);
- updateAutoConfirmationState();
- }
+ mPasswordEntry.setUsePinShapes(true);
+ updateAutoConfirmationState();
}
protected void onUserInput() {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 63ac783ad42b..129a6bb72996 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -35,7 +35,6 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor
import com.android.systemui.statusbar.notification.shared.NotificationAvalancheSuppression
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
@@ -57,7 +56,6 @@ class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, ha
NotificationAvalancheSuppression.token dependsOn VisualInterruptionRefactor.token
PriorityPeopleSection.token dependsOn SortBySectionTimeFlag.token
NotificationMinimalism.token dependsOn NotificationThrottleHun.token
- ModesEmptyShadeFix.token dependsOn FooterViewRefactor.token
ModesEmptyShadeFix.token dependsOn modesUi
// SceneContainer dependencies
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index c039e0188064..2c33c0b4403b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -76,21 +76,10 @@ object Flags {
val LOCKSCREEN_CUSTOM_CLOCKS =
resourceBooleanFlag(R.bool.config_enableLockScreenCustomClocks, "lockscreen_custom_clocks")
- /**
- * Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository
- * will occur in stages. This is one stage of many to come.
- */
- // TODO(b/255607168): Tracking Bug
- @JvmField val DOZING_MIGRATION_1 = unreleasedFlag("dozing_migration_1")
-
/** Flag to control the revamp of keyguard biometrics progress animation */
// TODO(b/244313043): Tracking bug
@JvmField val BIOMETRICS_ANIMATION_REVAMP = unreleasedFlag("biometrics_animation_revamp")
- // flag for controlling auto pin confirmation and material u shapes in bouncer
- @JvmField
- val AUTO_PIN_CONFIRMATION = releasedFlag("auto_pin_confirmation", "auto_pin_confirmation")
-
/** Enables code to show contextual loyalty cards in wallet entrypoints */
// TODO(b/294110497): Tracking Bug
@JvmField
@@ -100,10 +89,6 @@ object Flags {
// TODO(b/242908637): Tracking Bug
@JvmField val WALLPAPER_FULLSCREEN_PREVIEW = releasedFlag("wallpaper_fullscreen_preview")
- /** Inflate and bind views upon emitting a blueprint value . */
- // TODO(b/297365780): Tracking Bug
- @JvmField val LAZY_INFLATE_KEYGUARD = releasedFlag("lazy_inflate_keyguard")
-
/** Enables UI updates for AI wallpapers in the wallpaper picker. */
// TODO(b/267722622): Tracking Bug
@JvmField val WALLPAPER_PICKER_UI_FOR_AIWP = releasedFlag("wallpaper_picker_ui_for_aiwp")
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt
index 19a19d551613..c702ba9f401e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt
@@ -25,6 +25,7 @@ import com.android.systemui.CoreStartable
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.shortcut.data.repository.CustomInputGesturesRepository
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperStateRepository
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.CommandQueue
@@ -41,6 +42,7 @@ constructor(
private val stateRepository: ShortcutHelperStateRepository,
private val activityStarter: ActivityStarter,
@Background private val backgroundScope: CoroutineScope,
+ private val customInputGesturesRepository: CustomInputGesturesRepository
) : CoreStartable {
override fun start() {
registerBroadcastReceiver(
@@ -55,6 +57,10 @@ constructor(
action = Intent.ACTION_CLOSE_SYSTEM_DIALOGS,
onReceive = { stateRepository.hide() },
)
+ registerBroadcastReceiver(
+ action = Intent.ACTION_USER_SWITCHED,
+ onReceive = { customInputGesturesRepository.refreshCustomInputGestures() },
+ )
commandQueue.addCallback(
object : CommandQueue.Callbacks {
override fun dismissKeyboardShortcutsMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
index 36cd40052041..e5c638cbdfba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/CustomInputGesturesRepository.kt
@@ -25,6 +25,7 @@ import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_ERROR_RES
import android.hardware.input.InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS
import android.hardware.input.InputSettings
import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestResult
import com.android.systemui.keyboard.shared.model.ShortcutCustomizationRequestResult.ERROR_OTHER
@@ -37,6 +38,7 @@ import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
+@SysUISingleton
class CustomInputGesturesRepository
@Inject
constructor(private val userTracker: UserTracker,
@@ -56,7 +58,7 @@ constructor(private val userTracker: UserTracker,
val customInputGestures =
_customInputGesture.onStart { refreshCustomInputGestures() }
- private fun refreshCustomInputGestures() {
+ fun refreshCustomInputGestures() {
setCustomInputGestures(inputGestures = retrieveCustomInputGestures())
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
index d7be5e622276..e255bdea6100 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/data/repository/InputGestureMaps.kt
@@ -27,14 +27,19 @@ import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_VOICE_ASSISTANT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT
+import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW
import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.AppCategories
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MultiTasking
@@ -66,6 +71,11 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION to MultiTasking,
KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT to MultiTasking,
KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT to MultiTasking,
+ KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW to MultiTasking,
+ KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW to MultiTasking,
+ KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW to MultiTasking,
+ KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW to MultiTasking,
+ KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY to MultiTasking,
// App Category
KEY_GESTURE_TYPE_LAUNCH_APPLICATION to AppCategories,
@@ -102,15 +112,23 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
R.string.shortcutHelper_category_split_screen,
KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT to
R.string.shortcutHelper_category_split_screen,
+ KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW to
+ R.string.shortcutHelper_category_split_screen,
+ KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW to
+ R.string.shortcutHelper_category_split_screen,
+ KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW to
+ R.string.shortcutHelper_category_split_screen,
+ KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW to
+ R.string.shortcutHelper_category_split_screen,
+ KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY to R.string.shortcutHelper_category_split_screen,
// App Category
- KEY_GESTURE_TYPE_LAUNCH_APPLICATION to
- R.string.keyboard_shortcut_group_applications,
+ KEY_GESTURE_TYPE_LAUNCH_APPLICATION to R.string.keyboard_shortcut_group_applications,
)
/**
- * App Category shortcut labels are mapped dynamically based on intent
- * see [InputGestureDataAdapter.fetchShortcutLabelByAppLaunchData]
+ * App Category shortcut labels are mapped dynamically based on intent see
+ * [InputGestureDataAdapter.fetchShortcutLabelByAppLaunchData]
*/
val gestureToInternalKeyboardShortcutInfoLabelResIdMap =
mapOf(
@@ -136,6 +154,16 @@ class InputGestureMaps @Inject constructor(private val context: Context) {
KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT to R.string.system_multitasking_lhs,
KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT to R.string.system_multitasking_rhs,
KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION to R.string.system_multitasking_full_screen,
+ KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW to
+ R.string.system_desktop_mode_snap_left_window,
+ KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW to
+ R.string.system_desktop_mode_snap_right_window,
+ KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW to
+ R.string.system_desktop_mode_minimize_window,
+ KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW to
+ R.string.system_desktop_mode_toggle_maximize_window,
+ KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY to
+ R.string.system_multitasking_move_to_next_display,
)
val shortcutLabelToKeyGestureTypeMap: Map<String, Int>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index d40fe468b0a5..591383999182 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -538,27 +538,30 @@ public class KeyguardService extends Service {
@Override // Binder interface
public void onFinishedGoingToSleep(
- @PowerManager.GoToSleepReason int pmSleepReason, boolean cameraGestureTriggered) {
+ @PowerManager.GoToSleepReason int pmSleepReason, boolean
+ powerButtonLaunchGestureTriggered) {
trace("onFinishedGoingToSleep pmSleepReason=" + pmSleepReason
- + " cameraGestureTriggered=" + cameraGestureTriggered);
+ + " powerButtonLaunchTriggered=" + powerButtonLaunchGestureTriggered);
checkPermission();
mKeyguardViewMediator.onFinishedGoingToSleep(
WindowManagerPolicyConstants.translateSleepReasonToOffReason(pmSleepReason),
- cameraGestureTriggered);
- mPowerInteractor.onFinishedGoingToSleep(cameraGestureTriggered);
+ powerButtonLaunchGestureTriggered);
+ mPowerInteractor.onFinishedGoingToSleep(powerButtonLaunchGestureTriggered);
mKeyguardLifecyclesDispatcher.dispatch(
KeyguardLifecyclesDispatcher.FINISHED_GOING_TO_SLEEP);
}
@Override // Binder interface
public void onStartedWakingUp(
- @PowerManager.WakeReason int pmWakeReason, boolean cameraGestureTriggered) {
+ @PowerManager.WakeReason int pmWakeReason,
+ boolean powerButtonLaunchGestureTriggered) {
trace("onStartedWakingUp pmWakeReason=" + pmWakeReason
- + " cameraGestureTriggered=" + cameraGestureTriggered);
+ + " powerButtonLaunchGestureTriggered=" + powerButtonLaunchGestureTriggered);
Trace.beginSection("KeyguardService.mBinder#onStartedWakingUp");
checkPermission();
- mKeyguardViewMediator.onStartedWakingUp(pmWakeReason, cameraGestureTriggered);
- mPowerInteractor.onStartedWakingUp(pmWakeReason, cameraGestureTriggered);
+ mKeyguardViewMediator.onStartedWakingUp(pmWakeReason,
+ powerButtonLaunchGestureTriggered);
+ mPowerInteractor.onStartedWakingUp(pmWakeReason, powerButtonLaunchGestureTriggered);
mKeyguardLifecyclesDispatcher.dispatch(
KeyguardLifecyclesDispatcher.STARTED_WAKING_UP, pmWakeReason);
Trace.endSection();
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
index e5ff2529e335..f295c0ccb3de 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt
@@ -19,6 +19,7 @@ import android.content.Context
import android.hardware.display.DisplayManager
import android.os.Bundle
import android.os.UserHandle
+import android.view.View
import androidx.annotation.StyleRes
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
@@ -119,6 +120,12 @@ class ScreenRecordPermissionDialogDelegate(
super<BaseMediaProjectionPermissionDialogDelegate>.onCreate(dialog, savedInstanceState)
setDialogTitle(R.string.screenrecord_permission_dialog_title)
dialog.setTitle(R.string.screenrecord_title)
+ setStartButtonOnClickListener { v: View? ->
+ val screenRecordViewBinder: ScreenRecordPermissionViewBinder? =
+ viewBinder as ScreenRecordPermissionViewBinder?
+ screenRecordViewBinder?.startButtonOnClicked()
+ dialog.dismiss()
+ }
setCancelButtonOnClickListener { dialog.dismiss() }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
index 9f7e1ade964a..691bdd4a1b27 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
@@ -79,37 +79,38 @@ class ScreenRecordPermissionViewBinder(
override fun bind() {
super.bind()
initRecordOptionsView()
- setStartButtonOnClickListener { _: View? ->
- onStartRecordingClicked?.run()
- if (selectedScreenShareOption.mode == ENTIRE_SCREEN) {
- requestScreenCapture(
- captureTarget = null,
- displayId = selectedScreenShareOption.displayId,
- )
- }
- if (selectedScreenShareOption.mode == SINGLE_APP) {
- val intent = Intent(dialog.context, MediaProjectionAppSelectorActivity::class.java)
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ setStartButtonOnClickListener { startButtonOnClicked() }
+ }
- // We can't start activity for result here so we use result receiver to get
- // the selected target to capture
- intent.putExtra(
- MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER,
- CaptureTargetResultReceiver(),
- )
+ fun startButtonOnClicked() {
+ onStartRecordingClicked?.run()
+ if (selectedScreenShareOption.mode == ENTIRE_SCREEN) {
+ requestScreenCapture(
+ captureTarget = null,
+ displayId = selectedScreenShareOption.displayId,
+ )
+ }
+ if (selectedScreenShareOption.mode == SINGLE_APP) {
+ val intent = Intent(dialog.context, MediaProjectionAppSelectorActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- intent.putExtra(
- MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
- hostUserHandle,
- )
- intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid)
- intent.putExtra(
- MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE,
- MediaProjectionAppSelectorActivity.ScreenShareType.ScreenRecord.name,
- )
- activityStarter.startActivity(intent, /* dismissShade= */ true)
- }
- dialog.dismiss()
+ // We can't start activity for result here so we use result receiver to get
+ // the selected target to capture
+ intent.putExtra(
+ MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER,
+ CaptureTargetResultReceiver(),
+ )
+
+ intent.putExtra(
+ MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
+ hostUserHandle,
+ )
+ intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid)
+ intent.putExtra(
+ MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE,
+ MediaProjectionAppSelectorActivity.ScreenShareType.ScreenRecord.name,
+ )
+ activityStarter.startActivity(intent, /* dismissShade= */ true)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index e168025b2bf8..c9eb4962ab00 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -162,7 +162,6 @@ import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.headsup.OnHeadsUpChangedListener;
@@ -1214,14 +1213,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
private boolean hasVisibleNotifications() {
- if (FooterViewRefactor.isEnabled()) {
- return mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()
- || mMediaDataManager.hasActiveMediaOrRecommendation();
- } else {
- return mNotificationStackScrollLayoutController
- .getVisibleNotificationCount() != 0
- || mMediaDataManager.hasActiveMediaOrRecommendation();
- }
+ return mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()
+ || mMediaDataManager.hasActiveMediaOrRecommendation();
}
@Override
@@ -2218,9 +2211,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
@Override
public void setBouncerShowing(boolean bouncerShowing) {
mBouncerShowing = bouncerShowing;
- if (!FooterViewRefactor.isEnabled()) {
- mNotificationStackScrollLayoutController.updateShowEmptyShadeView();
- }
updateVisibility();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index c88e7b827881..14087a0efcfc 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -86,7 +86,6 @@ import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.QsFrameTranslateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
@@ -96,8 +95,8 @@ import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
@@ -1022,12 +1021,6 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum
}
void updateQsState() {
- if (!FooterViewRefactor.isEnabled()) {
- // Update full screen state; note that this will be true if the QS panel is only
- // partially expanded, and that is fixed with the footer view refactor.
- setQsFullScreen(/* qsFullScreen = */ getExpanded() && !mSplitShadeEnabled);
- }
-
if (mQsStateUpdateListener != null) {
mQsStateUpdateListener.onQsStateUpdated(getExpanded(), mStackScrollerOverscrolling);
}
@@ -1094,10 +1087,8 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum
// Update the light bar
mLightBarController.setQsExpanded(mFullyExpanded);
- if (FooterViewRefactor.isEnabled()) {
- // Update full screen state
- setQsFullScreen(/* qsFullScreen = */ mFullyExpanded && !mSplitShadeEnabled);
- }
+ // Update full screen state
+ setQsFullScreen(/* qsFullScreen = */ mFullyExpanded && !mSplitShadeEnabled);
}
float getLockscreenShadeDragProgress() {
@@ -2268,10 +2259,8 @@ public class QuickSettingsControllerImpl implements QuickSettingsController, Dum
setExpansionHeight(qsHeight);
}
- boolean hasNotifications = FooterViewRefactor.isEnabled()
- ? mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()
- : mNotificationStackScrollLayoutController.getVisibleNotificationCount()
- != 0;
+ boolean hasNotifications =
+ mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue();
if (!hasNotifications && !mMediaDataManager.hasActiveMediaOrRecommendation()) {
// No notifications are visible, let's animate to the height of qs instead
if (isQsFragmentCreated()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt
index a747abbc6a6e..1c14d3349027 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChronometerText.kt
@@ -28,17 +28,11 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.Measurable
-import androidx.compose.ui.layout.MeasureResult
-import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.node.LayoutModifierNode
-import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.constrain
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.statusbar.chips.ui.compose.modifiers.neverDecreaseWidth
import kotlinx.coroutines.delay
/** Platform-optimized interface for getting current time */
@@ -97,35 +91,3 @@ fun ChronometerText(
modifier = modifier.neverDecreaseWidth(),
)
}
-
-/** A modifier that ensures the width of the content only increases and never decreases. */
-private fun Modifier.neverDecreaseWidth(): Modifier {
- return this.then(neverDecreaseWidthElement)
-}
-
-private data object neverDecreaseWidthElement : ModifierNodeElement<NeverDecreaseWidthNode>() {
- override fun create(): NeverDecreaseWidthNode {
- return NeverDecreaseWidthNode()
- }
-
- override fun update(node: NeverDecreaseWidthNode) {
- error("This should never be called")
- }
-}
-
-private class NeverDecreaseWidthNode : Modifier.Node(), LayoutModifierNode {
- private var minWidth = 0
-
- override fun MeasureScope.measure(
- measurable: Measurable,
- constraints: Constraints,
- ): MeasureResult {
- val placeable = measurable.measure(Constraints(minWidth = minWidth).constrain(constraints))
- val width = placeable.width
- val height = placeable.height
-
- minWidth = maxOf(minWidth, width)
-
- return layout(width, height) { placeable.place(0, 0) }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt
new file mode 100644
index 000000000000..505a5fcb18b4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/modifiers/NeverDecreaseWidth.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2025 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.chips.ui.compose.modifiers
+
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasureResult
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.constrain
+
+/** A modifier that ensures the width of the content only increases and never decreases. */
+fun Modifier.neverDecreaseWidth(): Modifier {
+ return this.then(neverDecreaseWidthElement)
+}
+
+private data object neverDecreaseWidthElement : ModifierNodeElement<NeverDecreaseWidthNode>() {
+ override fun create(): NeverDecreaseWidthNode {
+ return NeverDecreaseWidthNode()
+ }
+
+ override fun update(node: NeverDecreaseWidthNode) {
+ error("This should never be called")
+ }
+}
+
+private class NeverDecreaseWidthNode : Modifier.Node(), LayoutModifierNode {
+ private var minWidth = 0
+
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints,
+ ): MeasureResult {
+ val placeable = measurable.measure(Constraints(minWidth = minWidth).constrain(constraints))
+ val width = placeable.width
+ val height = placeable.height
+
+ minWidth = maxOf(minWidth, width)
+
+ return layout(width, height) { placeable.place(0, 0) }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 254b792f8152..d327fc23fd06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.dagger;
-import static com.android.systemui.Flags.predictiveBackAnimateDialogs;
-
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
@@ -28,7 +26,6 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.CoreStartable;
import com.android.systemui.animation.ActivityTransitionAnimator;
-import com.android.systemui.animation.AnimationFeatureFlags;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
@@ -226,8 +223,7 @@ public interface CentralSurfacesDependenciesModule {
IDreamManager dreamManager,
KeyguardStateController keyguardStateController,
Lazy<AlternateBouncerInteractor> alternateBouncerInteractor,
- InteractionJankMonitor interactionJankMonitor,
- AnimationFeatureFlags animationFeatureFlags) {
+ InteractionJankMonitor interactionJankMonitor) {
DialogTransitionAnimator.Callback callback = new DialogTransitionAnimator.Callback() {
@Override
public boolean isDreaming() {
@@ -249,19 +245,6 @@ public interface CentralSurfacesDependenciesModule {
return alternateBouncerInteractor.get().canShowAlternateBouncerForFingerprint();
}
};
- return new DialogTransitionAnimator(
- mainExecutor, callback, interactionJankMonitor, animationFeatureFlags);
- }
-
- /** */
- @Provides
- @SysUISingleton
- static AnimationFeatureFlags provideAnimationFeatureFlags() {
- return new AnimationFeatureFlags() {
- @Override
- public boolean isPredictiveBackQsDialogAnim() {
- return predictiveBackAnimateDialogs();
- }
- };
+ return new DialogTransitionAnimator(mainExecutor, callback, interactionJankMonitor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 32de65be5b5b..d4d3cdf42fb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.notification.collection.render.NotifStackC
import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
import javax.inject.Inject
@@ -43,7 +42,8 @@ internal constructor(
private val groupExpansionManagerImpl: GroupExpansionManagerImpl,
private val renderListInteractor: RenderNotificationListInteractor,
private val activeNotificationsInteractor: ActiveNotificationsInteractor,
- private val sensitiveNotificationProtectionController: SensitiveNotificationProtectionController,
+ private val sensitiveNotificationProtectionController:
+ SensitiveNotificationProtectionController,
) : Coordinator {
override fun attach(pipeline: NotifPipeline) {
@@ -51,14 +51,11 @@ internal constructor(
groupExpansionManagerImpl.attach(pipeline)
}
+ // TODO: b/293167744 - Remove controller param.
private fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) =
traceSection("StackCoordinator.onAfterRenderList") {
val notifStats = calculateNotifStats(entries)
- if (FooterViewRefactor.isEnabled) {
- activeNotificationsInteractor.setNotifStats(notifStats)
- } else {
- controller.setNotifStats(notifStats)
- }
+ activeNotificationsInteractor.setNotifStats(notifStats)
renderListInteractor.setRenderedList(entries)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
index fbec6406e9d4..7e2361f24da9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
@@ -26,7 +26,6 @@ import com.android.systemui.shared.notifications.domain.interactor.NotificationS
import com.android.systemui.statusbar.notification.NotificationActivityStarter.SettingsIntent
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterMessageViewModel
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.kotlin.FlowDumperImpl
@@ -35,7 +34,6 @@ import dagger.assisted.AssistedInject
import java.util.Locale
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOf
@@ -57,9 +55,7 @@ constructor(
dumpManager: DumpManager,
) : FlowDumperImpl(dumpManager) {
val areNotificationsHiddenInShade: Flow<Boolean> by lazy {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(false)
- } else if (ModesEmptyShadeFix.isEnabled) {
+ if (ModesEmptyShadeFix.isEnabled) {
zenModeInteractor.areNotificationsHiddenInShade
.dumpWhileCollecting("areNotificationsHiddenInShade")
.flowOn(bgDispatcher)
@@ -70,15 +66,10 @@ constructor(
}
}
- val hasFilteredOutSeenNotifications: StateFlow<Boolean> by lazy {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- MutableStateFlow(false)
- } else {
- seenNotificationsInteractor.hasFilteredOutSeenNotifications.dumpValue(
- "hasFilteredOutSeenNotifications"
- )
- }
- }
+ val hasFilteredOutSeenNotifications: StateFlow<Boolean> =
+ seenNotificationsInteractor.hasFilteredOutSeenNotifications.dumpValue(
+ "hasFilteredOutSeenNotifications"
+ )
val text: Flow<String> by lazy {
if (ModesEmptyShadeFix.isUnexpectedlyInLegacyMode()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt
deleted file mode 100644
index 7e6044eb6869..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/shared/FooterViewRefactor.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 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.footer.shared
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the FooterView refactor flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object FooterViewRefactor {
- /** The aconfig flag name */
- const val FLAG_NAME = Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR
-
- /** A token used for dependency declaration */
- val token: FlagToken
- get() = FlagToken(FLAG_NAME, isEnabled)
-
- /** Is the refactor enabled */
- @JvmStatic
- inline val isEnabled
- get() = Flags.notificationsFooterViewRefactor()
-
- /**
- * Called to ensure code is only run when the flag is enabled. This protects users from the
- * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
- * build to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun isUnexpectedlyInLegacyMode() =
- RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
- /**
- * Called to ensure code is only run when the flag is disabled. This will throw an exception if
- * the flag is enabled to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
index d25889820629..a670f69df601 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterView.java
@@ -41,7 +41,6 @@ import androidx.annotation.NonNull;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter;
import com.android.systemui.statusbar.notification.row.FooterViewButton;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
@@ -63,16 +62,9 @@ public class FooterView extends StackScrollerDecorView {
private FooterViewButton mSettingsButton;
private FooterViewButton mHistoryButton;
private boolean mShouldBeHidden;
- private boolean mShowHistory;
- // String cache, for performance reasons.
- // Reading them from a Resources object can be quite slow sometimes.
- private String mManageNotificationText;
- private String mManageNotificationHistoryText;
// Footer label
private TextView mSeenNotifsFooterTextView;
- private String mSeenNotifsFilteredText;
- private Drawable mSeenNotifsFilteredIcon;
private @StringRes int mClearAllButtonTextId;
private @StringRes int mClearAllButtonDescriptionId;
@@ -159,8 +151,8 @@ public class FooterView extends StackScrollerDecorView {
IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
super.dump(pw, args);
DumpUtilsKt.withIncreasedIndent(pw, () -> {
+ // TODO: b/375010573 - update dumps for redesign
pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
- pw.println("manageButton showHistory: " + mShowHistory);
pw.println("manageButton visibility: "
+ DumpUtilsKt.visibilityString(mClearAllButton.getVisibility()));
pw.println("dismissButton visibility: "
@@ -170,7 +162,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the text label for the "Clear all" button. */
public void setClearAllButtonText(@StringRes int textId) {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
if (mClearAllButtonTextId == textId) {
return; // nothing changed
}
@@ -187,9 +178,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the accessibility content description for the "Clear all" button. */
public void setClearAllButtonDescription(@StringRes int contentDescriptionId) {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- return;
- }
if (mClearAllButtonDescriptionId == contentDescriptionId) {
return; // nothing changed
}
@@ -207,7 +195,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the text label for the "Manage"/"History" button. */
public void setManageOrHistoryButtonText(@StringRes int textId) {
NotifRedesignFooter.assertInLegacyMode();
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
if (mManageOrHistoryButtonTextId == textId) {
return; // nothing changed
}
@@ -226,9 +213,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the accessibility content description for the "Clear all" button. */
public void setManageOrHistoryButtonDescription(@StringRes int contentDescriptionId) {
NotifRedesignFooter.assertInLegacyMode();
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- return;
- }
if (mManageOrHistoryButtonDescriptionId == contentDescriptionId) {
return; // nothing changed
}
@@ -247,7 +231,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the string for a message to be shown instead of the buttons. */
public void setMessageString(@StringRes int messageId) {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
if (mMessageStringId == messageId) {
return; // nothing changed
}
@@ -265,7 +248,6 @@ public class FooterView extends StackScrollerDecorView {
/** Set the icon to be shown before the message (see {@link #setMessageString(int)}). */
public void setMessageIcon(@DrawableRes int iconId) {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) return;
if (mMessageIconId == iconId) {
return; // nothing changed
}
@@ -303,32 +285,17 @@ public class FooterView extends StackScrollerDecorView {
mManageOrHistoryButton = findViewById(R.id.manage_text);
}
mSeenNotifsFooterTextView = findViewById(R.id.unlock_prompt_footer);
- if (!FooterViewRefactor.isEnabled()) {
- updateResources();
- }
updateContent();
updateColors();
}
/** Show a message instead of the footer buttons. */
public void setFooterLabelVisible(boolean isVisible) {
- // In the refactored code, hiding the buttons is handled in the FooterViewModel
- if (FooterViewRefactor.isEnabled()) {
- if (isVisible) {
- mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
- } else {
- mSeenNotifsFooterTextView.setVisibility(View.GONE);
- }
+ // Note: hiding the buttons is handled in the FooterViewModel
+ if (isVisible) {
+ mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
} else {
- if (isVisible) {
- mManageOrHistoryButton.setVisibility(View.GONE);
- mClearAllButton.setVisibility(View.GONE);
- mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
- } else {
- mManageOrHistoryButton.setVisibility(View.VISIBLE);
- mClearAllButton.setVisibility(View.VISIBLE);
- mSeenNotifsFooterTextView.setVisibility(View.GONE);
- }
+ mSeenNotifsFooterTextView.setVisibility(View.GONE);
}
}
@@ -359,10 +326,8 @@ public class FooterView extends StackScrollerDecorView {
/** Set onClickListener for the clear all (end) button. */
public void setClearAllButtonClickListener(OnClickListener listener) {
- if (FooterViewRefactor.isEnabled()) {
- if (mClearAllButtonClickListener == listener) return;
- mClearAllButtonClickListener = listener;
- }
+ if (mClearAllButtonClickListener == listener) return;
+ mClearAllButtonClickListener = listener;
mClearAllButton.setOnClickListener(listener);
}
@@ -379,62 +344,17 @@ public class FooterView extends StackScrollerDecorView {
|| touchY > mContent.getY() + mContent.getHeight();
}
- /** Show "History" instead of "Manage" on the start button. */
- public void showHistory(boolean showHistory) {
- FooterViewRefactor.assertInLegacyMode();
- if (mShowHistory == showHistory) {
- return;
- }
- mShowHistory = showHistory;
- updateContent();
- }
-
private void updateContent() {
- if (FooterViewRefactor.isEnabled()) {
- updateClearAllButtonText();
- updateClearAllButtonDescription();
-
- if (!NotifRedesignFooter.isEnabled()) {
- updateManageOrHistoryButtonText();
- updateManageOrHistoryButtonDescription();
- }
-
- updateMessageString();
- updateMessageIcon();
- } else {
- // NOTE: Prior to the refactor, `updateResources` set the class properties to the right
- // string values. It was always being called together with `updateContent`, which
- // deals with actually associating those string values with the correct views
- // (buttons or text).
- // In the new code, the resource IDs are being set in the view binder (through
- // setMessageString and similar setters). The setters themselves now deal with
- // updating both the resource IDs and the views where appropriate (as in, calling
- // `updateMessageString` when the resource ID changes). This eliminates the need for
- // `updateResources`, which will eventually be removed. There are, however, still
- // situations in which we want to update the views even if the resource IDs didn't
- // change, such as configuration changes.
- if (mShowHistory) {
- mManageOrHistoryButton.setText(mManageNotificationHistoryText);
- mManageOrHistoryButton.setContentDescription(mManageNotificationHistoryText);
- } else {
- mManageOrHistoryButton.setText(mManageNotificationText);
- mManageOrHistoryButton.setContentDescription(mManageNotificationText);
- }
-
- mClearAllButton.setText(R.string.clear_all_notifications_text);
- mClearAllButton.setContentDescription(
- mContext.getString(R.string.accessibility_clear_all));
+ updateClearAllButtonText();
+ updateClearAllButtonDescription();
- mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText);
- mSeenNotifsFooterTextView
- .setCompoundDrawablesRelative(mSeenNotifsFilteredIcon, null, null, null);
+ if (!NotifRedesignFooter.isEnabled()) {
+ updateManageOrHistoryButtonText();
+ updateManageOrHistoryButtonDescription();
}
- }
- /** Whether the start button shows "History" (true) or "Manage" (false). */
- public boolean isHistoryShown() {
- FooterViewRefactor.assertInLegacyMode();
- return mShowHistory;
+ updateMessageString();
+ updateMessageIcon();
}
@Override
@@ -445,9 +365,6 @@ public class FooterView extends StackScrollerDecorView {
}
super.onConfigurationChanged(newConfig);
updateColors();
- if (!FooterViewRefactor.isEnabled()) {
- updateResources();
- }
updateContent();
}
@@ -502,18 +419,6 @@ public class FooterView extends StackScrollerDecorView {
}
}
- private void updateResources() {
- FooterViewRefactor.assertInLegacyMode();
- mManageNotificationText = getContext().getString(R.string.manage_notifications_text);
- mManageNotificationHistoryText = getContext()
- .getString(R.string.manage_notifications_history_text);
- int unlockIconSize = getResources()
- .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
- mSeenNotifsFilteredText = getContext().getString(R.string.unlock_to_see_notif_text);
- mSeenNotifsFilteredIcon = getContext().getDrawable(R.drawable.ic_friction_lock_closed);
- mSeenNotifsFilteredIcon.setBounds(0, 0, unlockIconSize, unlockIconSize);
- }
-
@Override
@NonNull
public ExpandableViewState createExpandableViewState() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
index e724935e3ef4..5696e9f0c5a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModel.kt
@@ -27,7 +27,6 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter.S
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.ui.AnimatableEvent
@@ -144,6 +143,7 @@ class FooterViewModel(
)
}
+// TODO: b/293167744 - remove this, use new viewmodel style
@Module
object FooterViewModelModule {
@Provides
@@ -153,18 +153,13 @@ object FooterViewModelModule {
notificationSettingsInteractor: Provider<NotificationSettingsInteractor>,
seenNotificationsInteractor: Provider<SeenNotificationsInteractor>,
shadeInteractor: Provider<ShadeInteractor>,
- ): Optional<FooterViewModel> {
- return if (FooterViewRefactor.isEnabled) {
- Optional.of(
- FooterViewModel(
- activeNotificationsInteractor.get(),
- notificationSettingsInteractor.get(),
- seenNotificationsInteractor.get(),
- shadeInteractor.get(),
- )
+ ): Optional<FooterViewModel> =
+ Optional.of(
+ FooterViewModel(
+ activeNotificationsInteractor.get(),
+ notificationSettingsInteractor.get(),
+ seenNotificationsInteractor.get(),
+ shadeInteractor.get(),
)
- } else {
- Optional.empty()
- }
- }
+ )
}
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 071d23283c43..76591ac4e453 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
@@ -108,7 +108,6 @@ import com.android.systemui.statusbar.notification.collection.render.GroupExpans
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix;
import com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeView;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.headsup.HeadsUpUtil;
@@ -703,9 +702,6 @@ public class NotificationStackScrollLayout
if (!ModesEmptyShadeFix.isEnabled()) {
inflateEmptyShadeView();
}
- if (!FooterViewRefactor.isEnabled()) {
- inflateFooterView();
- }
}
/**
@@ -741,22 +737,12 @@ public class NotificationStackScrollLayout
}
void reinflateViews() {
- if (!FooterViewRefactor.isEnabled()) {
- inflateFooterView();
- updateFooter();
- }
if (!ModesEmptyShadeFix.isEnabled()) {
inflateEmptyShadeView();
}
mSectionsManager.reinflateViews();
}
- public void setIsRemoteInputActive(boolean isActive) {
- FooterViewRefactor.assertInLegacyMode();
- mIsRemoteInputActive = isActive;
- updateFooter();
- }
-
void sendRemoteInputRowBottomBound(Float bottom) {
if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
if (bottom != null) {
@@ -766,43 +752,6 @@ public class NotificationStackScrollLayout
mScrollViewFields.sendRemoteInputRowBottomBound(bottom);
}
- /** Setter for filtered notifs, to be removed with the FooterViewRefactor flag. */
- public void setHasFilteredOutSeenNotifications(boolean hasFilteredOutSeenNotifications) {
- FooterViewRefactor.assertInLegacyMode();
- mHasFilteredOutSeenNotifications = hasFilteredOutSeenNotifications;
- }
-
- @VisibleForTesting
- public void updateFooter() {
- FooterViewRefactor.assertInLegacyMode();
- if (mFooterView == null || mController == null) {
- return;
- }
- final boolean showHistory = mController.isHistoryEnabled();
- final boolean showDismissView = shouldShowDismissView();
-
- updateFooterView(shouldShowFooterView(showDismissView)/* visible */,
- showDismissView /* showDismissView */,
- showHistory/* showHistory */);
- }
-
- private boolean shouldShowDismissView() {
- FooterViewRefactor.assertInLegacyMode();
- return mController.hasActiveClearableNotifications(ROWS_ALL);
- }
-
- private boolean shouldShowFooterView(boolean showDismissView) {
- FooterViewRefactor.assertInLegacyMode();
- return (showDismissView || mController.getVisibleNotificationCount() > 0)
- && mIsCurrentUserSetup // see: b/193149550
- && !onKeyguard()
- && mUpcomingStatusBarState != StatusBarState.KEYGUARD
- // quick settings don't affect notifications when not in full screen
- && (getQsExpansionFraction() != 1 || !mQsFullScreen)
- && !mScreenOffAnimationController.shouldHideNotificationsFooter()
- && !mIsRemoteInputActive;
- }
-
void updateBgColor() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
@@ -1861,9 +1810,6 @@ public class NotificationStackScrollLayout
*/
private float getAppearEndPosition() {
SceneContainerFlag.assertInLegacyMode();
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- return getAppearEndPositionLegacy();
- }
int appearPosition = mAmbientState.getStackTopMargin();
if (mEmptyShadeView.getVisibility() == GONE) {
@@ -1883,32 +1829,6 @@ public class NotificationStackScrollLayout
return appearPosition + (onKeyguard() ? getTopPadding() : getIntrinsicPadding());
}
- /**
- * The version of {@code getAppearEndPosition} that uses the notif count. The view shouldn't
- * need to know about that, so we want to phase this out with the footer view refactor.
- */
- private float getAppearEndPositionLegacy() {
- FooterViewRefactor.assertInLegacyMode();
-
- int appearPosition = mAmbientState.getStackTopMargin();
- int visibleNotifCount = mController.getVisibleNotificationCount();
- if (mEmptyShadeView.getVisibility() == GONE && visibleNotifCount > 0) {
- if (isHeadsUpTransition()
- || (mInHeadsUpPinnedMode && !mAmbientState.isDozing())) {
- if (mShelf.getVisibility() != GONE && visibleNotifCount > 1) {
- appearPosition += mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
- }
- appearPosition += getTopHeadsUpPinnedHeight()
- + getPositionInLinearLayout(mAmbientState.getTrackedHeadsUpRow());
- } else if (mShelf.getVisibility() != GONE) {
- appearPosition += mShelf.getIntrinsicHeight();
- }
- } else {
- appearPosition = mEmptyShadeView.getHeight();
- }
- return appearPosition + (onKeyguard() ? getTopPadding() : getIntrinsicPadding());
- }
-
private boolean isHeadsUpTransition() {
return mAmbientState.getTrackedHeadsUpRow() != null;
}
@@ -1928,8 +1848,7 @@ public class NotificationStackScrollLayout
// This can't use expansion fraction as that goes only from 0 to 1. Also when
// appear fraction for HUN is 0, expansion fraction will be already around 0.2-0.3
// and that makes translation jump immediately.
- float appearEndPosition = FooterViewRefactor.isEnabled() ? getAppearEndPosition()
- : getAppearEndPositionLegacy();
+ float appearEndPosition = getAppearEndPosition();
float appearStartPosition = getAppearStartPosition();
float hunAppearFraction = (height - appearStartPosition)
/ (appearEndPosition - appearStartPosition);
@@ -4848,15 +4767,6 @@ public class NotificationStackScrollLayout
}
}
- /**
- * Returns whether or not a History button is shown in the footer. If there is no footer, then
- * this will return false.
- **/
- public boolean isHistoryShown() {
- FooterViewRefactor.assertInLegacyMode();
- return mFooterView != null && mFooterView.isHistoryShown();
- }
-
/** Bind the {@link FooterView} to the NSSL. */
public void setFooterView(@NonNull FooterView footerView) {
int index = -1;
@@ -4866,18 +4776,6 @@ public class NotificationStackScrollLayout
}
mFooterView = footerView;
addView(mFooterView, index);
- if (!FooterViewRefactor.isEnabled()) {
- if (mManageButtonClickListener != null) {
- mFooterView.setManageButtonClickListener(mManageButtonClickListener);
- }
- mFooterView.setClearAllButtonClickListener(v -> {
- if (mFooterClearAllListener != null) {
- mFooterClearAllListener.onClearAll();
- }
- clearNotifications(ROWS_ALL, true /* closeShade */);
- footerView.setClearAllButtonVisible(false /* visible */, true /* animate */);
- });
- }
}
public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
@@ -4890,13 +4788,6 @@ public class NotificationStackScrollLayout
addView(mEmptyShadeView, index);
}
- /** Legacy version, should be removed with the footer refactor flag. */
- public void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
- FooterViewRefactor.assertInLegacyMode();
- updateEmptyShadeView(visible, areNotificationsHiddenInShade,
- mHasFilteredOutSeenNotifications);
- }
-
/** Trigger an update for the empty shade resources and visibility. */
public void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade,
boolean hasFilteredOutSeenNotifications) {
@@ -4949,18 +4840,6 @@ public class NotificationStackScrollLayout
return mEmptyShadeView.isVisible();
}
- public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
- FooterViewRefactor.assertInLegacyMode();
- if (mFooterView == null || mNotificationStackSizeCalculator == null) {
- return;
- }
- boolean animate = mIsExpanded && mAnimationsEnabled;
- mFooterView.setVisible(visible, animate);
- mFooterView.showHistory(showHistory);
- mFooterView.setClearAllButtonVisible(showDismissView, animate);
- mFooterView.setFooterLabelVisible(mHasFilteredOutSeenNotifications);
- }
-
@VisibleForTesting
public void setClearAllInProgress(boolean clearAllInProgress) {
mClearAllInProgress = clearAllInProgress;
@@ -5244,10 +5123,8 @@ public class NotificationStackScrollLayout
public void setQsFullScreen(boolean qsFullScreen) {
SceneContainerFlag.assertInLegacyMode();
- if (FooterViewRefactor.isEnabled()) {
- if (qsFullScreen == mQsFullScreen) {
- return; // no change
- }
+ if (qsFullScreen == mQsFullScreen) {
+ return; // no change
}
mQsFullScreen = qsFullScreen;
updateAlgorithmLayoutMinHeight();
@@ -5266,8 +5143,6 @@ public class NotificationStackScrollLayout
public void setQsExpansionFraction(float qsExpansionFraction) {
SceneContainerFlag.assertInLegacyMode();
- boolean footerAffected = getQsExpansionFraction() != qsExpansionFraction
- && (getQsExpansionFraction() == 1 || qsExpansionFraction == 1);
mQsExpansionFraction = qsExpansionFraction;
updateUseRoundedRectClipping();
@@ -5276,9 +5151,6 @@ public class NotificationStackScrollLayout
if (getOwnScrollY() > 0) {
setOwnScrollY((int) MathUtils.lerp(getOwnScrollY(), 0, getQsExpansionFraction()));
}
- if (!FooterViewRefactor.isEnabled() && footerAffected) {
- updateFooter();
- }
}
@VisibleForTesting
@@ -5456,14 +5328,6 @@ public class NotificationStackScrollLayout
requestChildrenUpdate();
}
- void setUpcomingStatusBarState(int upcomingStatusBarState) {
- FooterViewRefactor.assertInLegacyMode();
- mUpcomingStatusBarState = upcomingStatusBarState;
- if (mUpcomingStatusBarState != mStatusBarState) {
- updateFooter();
- }
- }
-
void onStatePostChange(boolean fromShadeLocked) {
boolean onKeyguard = onKeyguard();
@@ -5472,9 +5336,6 @@ public class NotificationStackScrollLayout
}
setExpandingEnabled(!onKeyguard);
- if (!FooterViewRefactor.isEnabled()) {
- updateFooter();
- }
requestChildrenUpdate();
onUpdateRowStates();
updateVisibility();
@@ -5490,8 +5351,7 @@ public class NotificationStackScrollLayout
if (mEmptyShadeView == null || mEmptyShadeView.getVisibility() == GONE) {
return getMinExpansionHeight();
} else {
- return FooterViewRefactor.isEnabled() ? getAppearEndPosition()
- : getAppearEndPositionLegacy();
+ return getAppearEndPosition();
}
}
@@ -5583,12 +5443,6 @@ public class NotificationStackScrollLayout
for (int i = 0; i < childCount; i++) {
ExpandableView child = getChildAtIndex(i);
child.dump(pw, args);
- if (!FooterViewRefactor.isEnabled()) {
- if (child instanceof FooterView) {
- DumpUtilsKt.withIncreasedIndent(pw,
- () -> dumpFooterViewVisibility(pw));
- }
- }
pw.println();
}
int transientViewCount = getTransientViewCount();
@@ -5615,45 +5469,6 @@ public class NotificationStackScrollLayout
pw.append(" bottomRadius=").println(mBgCornerRadii[4]);
}
- private void dumpFooterViewVisibility(IndentingPrintWriter pw) {
- FooterViewRefactor.assertInLegacyMode();
- final boolean showDismissView = shouldShowDismissView();
-
- pw.println("showFooterView: " + shouldShowFooterView(showDismissView));
- DumpUtilsKt.withIncreasedIndent(
- pw,
- () -> {
- pw.println("showDismissView: " + showDismissView);
- DumpUtilsKt.withIncreasedIndent(
- pw,
- () -> {
- pw.println(
- "hasActiveClearableNotifications: "
- + mController.hasActiveClearableNotifications(
- ROWS_ALL));
- });
- pw.println();
- pw.println("showHistory: " + mController.isHistoryEnabled());
- pw.println();
- pw.println(
- "visibleNotificationCount: "
- + mController.getVisibleNotificationCount());
- pw.println("mIsCurrentUserSetup: " + mIsCurrentUserSetup);
- pw.println("onKeyguard: " + onKeyguard());
- pw.println("mUpcomingStatusBarState: " + mUpcomingStatusBarState);
- if (!SceneContainerFlag.isEnabled()) {
- pw.println("QsExpansionFraction: " + getQsExpansionFraction());
- }
- pw.println("mQsFullScreen: " + mQsFullScreen);
- pw.println(
- "mScreenOffAnimationController"
- + ".shouldHideNotificationsFooter: "
- + mScreenOffAnimationController
- .shouldHideNotificationsFooter());
- pw.println("mIsRemoteInputActive: " + mIsRemoteInputActive);
- });
- }
-
public boolean isFullyHidden() {
return mAmbientState.isFullyHidden();
}
@@ -5764,14 +5579,6 @@ public class NotificationStackScrollLayout
clearNotifications(ROWS_GENTLE, closeShade, hideSilentSection);
}
- /** Legacy version of clearNotifications below. Uses the old data source for notif stats. */
- void clearNotifications(@SelectedRows int selection, boolean closeShade) {
- FooterViewRefactor.assertInLegacyMode();
- final boolean hideSilentSection = !mController.hasNotifications(
- ROWS_GENTLE, false /* clearable */);
- clearNotifications(selection, closeShade, hideSilentSection);
- }
-
/**
* Collects a list of visible rows, and animates them away in a staggered fashion as if they
* were dismissed. Notifications are dismissed in the backend via onClearAllAnimationsEnd.
@@ -5826,25 +5633,6 @@ public class NotificationStackScrollLayout
return canChildBeCleared(row) && matchesSelection(row, selection);
}
- /**
- * Register a {@link View.OnClickListener} to be invoked when the Manage button is clicked.
- */
- public void setManageButtonClickListener(@Nullable OnClickListener listener) {
- FooterViewRefactor.assertInLegacyMode();
- mManageButtonClickListener = listener;
- if (mFooterView != null) {
- mFooterView.setManageButtonClickListener(mManageButtonClickListener);
- }
- }
-
- @VisibleForTesting
- protected void inflateFooterView() {
- FooterViewRefactor.assertInLegacyMode();
- FooterView footerView = (FooterView) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_notification_footer, this, false);
- setFooterView(footerView);
- }
-
private void inflateEmptyShadeView() {
ModesEmptyShadeFix.assertInLegacyMode();
@@ -6091,11 +5879,6 @@ public class NotificationStackScrollLayout
mHighPriorityBeforeSpeedBump = highPriorityBeforeSpeedBump;
}
- void setFooterClearAllListener(FooterClearAllListener listener) {
- FooterViewRefactor.assertInLegacyMode();
- mFooterClearAllListener = listener;
- }
-
void setClearAllFinishedWhilePanelExpandedRunnable(Runnable runnable) {
mClearAllFinishedWhilePanelExpandedRunnable = runnable;
}
@@ -6394,17 +6177,6 @@ public class NotificationStackScrollLayout
}
/**
- * Sets whether the current user is set up, which is required to show the footer (b/193149550)
- */
- public void setCurrentUserSetup(boolean isCurrentUserSetup) {
- FooterViewRefactor.assertInLegacyMode();
- if (mIsCurrentUserSetup != isCurrentUserSetup) {
- mIsCurrentUserSetup = isCurrentUserSetup;
- updateFooter();
- }
- }
-
- /**
* Sets a {@link StackStateLogger} which is notified as the {@link StackStateAnimator} updates
* the views.
*/
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 a33a9ed2df75..b892bebb3120 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
@@ -29,11 +29,8 @@ import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
-import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_HIGH_PRIORITY;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.SelectedRows;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD;
-import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.animation.ObjectAnimator;
import android.content.res.Configuration;
@@ -64,14 +61,10 @@ import com.android.internal.view.OneShotPreDrawListener;
import com.android.systemui.Dumpable;
import com.android.systemui.ExpandHelper;
import com.android.systemui.Gefingerpoken;
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
-import com.android.systemui.keyguard.shared.model.KeyguardState;
-import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.media.controls.ui.controller.KeyguardMediaController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -92,18 +85,13 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpNotificationViewControllerEmptyImpl;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper.HeadsUpNotificationViewController;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
-import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.EntryWithDismissStats;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
@@ -115,14 +103,15 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Di
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
+import com.android.systemui.statusbar.notification.collection.render.DefaultNotifStackController;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
-import com.android.systemui.statusbar.notification.collection.render.NotifStats;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
-import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
-import com.android.systemui.statusbar.notification.dagger.SilentHeader;
-import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpNotificationViewControllerEmptyImpl;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper.HeadsUpNotificationViewController;
+import com.android.systemui.statusbar.notification.headsup.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -137,13 +126,8 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
-import com.android.systemui.statusbar.notification.headsup.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Compile;
import com.android.systemui.util.settings.SecureSettings;
@@ -179,10 +163,8 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private HeadsUpTouchHelper mHeadsUpTouchHelper;
private final NotificationRoundnessManager mNotificationRoundnessManager;
private final TunerService mTunerService;
- private final DeviceProvisionedController mDeviceProvisionedController;
private final DynamicPrivacyController mDynamicPrivacyController;
private final ConfigurationController mConfigurationController;
- private final ZenModeController mZenModeController;
private final MetricsLogger mMetricsLogger;
private final ColorUpdateLogger mColorUpdateLogger;
@@ -193,7 +175,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final NotifPipeline mNotifPipeline;
private final NotifCollection mNotifCollection;
private final UiEventLogger mUiEventLogger;
- private final NotificationRemoteInputManager mRemoteInputManager;
private final VisibilityLocationProviderDelegator mVisibilityLocationProviderDelegator;
private final ShadeController mShadeController;
private final Provider<WindowRootView> mWindowRootView;
@@ -201,9 +182,7 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mKeyguardBypassController;
private final PowerInteractor mPowerInteractor;
- private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final NotificationLockscreenUserManager mLockscreenUserManager;
- private final SectionHeaderController mSilentHeaderController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final InteractionJankMonitor mJankMonitor;
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@@ -211,8 +190,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final NotificationStackScrollLogger mLogger;
private final GroupExpansionManager mGroupExpansionManager;
- private final SeenNotificationsInteractor mSeenNotificationsInteractor;
- private final KeyguardTransitionRepository mKeyguardTransitionRepo;
private NotificationStackScrollLayout mView;
private TouchHandler mTouchHandler;
private NotificationSwipeHelper mSwipeHelper;
@@ -220,7 +197,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private Boolean mHistoryEnabled;
private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
- private boolean mIsInTransitionToAod = false;
private final NotificationTargetsHelper mNotificationTargetsHelper;
private final SecureSettings mSecureSettings;
@@ -235,11 +211,9 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final NotificationListContainerImpl mNotificationListContainer =
new NotificationListContainerImpl();
+ // TODO: b/293167744 - Remove this.
private final NotifStackController mNotifStackController =
- new NotifStackControllerImpl();
-
- @Nullable
- private NotificationActivityStarter mNotificationActivityStarter;
+ new DefaultNotifStackController();
@VisibleForTesting
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
@@ -248,9 +222,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
public void onViewAttachedToWindow(View v) {
mColorUpdateLogger.logTriggerEvent("NSSLC.onViewAttachedToWindow()");
mConfigurationController.addCallback(mConfigurationListener);
- if (!FooterViewRefactor.isEnabled()) {
- mZenModeController.addCallback(mZenModeControllerCallback);
- }
final int newBarState = mStatusBarStateController.getState();
if (newBarState != mBarState) {
mStateListener.onStateChanged(newBarState);
@@ -264,9 +235,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
public void onViewDetachedFromWindow(View v) {
mColorUpdateLogger.logTriggerEvent("NSSLC.onViewDetachedFromWindow()");
mConfigurationController.removeCallback(mConfigurationListener);
- if (!FooterViewRefactor.isEnabled()) {
- mZenModeController.removeCallback(mZenModeControllerCallback);
- }
mStatusBarStateController.removeCallback(mStateListener);
}
};
@@ -287,28 +255,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
@Nullable
private ObjectAnimator mHideAlphaAnimator = null;
- private final DeviceProvisionedListener mDeviceProvisionedListener =
- new DeviceProvisionedListener() {
- @Override
- public void onDeviceProvisionedChanged() {
- updateCurrentUserIsSetup();
- }
-
- @Override
- public void onUserSwitched() {
- updateCurrentUserIsSetup();
- }
-
- @Override
- public void onUserSetupChanged() {
- updateCurrentUserIsSetup();
- }
-
- private void updateCurrentUserIsSetup() {
- mView.setCurrentUserSetup(mDeviceProvisionedController.isCurrentUserSetup());
- }
- };
-
private final Runnable mSensitiveStateChangedListener = new Runnable() {
@Override
public void run() {
@@ -318,20 +264,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
};
- private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> {
- if (!FooterViewRefactor.isEnabled()) {
- // Let's update the footer once the notifications have been updated (in the next frame)
- mView.post(this::updateFooter);
- }
- };
-
@VisibleForTesting
final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onDensityOrFontScaleChanged() {
- if (!FooterViewRefactor.isEnabled()) {
- updateShowEmptyShadeView();
- }
mView.reinflateViews();
}
@@ -351,10 +287,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.updateBgColor();
mView.updateDecorViews();
mView.reinflateViews();
- if (!FooterViewRefactor.isEnabled()) {
- updateShowEmptyShadeView();
- updateFooter();
- }
}
@Override
@@ -363,7 +295,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
};
- private NotifStats mNotifStats = NotifStats.getEmpty();
private float mMaxAlphaForKeyguard = 1.0f;
private String mMaxAlphaForKeyguardSource = "constructor";
private float mMaxAlphaForUnhide = 1.0f;
@@ -401,19 +332,9 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
@Override
- public void onUpcomingStateChanged(int newState) {
- if (!FooterViewRefactor.isEnabled()) {
- mView.setUpcomingStatusBarState(newState);
- }
- }
-
- @Override
public void onStatePostChange() {
updateSensitivenessWithAnimation(mStatusBarStateController.goingToFullShade());
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
- if (!FooterViewRefactor.isEnabled()) {
- updateImportantForAccessibility();
- }
}
};
@@ -422,9 +343,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
public void onUserChanged(int userId) {
updateSensitivenessWithAnimation(false);
mHistoryEnabled = null;
- if (!FooterViewRefactor.isEnabled()) {
- updateFooter();
- }
}
};
@@ -656,7 +574,7 @@ public class NotificationStackScrollLayoutController implements Dumpable {
== null) {
mHeadsUpManager.removeNotification(
row.getEntry().getSbn().getKey(),
- /* removeImmediately= */ true ,
+ /* removeImmediately= */ true,
/* reason= */ "onChildSnappedBack"
);
}
@@ -714,14 +632,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
};
- private final ZenModeController.Callback mZenModeControllerCallback =
- new ZenModeController.Callback() {
- @Override
- public void onZenChanged(int zen) {
- updateShowEmptyShadeView();
- }
- };
-
@Inject
public NotificationStackScrollLayoutController(
NotificationStackScrollLayout view,
@@ -734,16 +644,12 @@ public class NotificationStackScrollLayoutController implements Dumpable {
Provider<IStatusBarService> statusBarService,
NotificationRoundnessManager notificationRoundnessManager,
TunerService tunerService,
- DeviceProvisionedController deviceProvisionedController,
DynamicPrivacyController dynamicPrivacyController,
@ShadeDisplayAware ConfigurationController configurationController,
SysuiStatusBarStateController statusBarStateController,
KeyguardMediaController keyguardMediaController,
KeyguardBypassController keyguardBypassController,
PowerInteractor powerInteractor,
- PrimaryBouncerInteractor primaryBouncerInteractor,
- KeyguardTransitionRepository keyguardTransitionRepo,
- ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
MetricsLogger metricsLogger,
ColorUpdateLogger colorUpdateLogger,
@@ -752,14 +658,11 @@ public class NotificationStackScrollLayoutController implements Dumpable {
FalsingManager falsingManager,
NotificationSwipeHelper.Builder notificationSwipeHelperBuilder,
GroupExpansionManager groupManager,
- @SilentHeader SectionHeaderController silentHeaderController,
NotifPipeline notifPipeline,
NotifCollection notifCollection,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
UiEventLogger uiEventLogger,
- NotificationRemoteInputManager remoteInputManager,
VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
- SeenNotificationsInteractor seenNotificationsInteractor,
NotificationListViewBinder viewBinder,
ShadeController shadeController,
Provider<WindowRootView> windowRootView,
@@ -775,7 +678,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
SensitiveNotificationProtectionController sensitiveNotificationProtectionController,
WallpaperInteractor wallpaperInteractor) {
mView = view;
- mKeyguardTransitionRepo = keyguardTransitionRepo;
mViewBinder = viewBinder;
mStackStateLogger = stackLogger;
mLogger = logger;
@@ -795,15 +697,12 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
mNotificationRoundnessManager = notificationRoundnessManager;
mTunerService = tunerService;
- mDeviceProvisionedController = deviceProvisionedController;
mDynamicPrivacyController = dynamicPrivacyController;
mConfigurationController = configurationController;
mStatusBarStateController = statusBarStateController;
mKeyguardMediaController = keyguardMediaController;
mKeyguardBypassController = keyguardBypassController;
mPowerInteractor = powerInteractor;
- mPrimaryBouncerInteractor = primaryBouncerInteractor;
- mZenModeController = zenModeController;
mLockscreenUserManager = lockscreenUserManager;
mMetricsLogger = metricsLogger;
mColorUpdateLogger = colorUpdateLogger;
@@ -815,13 +714,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mJankMonitor = jankMonitor;
mNotificationStackSizeCalculator = notificationStackSizeCalculator;
mGroupExpansionManager = groupManager;
- mSilentHeaderController = silentHeaderController;
mNotifPipeline = notifPipeline;
mNotifCollection = notifCollection;
mUiEventLogger = uiEventLogger;
- mRemoteInputManager = remoteInputManager;
mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
- mSeenNotificationsInteractor = seenNotificationsInteractor;
mShadeController = shadeController;
mWindowRootView = windowRootView;
mNotificationTargetsHelper = notificationTargetsHelper;
@@ -850,18 +746,7 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.setClearAllAnimationListener(this::onAnimationEnd);
mView.setClearAllListener((selection) -> mUiEventLogger.log(
NotificationPanelEvent.fromSelection(selection)));
- if (!FooterViewRefactor.isEnabled()) {
- mView.setFooterClearAllListener(() ->
- mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES));
- mView.setIsRemoteInputActive(mRemoteInputManager.isRemoteInputActive());
- mRemoteInputManager.addControllerCallback(new RemoteInputController.Callback() {
- @Override
- public void onRemoteInputActive(boolean active) {
- mView.setIsRemoteInputActive(active);
- }
- });
- }
- mView.setClearAllFinishedWhilePanelExpandedRunnable(()-> {
+ mView.setClearAllFinishedWhilePanelExpandedRunnable(() -> {
final Runnable doCollapseRunnable = () ->
mShadeController.animateCollapseShade(CommandQueue.FLAG_EXCLUDE_NONE);
mView.postDelayed(doCollapseRunnable, /* delayMillis = */ DELAY_BEFORE_SHADE_CLOSE);
@@ -889,19 +774,11 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled());
mKeyguardBypassController
.registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled);
- if (!FooterViewRefactor.isEnabled()) {
- mView.setManageButtonClickListener(v -> {
- if (mNotificationActivityStarter != null) {
- mNotificationActivityStarter.startHistoryIntent(v, mView.isHistoryShown());
- }
- });
- }
if (!SceneContainerFlag.isEnabled()) {
mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
}
mHeadsUpManager.setAnimationStateHandler(mView::setHeadsUpGoingAwayAnimationsAllowed);
- mDynamicPrivacyController.addListener(mDynamicPrivacyControllerListener);
mLockscreenShadeTransitionController.setStackScroller(this);
@@ -914,9 +791,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
switch (key) {
case Settings.Secure.NOTIFICATION_HISTORY_ENABLED:
mHistoryEnabled = null; // invalidate
- if (!FooterViewRefactor.isEnabled()) {
- updateFooter();
- }
break;
case HIGH_PRIORITY:
mView.setHighPriorityBeforeSpeedBump("1".equals(newValue));
@@ -938,12 +812,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
return kotlin.Unit.INSTANCE;
});
- if (!FooterViewRefactor.isEnabled()) {
- // attach callback, and then call it to update mView immediately
- mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- mDeviceProvisionedListener.onDeviceProvisionedChanged();
- }
-
if (screenshareNotificationHiding()) {
mSensitiveNotificationProtectionController
.registerSensitiveStateListener(mSensitiveStateChangedListener);
@@ -953,20 +821,12 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
}
mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
- if (!FooterViewRefactor.isEnabled()) {
- mSilentHeaderController.setOnClearSectionClickListener(v -> clearSilentNotifications());
- }
mGroupExpansionManager.registerGroupExpansionChangeListener(
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
mViewBinder.bindWhileAttached(mView, this);
- if (!FooterViewRefactor.isEnabled()) {
- collectFlow(mView, mKeyguardTransitionRepo.getTransitions(),
- this::onKeyguardTransitionChanged);
- }
-
mView.setWallpaperInteractor(mWallpaperInteractor);
}
@@ -1168,11 +1028,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
return mView != null && mView.isAddOrRemoveAnimationPending();
}
- public int getVisibleNotificationCount() {
- FooterViewRefactor.assertInLegacyMode();
- return mNotifStats.getNumActiveNotifs();
- }
-
public boolean isHistoryEnabled() {
Boolean historyEnabled = mHistoryEnabled;
if (historyEnabled == null) {
@@ -1284,9 +1139,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
public void setQsFullScreen(boolean fullScreen) {
mView.setQsFullScreen(fullScreen);
- if (!FooterViewRefactor.isEnabled()) {
- updateShowEmptyShadeView();
- }
}
public void setScrollingEnabled(boolean enabled) {
@@ -1464,64 +1316,12 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
/**
- * Set the visibility of the view, and propagate it to specific children.
+ * Set the visibility of the view.
*
* @param visible either the view is visible or not.
*/
public void updateVisibility(boolean visible) {
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-
- // Refactor note: the empty shade's visibility doesn't seem to actually depend on the
- // parent visibility (so this update seemingly doesn't do anything). Therefore, this is not
- // modeled in the refactored code.
- if (!FooterViewRefactor.isEnabled() && mView.getVisibility() == View.VISIBLE) {
- // Synchronize EmptyShadeView visibility with the parent container.
- updateShowEmptyShadeView();
- updateImportantForAccessibility();
- }
- }
-
- /**
- * Update whether we should show the empty shade view ("no notifications" in the shade).
- * <p>
- * When in split mode, notifications are always visible regardless of the state of the
- * QuickSettings panel. That being the case, empty view is always shown if the other conditions
- * are true.
- */
- public void updateShowEmptyShadeView() {
- FooterViewRefactor.assertInLegacyMode();
-
- Trace.beginSection("NSSLC.updateShowEmptyShadeView");
-
- final boolean shouldShow = getVisibleNotificationCount() == 0
- && !mView.isQsFullScreen()
- // Hide empty shade view when in transition to AOD.
- // That avoids "No Notifications" to blink when transitioning to AOD.
- // For more details, see: b/228790482
- && !mIsInTransitionToAod
- // Don't show any notification content if the bouncer is showing. See b/267060171.
- && !mPrimaryBouncerInteractor.isBouncerShowing();
-
- mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
-
- Trace.endSection();
- }
-
- /**
- * Update the importantForAccessibility of NotificationStackScrollLayout.
- * <p>
- * We want the NSSL to be unimportant for accessibility when there's no
- * notifications in it while the device is on lock screen, to avoid unlablel NSSL view.
- * Otherwise, we want it to be important for accessibility to enable accessibility
- * auto-scrolling in NSSL.
- */
- public void updateImportantForAccessibility() {
- FooterViewRefactor.assertInLegacyMode();
- if (getVisibleNotificationCount() == 0 && mView.onKeyguard()) {
- mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- } else {
- mView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
}
public boolean isShowingEmptyShadeView() {
@@ -1577,34 +1377,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.setPulsing(pulsing, animatePulse);
}
- /**
- * Return whether there are any clearable notifications
- */
- public boolean hasActiveClearableNotifications(@SelectedRows int selection) {
- FooterViewRefactor.assertInLegacyMode();
- return hasNotifications(selection, true /* clearable */);
- }
-
- public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
- FooterViewRefactor.assertInLegacyMode();
- boolean hasAlertingMatchingClearable = isClearable
- ? mNotifStats.getHasClearableAlertingNotifs()
- : mNotifStats.getHasNonClearableAlertingNotifs();
- boolean hasSilentMatchingClearable = isClearable
- ? mNotifStats.getHasClearableSilentNotifs()
- : mNotifStats.getHasNonClearableSilentNotifs();
- switch (selection) {
- case ROWS_GENTLE:
- return hasSilentMatchingClearable;
- case ROWS_HIGH_PRIORITY:
- return hasAlertingMatchingClearable;
- case ROWS_ALL:
- return hasSilentMatchingClearable || hasAlertingMatchingClearable;
- default:
- throw new IllegalStateException("Bad selection: " + selection);
- }
- }
-
/** Sets whether the NSSL is displayed over the unoccluded Lockscreen. */
public void setOnLockscreen(boolean isOnLockscreen) {
if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
@@ -1637,9 +1409,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
entry.notifyHeightChanged(true /* needsAnimation */);
- if (!FooterViewRefactor.isEnabled()) {
- updateFooter();
- }
}
public void lockScrollTo(NotificationEntry entry) {
@@ -1662,13 +1431,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
};
}
- public void updateFooter() {
- FooterViewRefactor.assertInLegacyMode();
- Trace.beginSection("NSSLC.updateFooter");
- mView.updateFooter();
- Trace.endSection();
- }
-
public void onUpdateRowStates() {
mView.onUpdateRowStates();
}
@@ -1695,18 +1457,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
return mView.getTransientViewCount();
}
- public View getTransientView(int i) {
- return mView.getTransientView(i);
- }
-
public NotificationStackScrollLayout getView() {
return mView;
}
- public float calculateGapHeight(ExpandableView previousView, ExpandableView child, int count) {
- return mView.calculateGapHeight(previousView, child, count);
- }
-
NotificationRoundnessManager getNotificationRoundnessManager() {
return mNotificationRoundnessManager;
}
@@ -1772,13 +1526,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
return NotificationSwipeHelper.isTouchInView(event, view);
}
- public void clearSilentNotifications() {
- FooterViewRefactor.assertInLegacyMode();
- // Leave the shade open if there will be other notifs left over to clear
- final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
- mView.clearNotifications(ROWS_GENTLE, closeShade);
- }
-
private void onAnimationEnd(List<ExpandableNotificationRow> viewsToRemove,
@SelectedRows int selectedRows) {
if (selectedRows == ROWS_ALL) {
@@ -1880,10 +1627,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
mView.animateNextTopPaddingChange();
}
- public void setNotificationActivityStarter(NotificationActivityStarter activityStarter) {
- mNotificationActivityStarter = activityStarter;
- }
-
public NotificationTargetsHelper getNotificationTargetsHelper() {
return mNotificationTargetsHelper;
}
@@ -1898,18 +1641,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
}
@VisibleForTesting
- void onKeyguardTransitionChanged(TransitionStep transitionStep) {
- FooterViewRefactor.assertInLegacyMode();
- boolean isTransitionToAod = transitionStep.getTo().equals(KeyguardState.AOD)
- && (transitionStep.getFrom().equals(KeyguardState.GONE)
- || transitionStep.getFrom().equals(KeyguardState.OCCLUDED));
- if (mIsInTransitionToAod != isTransitionToAod) {
- mIsInTransitionToAod = isTransitionToAod;
- updateShowEmptyShadeView();
- }
- }
-
- @VisibleForTesting
TouchHandler getTouchHandler() {
return mTouchHandler;
}
@@ -2288,22 +2019,4 @@ public class NotificationStackScrollLayoutController implements Dumpable {
&& !mSwipeHelper.isSwiping();
}
}
-
- private class NotifStackControllerImpl implements NotifStackController {
- @Override
- public void setNotifStats(@NonNull NotifStats notifStats) {
- FooterViewRefactor.assertInLegacyMode();
- mNotifStats = notifStats;
-
- if (!FooterViewRefactor.isEnabled()) {
- mView.setHasFilteredOutSeenNotifications(
- mSeenNotificationsInteractor
- .getHasFilteredOutSeenNotifications().getValue());
-
- updateFooter();
- updateShowEmptyShadeView();
- updateImportantForAccessibility();
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 1653029dc994..06b989aaab57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -35,7 +35,6 @@ import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeView;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -463,26 +462,23 @@ public class StackScrollAlgorithm {
if (v == ambientState.getShelf()) {
continue;
}
- if (FooterViewRefactor.isEnabled()) {
- if (v instanceof EmptyShadeView) {
- emptyShadeVisible = true;
- }
- if (v instanceof FooterView footerView) {
- if (emptyShadeVisible || notGoneIndex == 0) {
- // if the empty shade is visible or the footer is the first visible
- // view, we're in a transitory state so let's leave the footer alone.
- if (Flags.notificationsFooterVisibilityFix()
- && !SceneContainerFlag.isEnabled()) {
- // ...except for the hidden state, to prevent it from flashing on
- // the screen (this piece is copied from updateChild, and is not
- // necessary in flexiglass).
- if (footerView.shouldBeHidden()
- || !ambientState.isShadeExpanded()) {
- footerView.getViewState().hidden = true;
- }
+ if (v instanceof EmptyShadeView) {
+ emptyShadeVisible = true;
+ }
+ if (v instanceof FooterView footerView) {
+ if (emptyShadeVisible || notGoneIndex == 0) {
+ // if the empty shade is visible or the footer is the first visible
+ // view, we're in a transitory state so let's leave the footer alone.
+ if (Flags.notificationsFooterVisibilityFix()
+ && !SceneContainerFlag.isEnabled()) {
+ // ...except for the hidden state, to prevent it from flashing on
+ // the screen (this piece is copied from updateChild, and is not
+ // necessary in flexiglass).
+ if (footerView.shouldBeHidden() || !ambientState.isShadeExpanded()) {
+ footerView.getViewState().hidden = true;
}
- continue;
}
+ continue;
}
}
@@ -699,44 +695,28 @@ public class StackScrollAlgorithm {
viewEnd, /* hunMax */ ambientState.getMaxHeadsUpTranslation()
);
if (view instanceof FooterView) {
- if (FooterViewRefactor.isEnabled()) {
- if (SceneContainerFlag.isEnabled()) {
- final float footerEnd =
- stackTop + viewState.getYTranslation() + view.getIntrinsicHeight();
- final boolean noSpaceForFooter = footerEnd > ambientState.getStackCutoff();
- ((FooterView.FooterViewState) viewState).hideContent =
- noSpaceForFooter || (ambientState.isClearAllInProgress()
- && !hasNonClearableNotifs(algorithmState));
- } else {
- // TODO(b/333445519): shouldBeHidden should reflect whether the shade is closed
- // already, so we shouldn't need to use ambientState here. However,
- // currently it doesn't get updated quickly enough and can cause the footer to
- // flash when closing the shade. As such, we temporarily also check the
- // ambientState directly.
- if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) {
- viewState.hidden = true;
- } else {
- final float footerEnd = algorithmState.mCurrentExpandedYPosition
- + view.getIntrinsicHeight();
- final boolean noSpaceForFooter =
- footerEnd > ambientState.getStackEndHeight();
- ((FooterView.FooterViewState) viewState).hideContent =
- noSpaceForFooter || (ambientState.isClearAllInProgress()
- && !hasNonClearableNotifs(algorithmState));
- }
- }
+ if (SceneContainerFlag.isEnabled()) {
+ final float footerEnd =
+ stackTop + viewState.getYTranslation() + view.getIntrinsicHeight();
+ final boolean noSpaceForFooter = footerEnd > ambientState.getStackCutoff();
+ ((FooterView.FooterViewState) viewState).hideContent =
+ noSpaceForFooter || (ambientState.isClearAllInProgress()
+ && !hasNonClearableNotifs(algorithmState));
} else {
- final boolean shadeClosed = !ambientState.isShadeExpanded();
- final boolean isShelfShowing = algorithmState.firstViewInShelf != null;
- if (shadeClosed) {
+ // TODO(b/333445519): shouldBeHidden should reflect whether the shade is closed
+ // already, so we shouldn't need to use ambientState here. However,
+ // currently it doesn't get updated quickly enough and can cause the footer to
+ // flash when closing the shade. As such, we temporarily also check the
+ // ambientState directly.
+ if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) {
viewState.hidden = true;
} else {
final float footerEnd = algorithmState.mCurrentExpandedYPosition
+ view.getIntrinsicHeight();
- final boolean noSpaceForFooter = footerEnd > ambientState.getStackEndHeight();
+ final boolean noSpaceForFooter =
+ footerEnd > ambientState.getStackEndHeight();
((FooterView.FooterViewState) viewState).hideContent =
- isShelfShowing || noSpaceForFooter
- || (ambientState.isClearAllInProgress()
+ noSpaceForFooter || (ambientState.isClearAllInProgress()
&& !hasNonClearableNotifs(algorithmState));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index b4561686b7b2..1d7e658932ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -40,7 +40,6 @@ import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyS
import com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeView
import com.android.systemui.statusbar.notification.emptyshade.ui.viewbinder.EmptyShadeViewBinder
import com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel.EmptyShadeViewModel
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView
import com.android.systemui.statusbar.notification.footer.ui.viewbinder.FooterViewBinder
@@ -108,25 +107,20 @@ constructor(
launch { bindShelf(shelf) }
bindHideList(viewController, viewModel, hiderTracker)
- if (FooterViewRefactor.isEnabled) {
- val hasNonClearableSilentNotifications: StateFlow<Boolean> =
- viewModel.hasNonClearableSilentNotifications.stateIn(this)
- launch { reinflateAndBindFooter(view, hasNonClearableSilentNotifications) }
- launch {
- if (ModesEmptyShadeFix.isEnabled) {
- reinflateAndBindEmptyShade(view)
- } else {
- bindEmptyShadeLegacy(viewModel.emptyShadeViewFactory.create(), view)
- }
+ val hasNonClearableSilentNotifications: StateFlow<Boolean> =
+ viewModel.hasNonClearableSilentNotifications.stateIn(this)
+ launch { reinflateAndBindFooter(view, hasNonClearableSilentNotifications) }
+ launch {
+ if (ModesEmptyShadeFix.isEnabled) {
+ reinflateAndBindEmptyShade(view)
+ } else {
+ bindEmptyShadeLegacy(viewModel.emptyShadeViewFactory.create(), view)
}
- launch {
- bindSilentHeaderClickListener(view, hasNonClearableSilentNotifications)
- }
- launch {
- viewModel.isImportantForAccessibility.collect { isImportantForAccessibility
- ->
- view.setImportantForAccessibilityYesNo(isImportantForAccessibility)
- }
+ }
+ launch { bindSilentHeaderClickListener(view, hasNonClearableSilentNotifications) }
+ launch {
+ viewModel.isImportantForAccessibility.collect { isImportantForAccessibility ->
+ view.setImportantForAccessibilityYesNo(isImportantForAccessibility)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index ea714608ea66..0b2b84e60f4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -28,7 +28,6 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
@@ -81,9 +80,6 @@ constructor(
controller.setOverExpansion(0f)
controller.setOverScrollAmount(0)
- if (!FooterViewRefactor.isEnabled) {
- controller.updateFooter()
- }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index 38390e7bdb39..fcc671a5bae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -25,7 +25,6 @@ import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotif
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel.EmptyShadeViewModel
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModel
import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey
import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
@@ -75,46 +74,37 @@ constructor(
* we want it to be important for accessibility to enable accessibility auto-scrolling in NSSL.
* See b/242235264 for more details.
*/
- val isImportantForAccessibility: Flow<Boolean> by lazy {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(true)
- } else {
- combine(
- activeNotificationsInteractor.areAnyNotificationsPresent,
- notificationStackInteractor.isShowingOnLockscreen,
- ) { hasNotifications, isShowingOnLockscreen ->
- hasNotifications || !isShowingOnLockscreen
- }
- .distinctUntilChanged()
- .dumpWhileCollecting("isImportantForAccessibility")
- .flowOn(bgDispatcher)
- }
- }
+ val isImportantForAccessibility: Flow<Boolean> =
+ combine(
+ activeNotificationsInteractor.areAnyNotificationsPresent,
+ notificationStackInteractor.isShowingOnLockscreen,
+ ) { hasNotifications, isShowingOnLockscreen ->
+ hasNotifications || !isShowingOnLockscreen
+ }
+ .distinctUntilChanged()
+ .dumpWhileCollecting("isImportantForAccessibility")
+ .flowOn(bgDispatcher)
val shouldShowEmptyShadeView: Flow<Boolean> by lazy {
ModesEmptyShadeFix.assertInLegacyMode()
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(false)
- } else {
- combine(
- activeNotificationsInteractor.areAnyNotificationsPresent,
- shadeInteractor.isQsFullscreen,
- notificationStackInteractor.isShowingOnLockscreen,
- ) { hasNotifications, isQsFullScreen, isShowingOnLockscreen ->
- when {
- hasNotifications -> false
- isQsFullScreen -> false
- // Do not show the empty shade if the lockscreen is visible (including AOD
- // b/228790482 and bouncer b/267060171), except if the shade is opened on
- // top.
- isShowingOnLockscreen -> false
- else -> true
- }
+ combine(
+ activeNotificationsInteractor.areAnyNotificationsPresent,
+ shadeInteractor.isQsFullscreen,
+ notificationStackInteractor.isShowingOnLockscreen,
+ ) { hasNotifications, isQsFullScreen, isShowingOnLockscreen ->
+ when {
+ hasNotifications -> false
+ isQsFullScreen -> false
+ // Do not show the empty shade if the lockscreen is visible (including AOD
+ // b/228790482 and bouncer b/267060171), except if the shade is opened on
+ // top.
+ isShowingOnLockscreen -> false
+ else -> true
}
- .distinctUntilChanged()
- .dumpWhileCollecting("shouldShowEmptyShadeView")
- .flowOn(bgDispatcher)
- }
+ }
+ .distinctUntilChanged()
+ .dumpWhileCollecting("shouldShowEmptyShadeView")
+ .flowOn(bgDispatcher)
}
val shouldShowEmptyShadeViewAnimated: Flow<AnimatedValue<Boolean>> by lazy {
@@ -164,18 +154,14 @@ constructor(
*/
val shouldHideFooterView: Flow<Boolean> by lazy {
SceneContainerFlag.assertInLegacyMode()
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(false)
- } else {
- // When the shade is closed, the footer is still present in the list, but not visible.
- // This prevents the footer from being shown when a HUN is present, while still allowing
- // the footer to be counted as part of the shade for measurements.
- shadeInteractor.shadeExpansion
- .map { it == 0f }
- .distinctUntilChanged()
- .dumpWhileCollecting("shouldHideFooterView")
- .flowOn(bgDispatcher)
- }
+ // When the shade is closed, the footer is still present in the list, but not visible.
+ // This prevents the footer from being shown when a HUN is present, while still allowing
+ // the footer to be counted as part of the shade for measurements.
+ shadeInteractor.shadeExpansion
+ .map { it == 0f }
+ .distinctUntilChanged()
+ .dumpWhileCollecting("shouldHideFooterView")
+ .flowOn(bgDispatcher)
}
/**
@@ -188,68 +174,64 @@ constructor(
*/
val shouldIncludeFooterView: Flow<AnimatedValue<Boolean>> by lazy {
SceneContainerFlag.assertInLegacyMode()
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(AnimatedValue.NotAnimating(false))
- } else {
- combine(
- activeNotificationsInteractor.areAnyNotificationsPresent,
- userSetupInteractor.isUserSetUp,
- notificationStackInteractor.isShowingOnLockscreen,
- shadeInteractor.isQsFullscreen,
- remoteInputInteractor.isRemoteInputActive,
- ) {
- hasNotifications,
- isUserSetUp,
- isShowingOnLockscreen,
- qsFullScreen,
- isRemoteInputActive ->
- when {
- !hasNotifications -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
- // Hide the footer until the user setup is complete, to prevent access
- // to settings (b/193149550).
- !isUserSetUp -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
- // Do not show the footer if the lockscreen is visible (incl. AOD),
- // except if the shade is opened on top. See also b/219680200.
- // Do not animate, as that makes the footer appear briefly when
- // transitioning between the shade and keyguard.
- isShowingOnLockscreen -> VisibilityChange.DISAPPEAR_WITHOUT_ANIMATION
- // Do not show the footer if quick settings are fully expanded (except
- // for the foldable split shade view). See b/201427195 && b/222699879.
- qsFullScreen -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
- // Hide the footer if remote input is active (i.e. user is replying to a
- // notification). See b/75984847.
- isRemoteInputActive -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
- else -> VisibilityChange.APPEAR_WITH_ANIMATION
- }
+ combine(
+ activeNotificationsInteractor.areAnyNotificationsPresent,
+ userSetupInteractor.isUserSetUp,
+ notificationStackInteractor.isShowingOnLockscreen,
+ shadeInteractor.isQsFullscreen,
+ remoteInputInteractor.isRemoteInputActive,
+ ) {
+ hasNotifications,
+ isUserSetUp,
+ isShowingOnLockscreen,
+ qsFullScreen,
+ isRemoteInputActive ->
+ when {
+ !hasNotifications -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Hide the footer until the user setup is complete, to prevent access
+ // to settings (b/193149550).
+ !isUserSetUp -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Do not show the footer if the lockscreen is visible (incl. AOD),
+ // except if the shade is opened on top. See also b/219680200.
+ // Do not animate, as that makes the footer appear briefly when
+ // transitioning between the shade and keyguard.
+ isShowingOnLockscreen -> VisibilityChange.DISAPPEAR_WITHOUT_ANIMATION
+ // Do not show the footer if quick settings are fully expanded (except
+ // for the foldable split shade view). See b/201427195 && b/222699879.
+ qsFullScreen -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Hide the footer if remote input is active (i.e. user is replying to a
+ // notification). See b/75984847.
+ isRemoteInputActive -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ else -> VisibilityChange.APPEAR_WITH_ANIMATION
}
- .distinctUntilChanged(
- // Equivalent unless visibility changes
- areEquivalent = { a: VisibilityChange, b: VisibilityChange ->
- a.visible == b.visible
- }
- )
- // Should we animate the visibility change?
- .sample(
- // TODO(b/322167853): This check is currently duplicated in FooterViewModel,
- // but instead it should be a field in ShadeAnimationInteractor.
- combine(
- shadeInteractor.isShadeFullyExpanded,
- shadeInteractor.isShadeTouchable,
- ::Pair,
- )
- .onStart { emit(Pair(false, false)) }
- ) { visibilityChange, (isShadeFullyExpanded, animationsEnabled) ->
- // Animate if the shade is interactive, but NOT on the lockscreen. Having
- // animations enabled while on the lockscreen makes the footer appear briefly
- // when transitioning between the shade and keyguard.
- val shouldAnimate =
- isShadeFullyExpanded && animationsEnabled && visibilityChange.canAnimate
- AnimatableEvent(visibilityChange.visible, shouldAnimate)
+ }
+ .distinctUntilChanged(
+ // Equivalent unless visibility changes
+ areEquivalent = { a: VisibilityChange, b: VisibilityChange ->
+ a.visible == b.visible
}
- .toAnimatedValueFlow()
- .dumpWhileCollecting("shouldIncludeFooterView")
- .flowOn(bgDispatcher)
- }
+ )
+ // Should we animate the visibility change?
+ .sample(
+ // TODO(b/322167853): This check is currently duplicated in FooterViewModel,
+ // but instead it should be a field in ShadeAnimationInteractor.
+ combine(
+ shadeInteractor.isShadeFullyExpanded,
+ shadeInteractor.isShadeTouchable,
+ ::Pair,
+ )
+ .onStart { emit(Pair(false, false)) }
+ ) { visibilityChange, (isShadeFullyExpanded, animationsEnabled) ->
+ // Animate if the shade is interactive, but NOT on the lockscreen. Having
+ // animations enabled while on the lockscreen makes the footer appear briefly
+ // when transitioning between the shade and keyguard.
+ val shouldAnimate =
+ isShadeFullyExpanded && animationsEnabled && visibilityChange.canAnimate
+ AnimatableEvent(visibilityChange.visible, shouldAnimate)
+ }
+ .toAnimatedValueFlow()
+ .dumpWhileCollecting("shouldIncludeFooterView")
+ .flowOn(bgDispatcher)
}
// This flow replaces shouldHideFooterView+shouldIncludeFooterView in flexiglass.
@@ -328,25 +310,15 @@ constructor(
APPEAR_WITH_ANIMATION(visible = true, canAnimate = true),
}
- val hasClearableAlertingNotifications: Flow<Boolean> by lazy {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(false)
- } else {
- activeNotificationsInteractor.hasClearableAlertingNotifications.dumpWhileCollecting(
- "hasClearableAlertingNotifications"
- )
- }
- }
+ val hasClearableAlertingNotifications: Flow<Boolean> =
+ activeNotificationsInteractor.hasClearableAlertingNotifications.dumpWhileCollecting(
+ "hasClearableAlertingNotifications"
+ )
- val hasNonClearableSilentNotifications: Flow<Boolean> by lazy {
- if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
- flowOf(false)
- } else {
- activeNotificationsInteractor.hasNonClearableSilentNotifications.dumpWhileCollecting(
- "hasNonClearableSilentNotifications"
- )
- }
- }
+ val hasNonClearableSilentNotifications: Flow<Boolean> =
+ activeNotificationsInteractor.hasNonClearableSilentNotifications.dumpWhileCollecting(
+ "hasNonClearableSilentNotifications"
+ )
val topHeadsUpRow: Flow<HeadsUpRowKey?> by lazy {
if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 1474789ea0e3..3d6cd7e49dfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1487,8 +1487,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mActivityTransitionAnimator.setCallback(mActivityTransitionAnimatorCallback);
mActivityTransitionAnimator.addListener(mActivityTransitionAnimatorListener);
mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
- mStackScrollerController.setNotificationActivityStarter(
- mNotificationActivityStarterLazy.get());
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarterLazy.get());
mShadeController.setNotificationPresenter(mPresenterLazy.get());
mNotificationsController.initialize(
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 3749b96199f6..8443edd6aa87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone;
import static android.view.WindowInsets.Type.navigationBars;
-import static com.android.systemui.Flags.predictiveBackAnimateBouncer;
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
@@ -328,7 +327,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private float mQsExpansion;
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
- private boolean mIsBackAnimationEnabled;
private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
private final ActivityStarter mActivityStarter;
@@ -434,7 +432,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
mAlternateBouncerInteractor = alternateBouncerInteractor;
mBouncerInteractor = bouncerInteractor;
- mIsBackAnimationEnabled = predictiveBackAnimateBouncer();
mUdfpsOverlayInteractor = udfpsOverlayInteractor;
mActivityStarter = activityStarter;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
@@ -630,7 +627,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean shouldPlayBackAnimation() {
// Suppress back animation when bouncer shouldn't be dismissed on back invocation.
- return !needsFullscreenBouncer() && mIsBackAnimationEnabled;
+ return !needsFullscreenBouncer();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 03324d2a3e6a..c47ed1722bb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.Flags.predictiveBackAnimateDialogs;
-
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
@@ -285,15 +283,13 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
for (int i = 0; i < mOnCreateRunnables.size(); i++) {
mOnCreateRunnables.get(i).run();
}
- if (predictiveBackAnimateDialogs()) {
- View targetView = getWindow().getDecorView();
- DialogKt.registerAnimationOnBackInvoked(
- /* dialog = */ this,
- /* targetView = */ targetView,
- /* backAnimationSpec= */mDelegate.getBackAnimationSpec(
- () -> targetView.getResources().getDisplayMetrics())
- );
- }
+ View targetView = getWindow().getDecorView();
+ DialogKt.registerAnimationOnBackInvoked(
+ /* dialog = */ this,
+ /* targetView = */ targetView,
+ /* backAnimationSpec= */mDelegate.getBackAnimationSpec(
+ () -> targetView.getResources().getDisplayMetrics())
+ );
}
private void updateWindowSize() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
index 12ed647fdee7..fdc2d8d96f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.policy.domain.interactor
-import android.app.NotificationManager.INTERRUPTION_FILTER_NONE
import android.content.Context
+import android.media.AudioManager
import android.provider.Settings
import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
@@ -29,6 +29,7 @@ import com.android.settingslib.notification.data.repository.ZenModeRepository
import com.android.settingslib.notification.modes.ZenIcon
import com.android.settingslib.notification.modes.ZenIconLoader
import com.android.settingslib.notification.modes.ZenMode
+import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.modes.shared.ModesUi
import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
@@ -67,6 +68,17 @@ constructor(
deviceProvisioningRepository: DeviceProvisioningRepository,
userSetupRepository: UserSetupRepository,
) {
+ /**
+ * List of predicates to determine if the [ZenMode] blocks an audio stream. Typical use case
+ * would be: `zenModeByStreamPredicates[stream](zenMode)`
+ */
+ private val zenModeByStreamPredicates =
+ mapOf<Int, (ZenMode) -> Boolean>(
+ AudioManager.STREAM_MUSIC to { it.policy.priorityCategoryMedia == STATE_DISALLOW },
+ AudioManager.STREAM_ALARM to { it.policy.priorityCategoryAlarms == STATE_DISALLOW },
+ AudioManager.STREAM_SYSTEM to { it.policy.priorityCategorySystem == STATE_DISALLOW },
+ )
+
val isZenAvailable: Flow<Boolean> =
combine(
deviceProvisioningRepository.isDeviceProvisioned,
@@ -125,21 +137,16 @@ constructor(
.flowOn(bgDispatcher)
.distinctUntilChanged()
- val activeModesBlockingEverything: Flow<ActiveZenModes> = getFilteredActiveModesFlow { mode ->
- mode.interruptionFilter == INTERRUPTION_FILTER_NONE
- }
-
- val activeModesBlockingMedia: Flow<ActiveZenModes> = getFilteredActiveModesFlow { mode ->
- mode.policy.priorityCategoryMedia == STATE_DISALLOW
- }
-
- val activeModesBlockingAlarms: Flow<ActiveZenModes> = getFilteredActiveModesFlow { mode ->
- mode.policy.priorityCategoryAlarms == STATE_DISALLOW
- }
+ fun canBeBlockedByZenMode(stream: AudioStream): Boolean =
+ zenModeByStreamPredicates.containsKey(stream.value)
- private fun getFilteredActiveModesFlow(predicate: (ZenMode) -> Boolean): Flow<ActiveZenModes> {
+ fun activeModesBlockingStream(stream: AudioStream): Flow<ActiveZenModes> {
+ val isBlockingStream = zenModeByStreamPredicates[stream.value]
+ require(isBlockingStream != null) {
+ "$stream is unsupported. Use canBeBlockedByZenMode to check if the stream can be affected by the Zen Mode."
+ }
return modes
- .map { modes -> modes.filter { mode -> predicate(mode) } }
+ .map { modes -> modes.filter { isBlockingStream(it) } }
.map { modes -> buildActiveZenModes(modes) }
.flowOn(bgDispatcher)
.distinctUntilChanged()
@@ -194,7 +201,6 @@ constructor(
)
null
}
-
ZEN_DURATION_FOREVER -> null
else -> Duration.ofMinutes(zenDuration.toLong())
}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
index ae32b7a6175c..bce55cbdcc4a 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
@@ -50,7 +50,7 @@ fun BackGestureTutorialScreen(
)
GestureTutorialScreen(
screenConfig = screenConfig,
- gestureUiStateFlow = viewModel.gestureUiState,
+ tutorialStateFlow = viewModel.tutorialState,
motionEventConsumer = {
easterEggGestureViewModel.accept(it)
viewModel.handleEvent(it)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
index 73c54af595d9..284e23e5a288 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
@@ -18,7 +18,6 @@ package com.android.systemui.touchpad.tutorial.ui.composable
import android.view.MotionEvent
import androidx.activity.compose.BackHandler
-import androidx.annotation.RawRes
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
@@ -27,77 +26,21 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.inputdevice.tutorial.ui.composable.ActionTutorialContent
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.NotStarted
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
import kotlinx.coroutines.flow.Flow
-sealed interface GestureUiState {
- data object NotStarted : GestureUiState
-
- data class Finished(@RawRes val successAnimation: Int) : GestureUiState
-
- data class InProgress(
- val progress: Float = 0f,
- val progressStartMarker: String,
- val progressEndMarker: String,
- ) : GestureUiState
-
- data object Error : GestureUiState
-}
-
-fun GestureState.toGestureUiState(
- progressStartMarker: String,
- progressEndMarker: String,
- successAnimation: Int,
-): GestureUiState {
- return when (this) {
- GestureState.NotStarted -> NotStarted
- is GestureState.InProgress ->
- GestureUiState.InProgress(this.progress, progressStartMarker, progressEndMarker)
- is GestureState.Finished -> GestureUiState.Finished(successAnimation)
- GestureState.Error -> GestureUiState.Error
- }
-}
-
-fun GestureUiState.toTutorialActionState(previousState: TutorialActionState): TutorialActionState {
- return when (this) {
- NotStarted -> TutorialActionState.NotStarted
- is GestureUiState.InProgress -> {
- val inProgress =
- TutorialActionState.InProgress(
- progress = progress,
- startMarker = progressStartMarker,
- endMarker = progressEndMarker,
- )
- if (
- previousState is TutorialActionState.InProgressAfterError ||
- previousState is TutorialActionState.Error
- ) {
- return TutorialActionState.InProgressAfterError(inProgress)
- } else {
- return inProgress
- }
- }
- is Finished -> TutorialActionState.Finished(successAnimation)
- GestureUiState.Error -> TutorialActionState.Error
- }
-}
-
@Composable
fun GestureTutorialScreen(
screenConfig: TutorialScreenConfig,
- gestureUiStateFlow: Flow<GestureUiState>,
+ tutorialStateFlow: Flow<TutorialActionState>,
motionEventConsumer: (MotionEvent) -> Boolean,
easterEggTriggeredFlow: Flow<Boolean>,
onEasterEggFinished: () -> Unit,
@@ -106,25 +49,21 @@ fun GestureTutorialScreen(
) {
BackHandler(onBack = onBack)
val easterEggTriggered by easterEggTriggeredFlow.collectAsStateWithLifecycle(false)
- val gestureState by gestureUiStateFlow.collectAsStateWithLifecycle(NotStarted)
+ val tutorialState by tutorialStateFlow.collectAsStateWithLifecycle(NotStarted)
TouchpadGesturesHandlingBox(
motionEventConsumer,
- gestureState,
+ tutorialState,
easterEggTriggered,
onEasterEggFinished,
) {
- var lastState: TutorialActionState by remember {
- mutableStateOf(TutorialActionState.NotStarted)
- }
- lastState = gestureState.toTutorialActionState(lastState)
- ActionTutorialContent(lastState, onDoneButtonClicked, screenConfig)
+ ActionTutorialContent(tutorialState, onDoneButtonClicked, screenConfig)
}
}
@Composable
private fun TouchpadGesturesHandlingBox(
motionEventConsumer: (MotionEvent) -> Boolean,
- gestureState: GestureUiState,
+ tutorialState: TutorialActionState,
easterEggTriggered: Boolean,
onEasterEggFinished: () -> Unit,
modifier: Modifier = Modifier,
@@ -150,7 +89,7 @@ private fun TouchpadGesturesHandlingBox(
.pointerInteropFilter(
onTouchEvent = { event ->
// FINISHED is the final state so we don't need to process touches anymore
- if (gestureState is Finished) {
+ if (tutorialState is TutorialActionState.Finished) {
false
} else {
motionEventConsumer(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
index 4f1f40dc4c05..4acdb6070200 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
@@ -49,7 +49,7 @@ fun HomeGestureTutorialScreen(
)
GestureTutorialScreen(
screenConfig = screenConfig,
- gestureUiStateFlow = viewModel.gestureUiState,
+ tutorialStateFlow = viewModel.tutorialState,
motionEventConsumer = {
easterEggGestureViewModel.accept(it)
viewModel.handleEvent(it)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
index 6c9e26c4b7ea..8dd53a7fb815 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
@@ -50,7 +50,7 @@ fun RecentAppsGestureTutorialScreen(
)
GestureTutorialScreen(
screenConfig = screenConfig,
- gestureUiStateFlow = viewModel.gestureUiState,
+ tutorialStateFlow = viewModel.tutorialState,
motionEventConsumer = {
easterEggGestureViewModel.accept(it)
viewModel.handleEvent(it)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt
index 8e53669a7841..7a3d4d1ba88a 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt
@@ -17,12 +17,12 @@
package com.android.systemui.touchpad.tutorial.ui.viewmodel
import android.view.MotionEvent
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted
import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent
import com.android.systemui.util.kotlin.pairwiseBy
import kotlinx.coroutines.flow.Flow
@@ -30,21 +30,26 @@ import kotlinx.coroutines.flow.Flow
class BackGestureScreenViewModel(val gestureRecognizer: GestureRecognizerAdapter) :
TouchpadTutorialScreenViewModel {
- override val gestureUiState: Flow<GestureUiState> =
- gestureRecognizer.gestureState.pairwiseBy(GestureState.NotStarted) { previous, current ->
- toGestureUiState(current, previous)
- }
+ override val tutorialState: Flow<TutorialActionState> =
+ gestureRecognizer.gestureState
+ .pairwiseBy(NotStarted) { previous, current ->
+ current to toAnimationProperties(current, previous)
+ }
+ .mapToTutorialState()
override fun handleEvent(event: MotionEvent): Boolean {
return gestureRecognizer.handleTouchpadMotionEvent(event)
}
- private fun toGestureUiState(current: GestureState, previous: GestureState): GestureUiState {
+ private fun toAnimationProperties(
+ current: GestureState,
+ previous: GestureState,
+ ): TutorialAnimationProperties {
val (startMarker, endMarker) =
if (current is InProgress && current.direction == GestureDirection.LEFT) {
"gesture to L" to "end progress L"
} else "gesture to R" to "end progress R"
- return current.toGestureUiState(
+ return TutorialAnimationProperties(
progressStartMarker = startMarker,
progressEndMarker = endMarker,
successAnimation = successAnimation(previous),
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt
index 9d6f568fa1b1..c75d44f01e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt
@@ -17,9 +17,8 @@
package com.android.systemui.touchpad.tutorial.ui.viewmodel
import android.view.MotionEvent
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@@ -27,14 +26,17 @@ import kotlinx.coroutines.flow.map
class HomeGestureScreenViewModel(private val gestureRecognizer: GestureRecognizerAdapter) :
TouchpadTutorialScreenViewModel {
- override val gestureUiState: Flow<GestureUiState> =
- gestureRecognizer.gestureState.map {
- it.toGestureUiState(
- progressStartMarker = "drag with gesture",
- progressEndMarker = "release playback realtime",
- successAnimation = R.raw.trackpad_home_success,
- )
- }
+ override val tutorialState: Flow<TutorialActionState> =
+ gestureRecognizer.gestureState
+ .map {
+ it to
+ TutorialAnimationProperties(
+ progressStartMarker = "drag with gesture",
+ progressEndMarker = "release playback realtime",
+ successAnimation = R.raw.trackpad_home_success,
+ )
+ }
+ .mapToTutorialState()
override fun handleEvent(event: MotionEvent): Boolean {
return gestureRecognizer.handleTouchpadMotionEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt
index 97528583277f..9fab5f3641a4 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt
@@ -17,9 +17,8 @@
package com.android.systemui.touchpad.tutorial.ui.viewmodel
import android.view.MotionEvent
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
-import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@@ -27,14 +26,17 @@ import kotlinx.coroutines.flow.map
class RecentAppsGestureScreenViewModel(private val gestureRecognizer: GestureRecognizerAdapter) :
TouchpadTutorialScreenViewModel {
- override val gestureUiState: Flow<GestureUiState> =
- gestureRecognizer.gestureState.map {
- it.toGestureUiState(
- progressStartMarker = "drag with gesture",
- progressEndMarker = "onPause",
- successAnimation = R.raw.trackpad_recent_apps_success,
- )
- }
+ override val tutorialState: Flow<TutorialActionState> =
+ gestureRecognizer.gestureState
+ .map {
+ it to
+ TutorialAnimationProperties(
+ progressStartMarker = "drag with gesture",
+ progressEndMarker = "onPause",
+ successAnimation = R.raw.trackpad_recent_apps_success,
+ )
+ }
+ .mapToTutorialState()
override fun handleEvent(event: MotionEvent): Boolean {
return gestureRecognizer.handleTouchpadMotionEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt
index 31e953d6643c..3b6e3c76cdeb 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt
@@ -17,11 +17,62 @@
package com.android.systemui.touchpad.tutorial.ui.viewmodel
import android.view.MotionEvent
-import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import androidx.annotation.RawRes
+import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
interface TouchpadTutorialScreenViewModel {
- val gestureUiState: Flow<GestureUiState>
+ val tutorialState: Flow<TutorialActionState>
fun handleEvent(event: MotionEvent): Boolean
}
+
+data class TutorialAnimationProperties(
+ val progressStartMarker: String,
+ val progressEndMarker: String,
+ @RawRes val successAnimation: Int,
+)
+
+fun Flow<Pair<GestureState, TutorialAnimationProperties>>.mapToTutorialState():
+ Flow<TutorialActionState> {
+ return flow<TutorialActionState> {
+ var lastState: TutorialActionState = TutorialActionState.NotStarted
+ collect { (gestureState, animationProperties) ->
+ val newState = gestureState.toTutorialActionState(animationProperties, lastState)
+ lastState = newState
+ emit(newState)
+ }
+ }
+}
+
+fun GestureState.toTutorialActionState(
+ properties: TutorialAnimationProperties,
+ previousState: TutorialActionState,
+): TutorialActionState {
+ return when (this) {
+ NotStarted -> TutorialActionState.NotStarted
+ is InProgress -> {
+ val inProgress =
+ TutorialActionState.InProgress(
+ progress = progress,
+ startMarker = properties.progressStartMarker,
+ endMarker = properties.progressEndMarker,
+ )
+ if (
+ previousState is TutorialActionState.InProgressAfterError ||
+ previousState is TutorialActionState.Error
+ ) {
+ TutorialActionState.InProgressAfterError(inProgress)
+ } else {
+ inProgress
+ }
+ }
+ is Finished -> TutorialActionState.Finished(properties.successAnimation)
+ GestureState.Error -> TutorialActionState.Error
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
index 65970978b4ec..7d3966b98782 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
@@ -17,8 +17,9 @@ package com.android.systemui.unfold
import android.content.Context
import android.hardware.devicestate.DeviceStateManager
-import android.os.Trace
import com.android.app.tracing.TraceStateLogger
+import com.android.app.tracing.coroutines.TrackTracer
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -29,7 +30,6 @@ import com.android.systemui.util.Utils.isDeviceFoldable
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.plus
/**
@@ -45,7 +45,7 @@ constructor(
@Application applicationScope: CoroutineScope,
@Background private val coroutineContext: CoroutineContext,
private val deviceStateRepository: DeviceStateRepository,
- private val deviceStateManager: DeviceStateManager
+ private val deviceStateManager: DeviceStateManager,
) : CoreStartable {
private val isFoldable: Boolean = isDeviceFoldable(context.resources, deviceStateManager)
@@ -61,7 +61,7 @@ constructor(
bgScope.launch {
foldStateRepository.hingeAngle.collect {
- Trace.traceCounter(Trace.TRACE_TAG_APP, "hingeAngle", it.toInt())
+ TrackTracer.instantForGroup("unfold", "hingeAngle", it.toInt())
}
}
bgScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt
index fa1088426351..3b0c8a6b46f8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/VolumeDialogCallbacksInteractor.kt
@@ -46,7 +46,7 @@ class VolumeDialogCallbacksInteractor
constructor(
private val volumeDialogController: VolumeDialogController,
@VolumeDialogPlugin private val coroutineScope: CoroutineScope,
- @Background private val bgHandler: Handler,
+ @Background private val bgHandler: Handler?,
) {
@SuppressLint("SharedFlowCreation") // event-bus needed
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
index 88af210b6a36..940c79c78d76 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
@@ -19,7 +19,6 @@ package com.android.systemui.volume.dialog.sliders.dagger
import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogOverscrollViewBinder
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderHapticsViewBinder
-import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderTouchesViewBinder
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderViewBinder
import dagger.BindsInstance
import dagger.Subcomponent
@@ -34,8 +33,6 @@ interface VolumeDialogSliderComponent {
fun sliderViewBinder(): VolumeDialogSliderViewBinder
- fun sliderTouchesViewBinder(): VolumeDialogSliderTouchesViewBinder
-
fun sliderHapticsViewBinder(): VolumeDialogSliderHapticsViewBinder
fun overscrollViewBinder(): VolumeDialogOverscrollViewBinder
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderTouchesViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderTouchesViewBinder.kt
deleted file mode 100644
index 4ecac7a81893..000000000000
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderTouchesViewBinder.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2024 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.dialog.sliders.ui
-
-import android.annotation.SuppressLint
-import android.view.View
-import com.android.systemui.res.R
-import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
-import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderInputEventsViewModel
-import com.google.android.material.slider.Slider
-import javax.inject.Inject
-
-@VolumeDialogSliderScope
-class VolumeDialogSliderTouchesViewBinder
-@Inject
-constructor(private val viewModel: VolumeDialogSliderInputEventsViewModel) {
-
- @SuppressLint("ClickableViewAccessibility")
- fun bind(view: View) {
- with(view.requireViewById<Slider>(R.id.volume_dialog_slider)) {
- setOnTouchListener { _, event ->
- viewModel.onTouchEvent(event)
- false
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
index 67ffb0602860..ccd16ac5a331 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
@@ -23,6 +23,7 @@ import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
import com.android.systemui.res.R
import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
+import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderInputEventsViewModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderStateModel
import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderViewModel
import com.google.android.material.slider.Slider
@@ -35,7 +36,10 @@ import kotlinx.coroutines.flow.onEach
@VolumeDialogSliderScope
class VolumeDialogSliderViewBinder
@Inject
-constructor(private val viewModel: VolumeDialogSliderViewModel) {
+constructor(
+ private val viewModel: VolumeDialogSliderViewModel,
+ private val inputViewModel: VolumeDialogSliderInputEventsViewModel,
+) {
private val sliderValueProperty =
object : FloatPropertyCompat<Slider>("value") {
@@ -51,12 +55,16 @@ constructor(private val viewModel: VolumeDialogSliderViewModel) {
dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
}
+ @SuppressLint("ClickableViewAccessibility")
fun CoroutineScope.bind(view: View) {
var isInitialUpdate = true
val sliderView: Slider = view.requireViewById(R.id.volume_dialog_slider)
val animation = SpringAnimation(sliderView, sliderValueProperty)
animation.spring = springForce
-
+ sliderView.setOnTouchListener { _, event ->
+ inputViewModel.onTouchEvent(event)
+ false
+ }
sliderView.addOnChangeListener { _, value, fromUser ->
viewModel.setStreamVolume(value.roundToInt(), fromUser)
}
@@ -82,7 +90,7 @@ constructor(private val viewModel: VolumeDialogSliderViewModel) {
// coerce the current value to the new value range before animating it. This prevents
// animating from the value that is outside of current [valueFrom, valueTo].
value = value.coerceIn(valueFrom, valueTo)
- setTrackIconActiveStart(model.iconRes)
+ trackIconActiveStart = model.icon
if (isInitialUpdate) {
value = model.value
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
index f066b56e7de0..75d427acc05b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
@@ -71,7 +71,6 @@ constructor(private val viewModel: VolumeDialogSlidersViewModel) {
viewsToAnimate: Array<View>,
) {
with(component.sliderViewBinder()) { bind(sliderContainer) }
- with(component.sliderTouchesViewBinder()) { bind(sliderContainer) }
with(component.sliderHapticsViewBinder()) { bind(sliderContainer) }
with(component.overscrollViewBinder()) { bind(sliderContainer, viewsToAnimate) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderIconProvider.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderIconProvider.kt
index 5c39b6f9359c..daf4c8275d20 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderIconProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderIconProvider.kt
@@ -16,13 +16,16 @@
package com.android.systemui.volume.dialog.sliders.ui.viewmodel
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.drawable.Drawable
import android.media.AudioManager
import androidx.annotation.DrawableRes
-import com.android.settingslib.notification.domain.interactor.NotificationsSoundPolicyInteractor
import com.android.settingslib.volume.domain.interactor.AudioVolumeInteractor
import com.android.settingslib.volume.shared.model.AudioStream
import com.android.settingslib.volume.shared.model.RingerMode
import com.android.systemui.res.R
+import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -31,11 +34,12 @@ import kotlinx.coroutines.flow.flowOf
class VolumeDialogSliderIconProvider
@Inject
constructor(
- private val notificationsSoundPolicyInteractor: NotificationsSoundPolicyInteractor,
+ private val context: Context,
+ private val zenModeInteractor: ZenModeInteractor,
private val audioVolumeInteractor: AudioVolumeInteractor,
) {
- @DrawableRes
+ @SuppressLint("UseCompatLoadingForDrawables")
fun getStreamIcon(
stream: Int,
level: Int,
@@ -43,54 +47,71 @@ constructor(
levelMax: Int,
isMuted: Boolean,
isRoutedToBluetooth: Boolean,
- ): Flow<Int> {
+ ): Flow<Drawable> {
return combine(
- notificationsSoundPolicyInteractor.isZenMuted(AudioStream(stream)),
+ zenModeInteractor.activeModesBlockingStream(AudioStream(stream)),
ringerModeForStream(stream),
- ) { isZenMuted, ringerMode ->
- val isStreamOffline = level == 0 || isMuted
- if (isZenMuted) {
- // TODO(b/372466264) use icon for the corresponding zenmode
- return@combine com.android.internal.R.drawable.ic_qs_dnd
- }
- when (ringerMode?.value) {
- AudioManager.RINGER_MODE_VIBRATE ->
- return@combine R.drawable.ic_volume_ringer_vibrate
- AudioManager.RINGER_MODE_SILENT -> return@combine R.drawable.ic_ring_volume_off
- }
- if (isRoutedToBluetooth) {
- return@combine if (stream == AudioManager.STREAM_VOICE_CALL) {
- R.drawable.ic_volume_bt_sco
- } else {
- if (isStreamOffline) {
- R.drawable.ic_volume_media_bt_mute
- } else {
- R.drawable.ic_volume_media_bt
- }
- }
+ ) { activeModesBlockingStream, ringerMode ->
+ if (activeModesBlockingStream.mainMode?.icon != null) {
+ return@combine activeModesBlockingStream.mainMode.icon.drawable
+ } else {
+ context.getDrawable(
+ getIconRes(
+ stream,
+ level,
+ levelMin,
+ levelMax,
+ isMuted,
+ isRoutedToBluetooth,
+ ringerMode,
+ )
+ )!!
}
+ }
+ }
- return@combine if (isStreamOffline) {
- getMutedIconForStream(stream) ?: getIconForStream(stream)
+ @DrawableRes
+ private fun getIconRes(
+ stream: Int,
+ level: Int,
+ levelMin: Int,
+ levelMax: Int,
+ isMuted: Boolean,
+ isRoutedToBluetooth: Boolean,
+ ringerMode: RingerMode?,
+ ): Int {
+ val isStreamOffline = level == 0 || isMuted
+ when (ringerMode?.value) {
+ AudioManager.RINGER_MODE_VIBRATE -> return R.drawable.ic_volume_ringer_vibrate
+ AudioManager.RINGER_MODE_SILENT -> return R.drawable.ic_ring_volume_off
+ }
+ if (isRoutedToBluetooth) {
+ return if (stream == AudioManager.STREAM_VOICE_CALL) {
+ R.drawable.ic_volume_bt_sco
} else {
- if (level < (levelMax + levelMin) / 2) {
- // This icon is different on TV
- R.drawable.ic_volume_media_low
+ if (isStreamOffline) {
+ R.drawable.ic_volume_media_bt_mute
} else {
- getIconForStream(stream)
+ R.drawable.ic_volume_media_bt
}
}
}
- }
- @DrawableRes
- private fun getMutedIconForStream(stream: Int): Int? {
- return when (stream) {
- AudioManager.STREAM_MUSIC -> R.drawable.ic_volume_media_mute
- AudioManager.STREAM_NOTIFICATION -> R.drawable.ic_volume_ringer_mute
- AudioManager.STREAM_ALARM -> R.drawable.ic_volume_alarm_mute
- AudioManager.STREAM_SYSTEM -> R.drawable.ic_volume_system_mute
- else -> null
+ return if (isStreamOffline) {
+ when (stream) {
+ AudioManager.STREAM_MUSIC -> R.drawable.ic_volume_media_mute
+ AudioManager.STREAM_NOTIFICATION -> R.drawable.ic_volume_ringer_mute
+ AudioManager.STREAM_ALARM -> R.drawable.ic_volume_alarm_mute
+ AudioManager.STREAM_SYSTEM -> R.drawable.ic_volume_system_mute
+ else -> null
+ } ?: getIconForStream(stream)
+ } else {
+ if (level < (levelMax + levelMin) / 2) {
+ // This icon is different on TV
+ R.drawable.ic_volume_media_low
+ } else {
+ getIconForStream(stream)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
index 5750c049082f..8df9e788905c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderStateModel.kt
@@ -16,21 +16,21 @@
package com.android.systemui.volume.dialog.sliders.ui.viewmodel
-import androidx.annotation.DrawableRes
+import android.graphics.drawable.Drawable
import com.android.systemui.volume.dialog.shared.model.VolumeDialogStreamModel
data class VolumeDialogSliderStateModel(
val minValue: Float,
val maxValue: Float,
val value: Float,
- @DrawableRes val iconRes: Int,
+ val icon: Drawable,
)
-fun VolumeDialogStreamModel.toStateModel(@DrawableRes iconRes: Int): VolumeDialogSliderStateModel {
+fun VolumeDialogStreamModel.toStateModel(icon: Drawable): VolumeDialogSliderStateModel {
return VolumeDialogSliderStateModel(
minValue = levelMin.toFloat(),
value = level.toFloat(),
maxValue = levelMax.toFloat(),
- iconRes = iconRes,
+ icon = icon,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
index 6d8457be1014..06d9426fbe04 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogSliderViewModel.kt
@@ -66,7 +66,8 @@ constructor(
private val model: Flow<VolumeDialogStreamModel> =
interactor.slider
.filter {
- val lastVolumeUpdateTime = userVolumeUpdates.value?.timestampMillis ?: 0
+ val currentVolumeUpdate = userVolumeUpdates.value ?: return@filter true
+ val lastVolumeUpdateTime = currentVolumeUpdate.timestampMillis
getTimestampMillis() - lastVolumeUpdateTime > VOLUME_UPDATE_GRACE_PERIOD
}
.stateIn(coroutineScope, SharingStarted.Eagerly, null)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/VolumeDialogResources.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/VolumeDialogResources.kt
deleted file mode 100644
index e5cf62b91677..000000000000
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/VolumeDialogResources.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2024 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.dialog.ui
-
-import android.content.Context
-import android.content.res.Resources
-import com.android.systemui.dagger.qualifiers.UiBackground
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.onConfigChanged
-import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
-import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
-import javax.inject.Inject
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-
-/**
- * Provides cached resources [Flow]s that update when the configuration changes.
- *
- * Consume or use [kotlinx.coroutines.flow.first] to get the value.
- */
-@VolumeDialogScope
-class VolumeDialogResources
-@Inject
-constructor(
- @VolumeDialog private val coroutineScope: CoroutineScope,
- @UiBackground private val uiBackgroundContext: CoroutineContext,
- private val context: Context,
- private val configurationController: ConfigurationController,
-) {
-
- val dialogShowDurationMillis: Flow<Long> = configurationResource {
- getInteger(R.integer.config_dialogShowAnimationDurationMs).toLong()
- }
-
- val dialogHideDurationMillis: Flow<Long> = configurationResource {
- getInteger(R.integer.config_dialogHideAnimationDurationMs).toLong()
- }
-
- private fun <T> configurationResource(get: Resources.() -> T): Flow<T> =
- configurationController.onConfigChanged
- .map { context.resources.get() }
- .onStart { emit(context.resources.get()) }
- .flowOn(uiBackgroundContext)
- .stateIn(coroutineScope, SharingStarted.Eagerly, null)
- .filterNotNull()
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
index a3166a9978f4..1da2491c68b6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/binder/VolumeDialogViewBinder.kt
@@ -17,6 +17,7 @@
package com.android.systemui.volume.dialog.ui.binder
import android.app.Dialog
+import android.content.res.Resources
import android.graphics.Rect
import android.graphics.Region
import android.view.View
@@ -25,6 +26,7 @@ import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.InternalInsetsInfo
import androidx.constraintlayout.motion.widget.MotionLayout
import com.android.internal.view.RotationPolicy
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.util.children
import com.android.systemui.volume.SystemUIInterpolators
@@ -33,7 +35,6 @@ import com.android.systemui.volume.dialog.ringer.ui.binder.VolumeDialogRingerVie
import com.android.systemui.volume.dialog.settings.ui.binder.VolumeDialogSettingsButtonViewBinder
import com.android.systemui.volume.dialog.shared.model.VolumeDialogVisibilityModel
import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSlidersViewBinder
-import com.android.systemui.volume.dialog.ui.VolumeDialogResources
import com.android.systemui.volume.dialog.ui.utils.JankListenerFactory
import com.android.systemui.volume.dialog.ui.utils.suspendAnimate
import com.android.systemui.volume.dialog.ui.viewmodel.VolumeDialogViewModel
@@ -42,7 +43,6 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
@@ -56,7 +56,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
class VolumeDialogViewBinder
@Inject
constructor(
- private val volumeResources: VolumeDialogResources,
+ @Main resources: Resources,
private val viewModel: VolumeDialogViewModel,
private val jankListenerFactory: JankListenerFactory,
private val tracer: VolumeTracer,
@@ -65,6 +65,11 @@ constructor(
private val settingsButtonViewBinder: VolumeDialogSettingsButtonViewBinder,
) {
+ private val dialogShowAnimationDurationMs =
+ resources.getInteger(R.integer.config_dialogShowAnimationDurationMs).toLong()
+ private val dialogHideAnimationDurationMs =
+ resources.getInteger(R.integer.config_dialogHideAnimationDurationMs).toLong()
+
fun CoroutineScope.bind(dialog: Dialog) {
// Root view of the Volume Dialog.
val root: MotionLayout = dialog.requireViewById(R.id.volume_dialog_root)
@@ -99,12 +104,12 @@ constructor(
is VolumeDialogVisibilityModel.Visible -> {
tracer.traceVisibilityEnd(it)
calculateTranslationX(view)?.let(view::setTranslationX)
- view.animateShow(volumeResources.dialogShowDurationMillis.first())
+ view.animateShow(dialogShowAnimationDurationMs)
}
is VolumeDialogVisibilityModel.Dismissed -> {
tracer.traceVisibilityEnd(it)
view.animateHide(
- duration = volumeResources.dialogHideDurationMillis.first(),
+ duration = dialogHideAnimationDurationMs,
translationX = calculateTranslationX(view),
)
dialog.dismiss()
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
index b20dffb8ac33..7a6ede4c8b9c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/viewmodel/VolumeDialogViewModel.kt
@@ -44,9 +44,9 @@ class VolumeDialogViewModel
@Inject
constructor(
private val context: Context,
- private val dialogVisibilityInteractor: VolumeDialogVisibilityInteractor,
+ dialogVisibilityInteractor: VolumeDialogVisibilityInteractor,
volumeDialogSlidersInteractor: VolumeDialogSlidersInteractor,
- private val volumeDialogStateInteractor: VolumeDialogStateInteractor,
+ volumeDialogStateInteractor: VolumeDialogStateInteractor,
devicePostureController: DevicePostureController,
configurationController: ConfigurationController,
) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
index cec3d1eb86f0..5b8d9b045475 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
@@ -18,9 +18,6 @@ package com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel
import android.content.Context
import android.media.AudioManager
-import android.media.AudioManager.STREAM_ALARM
-import android.media.AudioManager.STREAM_MUSIC
-import android.media.AudioManager.STREAM_NOTIFICATION
import android.util.Log
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.logging.UiEventLogger
@@ -34,8 +31,6 @@ import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
import com.android.systemui.modes.shared.ModesUiIcons
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
-import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
-import com.android.systemui.util.kotlin.combine
import com.android.systemui.volume.panel.shared.VolumePanelLogger
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
import dagger.assisted.Assisted
@@ -43,12 +38,15 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlin.math.roundToInt
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -101,48 +99,16 @@ constructor(
)
override val slider: StateFlow<SliderState> =
- if (ModesUiIcons.isEnabled) {
- combine(
- audioVolumeInteractor.getAudioStream(audioStream),
- audioVolumeInteractor.canChangeVolume(audioStream),
- audioVolumeInteractor.ringerMode,
- zenModeInteractor.activeModesBlockingEverything,
- zenModeInteractor.activeModesBlockingAlarms,
- zenModeInteractor.activeModesBlockingMedia,
- ) {
- model,
- isEnabled,
- ringerMode,
- modesBlockingEverything,
- modesBlockingAlarms,
- modesBlockingMedia ->
- volumePanelLogger.onVolumeUpdateReceived(audioStream, model.volume)
- model.toState(
- isEnabled,
- ringerMode,
- getStreamDisabledMessage(
- modesBlockingEverything,
- modesBlockingAlarms,
- modesBlockingMedia,
- ),
- )
- }
- .stateIn(coroutineScope, SharingStarted.Eagerly, SliderState.Empty)
- } else {
- combine(
- audioVolumeInteractor.getAudioStream(audioStream),
- audioVolumeInteractor.canChangeVolume(audioStream),
- audioVolumeInteractor.ringerMode,
- ) { model, isEnabled, ringerMode ->
- volumePanelLogger.onVolumeUpdateReceived(audioStream, model.volume)
- model.toState(
- isEnabled,
- ringerMode,
- getStreamDisabledMessageWithoutModes(audioStream),
- )
- }
- .stateIn(coroutineScope, SharingStarted.Eagerly, SliderState.Empty)
- }
+ combine(
+ audioVolumeInteractor.getAudioStream(audioStream),
+ audioVolumeInteractor.canChangeVolume(audioStream),
+ audioVolumeInteractor.ringerMode,
+ streamDisabledMessage(),
+ ) { model, isEnabled, ringerMode, streamDisabledMessage ->
+ volumePanelLogger.onVolumeUpdateReceived(audioStream, model.volume)
+ model.toState(isEnabled, ringerMode, streamDisabledMessage)
+ }
+ .stateIn(coroutineScope, SharingStarted.Eagerly, SliderState.Empty)
init {
volumeChanges
@@ -229,40 +195,32 @@ constructor(
)
}
- private fun getStreamDisabledMessage(
- blockingEverything: ActiveZenModes,
- blockingAlarms: ActiveZenModes,
- blockingMedia: ActiveZenModes,
- ): String {
- // TODO: b/372213356 - Figure out the correct messages for VOICE_CALL and RING.
- // In fact, VOICE_CALL should not be affected by interruption filtering at all.
- return if (audioStream.value == STREAM_NOTIFICATION) {
- context.getString(R.string.stream_notification_unavailable)
- } else {
- val blockingModeName =
- when {
- blockingEverything.mainMode != null -> blockingEverything.mainMode.name
- audioStream.value == STREAM_ALARM -> blockingAlarms.mainMode?.name
- audioStream.value == STREAM_MUSIC -> blockingMedia.mainMode?.name
- else -> null
- }
-
- if (blockingModeName != null) {
- context.getString(R.string.stream_unavailable_by_modes, blockingModeName)
+ // TODO: b/372213356 - Figure out the correct messages for VOICE_CALL and RING.
+ // In fact, VOICE_CALL should not be affected by interruption filtering at all.
+ private fun streamDisabledMessage(): Flow<String> {
+ return if (ModesUiIcons.isEnabled) {
+ if (audioStream.value == AudioManager.STREAM_NOTIFICATION) {
+ flowOf(context.getString(R.string.stream_notification_unavailable))
} else {
- // Should not actually be visible, but as a catch-all.
- context.getString(R.string.stream_unavailable_by_unknown)
+ if (zenModeInteractor.canBeBlockedByZenMode(audioStream)) {
+ zenModeInteractor.activeModesBlockingStream(audioStream).map { blockingZenModes
+ ->
+ blockingZenModes.mainMode?.name?.let {
+ context.getString(R.string.stream_unavailable_by_modes, it)
+ } ?: context.getString(R.string.stream_unavailable_by_unknown)
+ }
+ } else {
+ flowOf(context.getString(R.string.stream_unavailable_by_unknown))
+ }
}
- }
- }
-
- private fun getStreamDisabledMessageWithoutModes(audioStream: AudioStream): String {
- // TODO: b/372213356 - Figure out the correct messages for VOICE_CALL and RING.
- // In fact, VOICE_CALL should not be affected by interruption filtering at all.
- return if (audioStream.value == STREAM_NOTIFICATION) {
- context.getString(R.string.stream_notification_unavailable)
} else {
- context.getString(R.string.stream_alarm_unavailable)
+ flowOf(
+ if (audioStream.value == AudioManager.STREAM_NOTIFICATION) {
+ context.getString(R.string.stream_notification_unavailable)
+ } else {
+ context.getString(R.string.stream_alarm_unavailable)
+ }
+ )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
index 2c37f510a45c..77bac59b9dcd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -15,7 +15,6 @@
*/
package com.android.systemui.statusbar.notification.collection.coordinator
-import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,15 +32,14 @@ import com.android.systemui.statusbar.notification.collection.render.NotifStackC
import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
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_SILENT
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController
+import com.android.systemui.util.mockito.withArgCaptor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
@@ -82,9 +80,9 @@ class StackCoordinatorTest : SysuiTestCase() {
sensitiveNotificationProtectionController,
)
coordinator.attach(pipeline)
- val captor = argumentCaptor<OnAfterRenderListListener>()
- verify(pipeline).addOnAfterRenderListListener(captor.capture())
- afterRenderListListener = captor.lastValue
+ afterRenderListListener = withArgCaptor {
+ verify(pipeline).addOnAfterRenderListListener(capture())
+ }
}
@Test
@@ -94,93 +92,9 @@ class StackCoordinatorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
- fun testSetRenderedListOnInteractor_footerFlagOn() {
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
- verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
fun testSetNotificationStats_clearableAlerting() {
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
- verify(stackController)
- .setNotifStats(
- NotifStats(
- 1,
- hasNonClearableAlertingNotifs = false,
- hasClearableAlertingNotifs = true,
- hasNonClearableSilentNotifs = false,
- hasClearableSilentNotifs = false,
- )
- )
- verifyNoMoreInteractions(activeNotificationsInteractor)
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
- fun testSetNotificationStats_isSensitiveStateActive_nonClearableAlerting() {
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
- whenever(section.bucket).thenReturn(BUCKET_ALERTING)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
- verify(stackController)
- .setNotifStats(
- NotifStats(
- 1,
- hasNonClearableAlertingNotifs = true,
- hasClearableAlertingNotifs = false,
- hasNonClearableSilentNotifs = false,
- hasClearableSilentNotifs = false,
- )
- )
- verifyNoMoreInteractions(activeNotificationsInteractor)
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- fun testSetNotificationStats_clearableSilent() {
- whenever(section.bucket).thenReturn(BUCKET_SILENT)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
- verify(stackController)
- .setNotifStats(
- NotifStats(
- 1,
- hasNonClearableAlertingNotifs = false,
- hasClearableAlertingNotifs = false,
- hasNonClearableSilentNotifs = false,
- hasClearableSilentNotifs = true,
- )
- )
- verifyNoMoreInteractions(activeNotificationsInteractor)
- }
-
- @Test
- @DisableFlags(FooterViewRefactor.FLAG_NAME)
- @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
- fun testSetNotificationStats_isSensitiveStateActive_nonClearableSilent() {
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
- whenever(section.bucket).thenReturn(BUCKET_SILENT)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
- verify(stackController)
- .setNotifStats(
- NotifStats(
- 1,
- hasNonClearableAlertingNotifs = false,
- hasClearableAlertingNotifs = false,
- hasNonClearableSilentNotifs = true,
- hasClearableSilentNotifs = false,
- )
- )
- verifyNoMoreInteractions(activeNotificationsInteractor)
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
- fun testSetNotificationStats_footerFlagOn_clearableAlerting() {
- whenever(section.bucket).thenReturn(BUCKET_ALERTING)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
@@ -195,12 +109,8 @@ class StackCoordinatorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(
- FooterViewRefactor.FLAG_NAME,
- FLAG_SCREENSHARE_NOTIFICATION_HIDING,
- FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX,
- )
- fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableAlerting() {
+ @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+ fun testSetNotificationStats_isSensitiveStateActive_nonClearableAlerting() {
whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
@@ -218,8 +128,7 @@ class StackCoordinatorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
- fun testSetNotificationStats_footerFlagOn_clearableSilent() {
+ fun testSetNotificationStats_clearableSilent() {
whenever(section.bucket).thenReturn(BUCKET_SILENT)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
verify(activeNotificationsInteractor)
@@ -236,12 +145,8 @@ class StackCoordinatorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(
- FooterViewRefactor.FLAG_NAME,
- FLAG_SCREENSHARE_NOTIFICATION_HIDING,
- FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX,
- )
- fun testSetNotificationStats_footerFlagOn_isSensitiveStateActive_nonClearableSilent() {
+ @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING, FLAG_SCREENSHARE_NOTIFICATION_HIDING_BUG_FIX)
+ fun testSetNotificationStats_isSensitiveStateActive_nonClearableSilent() {
whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
whenever(section.bucket).thenReturn(BUCKET_SILENT)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
@@ -259,8 +164,7 @@ class StackCoordinatorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
- fun testSetNotificationStats_footerFlagOn_nonClearableRedacted() {
+ fun testSetNotificationStats_nonClearableRedacted() {
entry.setSensitive(true, true)
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
index 25138fd0ff83..57a12df0cfee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
@@ -38,6 +38,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any
+import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
@@ -123,7 +124,8 @@ class IconManagerTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
- fun testCreateIcons_chipNotifIconFlagEnabled_statusBarChipIconIsNull() {
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun testCreateIcons_chipNotifIconFlagEnabled_cdFlagDisabled_statusBarChipIconIsNotNull() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
entry?.let { iconManager.createIcons(it) }
@@ -133,6 +135,17 @@ class IconManagerTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun testCreateIcons_chipNotifIconFlagEnabled_cdFlagEnabled_statusBarChipIconIsNull() {
+ val entry =
+ notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
+ entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
+
+ assertThat(entry?.icons?.statusBarChipIcon).isNull()
+ }
+
+ @Test
fun testCreateIcons_importantConversation_shortcutIcon() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = true)
@@ -158,7 +171,7 @@ class IconManagerTest : SysuiTestCase() {
notificationEntry(
hasShortcut = false,
hasMessageSenderIcon = false,
- hasLargeIcon = true
+ hasLargeIcon = true,
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
@@ -172,7 +185,7 @@ class IconManagerTest : SysuiTestCase() {
notificationEntry(
hasShortcut = false,
hasMessageSenderIcon = false,
- hasLargeIcon = false
+ hasLargeIcon = false,
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
@@ -187,7 +200,7 @@ class IconManagerTest : SysuiTestCase() {
hasShortcut = true,
hasMessageSenderIcon = true,
useMessagingStyle = false,
- hasLargeIcon = true
+ hasLargeIcon = true,
)
entry?.channel?.isImportantConversation = true
entry?.let { iconManager.createIcons(it) }
@@ -205,7 +218,8 @@ class IconManagerTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
- fun testCreateIcons_sensitiveImportantConversation() {
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun testCreateIcons_cdFlagDisabled_sensitiveImportantConversation() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
entry?.setSensitive(true, true)
@@ -219,8 +233,24 @@ class IconManagerTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun testCreateIcons_cdFlagEnabled_sensitiveImportantConversation() {
+ val entry =
+ notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
+ entry?.setSensitive(true, true)
+ entry?.channel?.isImportantConversation = true
+ entry?.let { iconManager.createIcons(it) }
+ testScope.runCurrent()
+ assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
+ assertThat(entry?.icons?.statusBarChipIcon).isNull()
+ assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
+ assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
+ }
+
+ @Test
@EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON)
- fun testUpdateIcons_sensitiveImportantConversation() {
+ @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+ fun testUpdateIcons_cdFlagDisabled_sensitiveImportantConversation() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
entry?.setSensitive(true, true)
@@ -236,6 +266,23 @@ class IconManagerTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON, StatusBarConnectedDisplays.FLAG_NAME)
+ fun testUpdateIcons_cdFlagEnabled_sensitiveImportantConversation() {
+ val entry =
+ notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
+ entry?.setSensitive(true, true)
+ entry?.channel?.isImportantConversation = true
+ entry?.let { iconManager.createIcons(it) }
+ // Updating the icons after creation shouldn't break anything
+ entry?.let { iconManager.updateIcons(it) }
+ testScope.runCurrent()
+ assertThat(entry?.icons?.statusBarIcon?.sourceIcon).isEqualTo(shortcutIc)
+ assertThat(entry?.icons?.statusBarChipIcon).isNull()
+ assertThat(entry?.icons?.shelfIcon?.sourceIcon).isEqualTo(smallIc)
+ assertThat(entry?.icons?.aodIcon?.sourceIcon).isEqualTo(smallIc)
+ }
+
+ @Test
fun testUpdateIcons_sensitivityChange() {
val entry =
notificationEntry(hasShortcut = true, hasMessageSenderIcon = true, hasLargeIcon = false)
@@ -254,7 +301,7 @@ class IconManagerTest : SysuiTestCase() {
hasShortcut: Boolean,
hasMessageSenderIcon: Boolean,
useMessagingStyle: Boolean = true,
- hasLargeIcon: Boolean
+ hasLargeIcon: Boolean,
): NotificationEntry? {
val n =
Notification.Builder(mContext, "id")
@@ -270,7 +317,7 @@ class IconManagerTest : SysuiTestCase() {
SystemClock.currentThreadTimeMillis(),
Person.Builder()
.setIcon(if (hasMessageSenderIcon) messageIc else null)
- .build()
+ .build(),
)
)
if (useMessagingStyle) {
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 e1a891662889..3763282cdebc 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
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.stack;
-import static android.view.View.GONE;
import static android.view.WindowInsets.Type.ime;
import static com.android.systemui.flags.SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag;
@@ -28,17 +27,14 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
-import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -64,7 +60,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
-import android.widget.TextView;
import androidx.test.filters.SmallTest;
@@ -92,8 +87,6 @@ import com.android.systemui.statusbar.notification.collection.render.GroupExpans
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix;
import com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeView;
-import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
-import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter;
import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
import com.android.systemui.statusbar.notification.headsup.AvalancheController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -603,158 +596,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void manageNotifications_visible() {
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- when(view.willBeGone()).thenReturn(true);
-
- mStackScroller.updateFooterView(true, false, true);
-
- verify(view).setVisible(eq(true), anyBoolean());
- verify(view).setClearAllButtonVisible(eq(false), anyBoolean());
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void clearAll_visible() {
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- when(view.willBeGone()).thenReturn(true);
-
- mStackScroller.updateFooterView(true, true, true);
-
- verify(view).setVisible(eq(true), anyBoolean());
- verify(view).setClearAllButtonVisible(eq(true), anyBoolean());
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testInflateFooterView() {
- mStackScroller.inflateFooterView();
- ArgumentCaptor<FooterView> captor = ArgumentCaptor.forClass(FooterView.class);
- verify(mStackScroller).setFooterView(captor.capture());
-
- assertNotNull(captor.getValue().findViewById(R.id.manage_text));
- assertNotNull(captor.getValue().findViewById(R.id.dismiss_text));
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testUpdateFooter_noNotifications() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(false, false, true);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- @DisableSceneContainer
- public void testUpdateFooter_remoteInput() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- mStackScroller.setIsRemoteInputActive(true);
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(true);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(false, true, true);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testUpdateFooter_withoutNotifications() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(false);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(false, false, true);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- @DisableSceneContainer
- public void testUpdateFooter_oneClearableNotification() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(true);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(true, true, true);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- @DisableSceneContainer
- public void testUpdateFooter_withoutHistory() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- when(mStackScrollLayoutController.isHistoryEnabled()).thenReturn(false);
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(true);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(true, true, false);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void testUpdateFooter_oneClearableNotification_beforeUserSetup() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(false);
-
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(true);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(false, true, true);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- @DisableSceneContainer
- public void testUpdateFooter_oneNonClearableNotification() {
- setBarStateForTest(StatusBarState.SHADE);
- mStackScroller.setCurrentUserSetup(true);
-
- when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
- when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
- .thenReturn(false);
- when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
-
- FooterView view = mock(FooterView.class);
- mStackScroller.setFooterView(view);
- mStackScroller.updateFooter();
- verify(mStackScroller, atLeastOnce()).updateFooterView(true, false, true);
- }
-
- @Test
public void testFooterPosition_atEnd() {
// add footer
FooterView view = mock(FooterView.class);
@@ -772,19 +613,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME,
- ModesEmptyShadeFix.FLAG_NAME,
- NotifRedesignFooter.FLAG_NAME})
- public void testReInflatesFooterViews() {
- when(mEmptyShadeView.getTextResource()).thenReturn(R.string.empty_shade_text);
- clearInvocations(mStackScroller);
- mStackScroller.reinflateViews();
- verify(mStackScroller).setFooterView(any());
- verify(mStackScroller).setEmptyShadeView(any());
- }
-
- @Test
- @EnableFlags(FooterViewRefactor.FLAG_NAME)
@DisableFlags(ModesEmptyShadeFix.FLAG_NAME)
public void testReInflatesEmptyShadeView() {
when(mEmptyShadeView.getTextResource()).thenReturn(R.string.empty_shade_text);
@@ -1231,31 +1059,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
@Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, NotifRedesignFooter.FLAG_NAME})
- public void hasFilteredOutSeenNotifs_updateFooter() {
- mStackScroller.setCurrentUserSetup(true);
-
- // add footer
- mStackScroller.inflateFooterView();
- TextView footerLabel =
- mStackScroller.mFooterView.requireViewById(R.id.unlock_prompt_footer);
-
- mStackScroller.setHasFilteredOutSeenNotifications(true);
- mStackScroller.updateFooter();
-
- assertThat(footerLabel.getVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- @DisableFlags({FooterViewRefactor.FLAG_NAME, ModesEmptyShadeFix.FLAG_NAME})
- public void hasFilteredOutSeenNotifs_updateEmptyShadeView() {
- mStackScroller.setHasFilteredOutSeenNotifications(true);
- mStackScroller.updateEmptyShadeView(true, false);
-
- verify(mEmptyShadeView).setFooterText(not(eq(0)));
- }
-
- @Test
@DisableSceneContainer
public void testWindowInsetAnimationProgress_updatesBottomInset() {
int imeInset = 100;
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
index 17093291e8b0..2a1877adc172 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogTransitionAnimator.kt
@@ -24,7 +24,6 @@ fun fakeDialogTransitionAnimator(
@Main mainExecutor: Executor,
isUnlocked: Boolean = true,
isShowingAlternateAuthOnUnlock: Boolean = false,
- isPredictiveBackQsDialogAnim: Boolean = false,
interactionJankMonitor: InteractionJankMonitor,
): DialogTransitionAnimator {
return DialogTransitionAnimator(
@@ -35,10 +34,6 @@ fun fakeDialogTransitionAnimator(
isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
),
interactionJankMonitor = interactionJankMonitor,
- featureFlags =
- object : AnimationFeatureFlags {
- override val isPredictiveBackQsDialogAnim = isPredictiveBackQsDialogAnim
- },
transitionAnimator = fakeTransitionAnimator(mainExecutor),
isForTesting = true,
)
@@ -50,6 +45,8 @@ private class FakeCallback(
private val isShowingAlternateAuthOnUnlock: Boolean = false,
) : DialogTransitionAnimator.Callback {
override fun isDreaming(): Boolean = isDreaming
+
override fun isUnlocked(): Boolean = isUnlocked
+
override fun isShowingAlternateAuthOnUnlock() = isShowingAlternateAuthOnUnlock
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
index 47991b3b9689..3df3ee983ecf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
@@ -154,6 +154,7 @@ val Kosmos.shortcutHelperCoreStartable by
shortcutHelperStateRepository,
activityStarter,
testScope,
+ customInputGesturesRepository
)
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index f15b8eec3f6b..cd46b38272c2 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -38,7 +38,7 @@ public class TouchState {
// Pointer-related constants
// This constant captures the current implementation detail that
// pointer IDs are between 0 and 31 inclusive (subject to change).
- // (See MAX_POINTER_ID in frameworks/base/include/ui/Input.h)
+ // (See MAX_POINTER_ID in frameworks/native/include/input/Input.h)
public static final int MAX_POINTER_COUNT = 32;
// Constant referring to the ids bits of all pointers.
public static final int ALL_POINTER_ID_BITS = 0xFFFFFFFF;
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 1f3b31692289..aeb2f5e9be84 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -176,7 +176,7 @@ public class VirtualDeviceManagerService extends SystemService {
public VirtualDeviceManagerService(Context context) {
super(context);
mImpl = new VirtualDeviceManagerImpl();
- mNativeImpl = Flags.enableNativeVdm() ? new VirtualDeviceManagerNativeImpl() : null;
+ mNativeImpl = new VirtualDeviceManagerNativeImpl();
mLocalService = new LocalService();
}
@@ -208,9 +208,7 @@ public class VirtualDeviceManagerService extends SystemService {
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public void onStart() {
publishBinderService(Context.VIRTUAL_DEVICE_SERVICE, mImpl);
- if (Flags.enableNativeVdm()) {
- publishBinderService(VIRTUAL_DEVICE_NATIVE_SERVICE, mNativeImpl);
- }
+ publishBinderService(VIRTUAL_DEVICE_NATIVE_SERVICE, mNativeImpl);
publishLocalService(VirtualDeviceManagerInternal.class, mLocalService);
ActivityTaskManagerInternal activityTaskManagerInternal = getLocalService(
ActivityTaskManagerInternal.class);
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 5d9db65fe2b2..d89db8d5581b 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -312,6 +312,13 @@ public final class DeviceStateManagerService extends SystemService {
mProcessObserver);
}
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_SYSTEM_SERVICES_READY) {
+ mDeviceStatePolicy.getDeviceStateProvider().onSystemReady();
+ }
+ }
+
@VisibleForTesting
Handler getHandler() {
return mHandler;
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
index 8d07609cef30..8a8ebc2ffc21 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateProvider.java
@@ -91,6 +91,11 @@ public interface DeviceStateProvider extends Dumpable {
@interface SupportedStatesUpdatedReason {}
/**
+ * Called when the system boot phase advances to PHASE_SYSTEM_SERVICES_READY.
+ */
+ default void onSystemReady() {};
+
+ /**
* Registers a listener for changes in provider state.
* <p>
* It is <b>required</b> that
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index 34bb4155c943..3babc0ae065c 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -18,6 +18,7 @@ package com.android.server.media.quality;
import android.content.ContentValues;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.quality.AmbientBacklightSettings;
@@ -35,8 +36,13 @@ import android.media.quality.SoundProfileHandle;
import android.os.Binder;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
import com.android.server.SystemService;
@@ -45,9 +51,11 @@ import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -64,10 +72,13 @@ public class MediaQualityService extends SystemService {
private final MediaQualityDbHelper mMediaQualityDbHelper;
private final BiMap<Long, String> mPictureProfileTempIdMap;
private final BiMap<Long, String> mSoundProfileTempIdMap;
+ private final PackageManager mPackageManager;
+ private final SparseArray<UserState> mUserStates = new SparseArray<>();
public MediaQualityService(Context context) {
super(context);
mContext = context;
+ mPackageManager = mContext.getPackageManager();
mPictureProfileTempIdMap = new BiMap<>();
mSoundProfileTempIdMap = new BiMap<>();
mMediaQualityDbHelper = new MediaQualityDbHelper(mContext);
@@ -85,12 +96,20 @@ public class MediaQualityService extends SystemService {
@Override
public PictureProfile createPictureProfile(PictureProfile pp, UserHandle user) {
+ if ((pp.getPackageName() != null && !pp.getPackageName().isEmpty()
+ && !incomingPackageEqualsCallingUidPackage(pp.getPackageName()))
+ && !hasGlobalPictureQualityServicePermission()) {
+ notifyError(null, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
ContentValues values = getContentValues(null,
pp.getProfileType(),
pp.getName(),
- pp.getPackageName(),
+ pp.getPackageName() == null || pp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : pp.getPackageName(),
pp.getInputId(),
pp.getParameters());
@@ -104,9 +123,13 @@ public class MediaQualityService extends SystemService {
@Override
public void updatePictureProfile(String id, PictureProfile pp, UserHandle user) {
- Long intId = mPictureProfileTempIdMap.getKey(id);
+ Long dbId = mPictureProfileTempIdMap.getKey(id);
+ if (!hasPermissionToUpdatePictureProfile(dbId, pp)) {
+ notifyError(id, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
- ContentValues values = getContentValues(intId,
+ ContentValues values = getContentValues(dbId,
pp.getProfileType(),
pp.getName(),
pp.getPackageName(),
@@ -118,27 +141,51 @@ public class MediaQualityService extends SystemService {
null, values);
}
+ private boolean hasPermissionToUpdatePictureProfile(Long dbId, PictureProfile toUpdate) {
+ PictureProfile fromDb = getPictureProfile(dbId);
+ return fromDb.getProfileType() == toUpdate.getProfileType()
+ && fromDb.getPackageName().equals(toUpdate.getPackageName())
+ && fromDb.getName().equals(toUpdate.getName())
+ && fromDb.getName().equals(getPackageOfCallingUid());
+ }
+
@Override
public void removePictureProfile(String id, UserHandle user) {
- Long intId = mPictureProfileTempIdMap.getKey(id);
- if (intId != null) {
+ Long dbId = mPictureProfileTempIdMap.getKey(id);
+
+ if (!hasPermissionToRemovePictureProfile(dbId)) {
+ notifyError(id, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+
+ if (dbId != null) {
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {Long.toString(intId)};
- db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, selection,
+ String[] selectionArgs = {Long.toString(dbId)};
+ int result = db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, selection,
selectionArgs);
- mPictureProfileTempIdMap.remove(intId);
+ if (result == 0) {
+ notifyError(id, PictureProfile.ERROR_INVALID_ARGUMENT,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+ mPictureProfileTempIdMap.remove(dbId);
}
}
+ private boolean hasPermissionToRemovePictureProfile(Long dbId) {
+ PictureProfile fromDb = getPictureProfile(dbId);
+ return fromDb.getName().equalsIgnoreCase(getPackageOfCallingUid());
+ }
+
@Override
public PictureProfile getPictureProfile(int type, String name, Bundle options,
UserHandle user) {
boolean includeParams =
options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
- + BaseParameters.PARAMETER_NAME + " = ?";
- String[] selectionArguments = {Integer.toString(type), name};
+ + BaseParameters.PARAMETER_NAME + " = ? AND "
+ + BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {Integer.toString(type), name, getPackageOfCallingUid()};
try (
Cursor cursor = getCursorAfterQuerying(
@@ -156,13 +203,42 @@ public class MediaQualityService extends SystemService {
return null;
}
cursor.moveToFirst();
- return getPictureProfileWithTempIdFromCursor(cursor);
+ return convertCursorToPictureProfileWithTempId(cursor);
+ }
+ }
+
+ private PictureProfile getPictureProfile(Long dbId) {
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArguments = {Long.toString(dbId)};
+
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(false), selection, selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%d"
+ + " in %s. Should only ever be 0 or 1.", count, dbId,
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToPictureProfileWithTempId(cursor);
}
}
@Override
public List<PictureProfile> getPictureProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ notifyError(null, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+
boolean includeParams =
options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
@@ -172,23 +248,31 @@ public class MediaQualityService extends SystemService {
}
@Override
- public List<PictureProfile> getAvailablePictureProfiles(Bundle options, UserHandle user) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
- if (packageNames != null && packageNames.length == 1 && !packageNames[0].isEmpty()) {
- return getPictureProfilesByPackage(packageNames[0], options, user);
+ public List<PictureProfile> getAvailablePictureProfiles(
+ Bundle options, UserHandle user) {
+ String packageName = getPackageOfCallingUid();
+ if (packageName != null) {
+ return getPictureProfilesByPackage(packageName, options, user);
}
return new ArrayList<>();
}
@Override
public boolean setDefaultPictureProfile(String profileId, UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ notifyError(profileId, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
// TODO: pass the profile ID to MediaQuality HAL when ready.
return false;
}
@Override
public List<String> getPictureProfilePackageNames(UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ notifyError(null, PictureProfile.ERROR_NO_PERMISSION,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
String [] column = {BaseParameters.PARAMETER_PACKAGE};
List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
null, null);
@@ -210,12 +294,19 @@ public class MediaQualityService extends SystemService {
@Override
public SoundProfile createSoundProfile(SoundProfile sp, UserHandle user) {
+ if ((sp.getPackageName() != null && !sp.getPackageName().isEmpty()
+ && !incomingPackageEqualsCallingUidPackage(sp.getPackageName()))
+ && !hasGlobalPictureQualityServicePermission()) {
+ //TODO: error handling
+ return null;
+ }
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
ContentValues values = getContentValues(null,
sp.getProfileType(),
sp.getName(),
- sp.getPackageName(),
+ sp.getPackageName() == null || sp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : sp.getPackageName(),
sp.getInputId(),
sp.getParameters());
@@ -229,9 +320,14 @@ public class MediaQualityService extends SystemService {
@Override
public void updateSoundProfile(String id, SoundProfile sp, UserHandle user) {
- Long intId = mSoundProfileTempIdMap.getKey(id);
+ Long dbId = mSoundProfileTempIdMap.getKey(id);
+
+ if (!hasPermissionToUpdateSoundProfile(dbId, sp)) {
+ //TODO: error handling
+ return;
+ }
- ContentValues values = getContentValues(intId,
+ ContentValues values = getContentValues(dbId,
sp.getProfileType(),
sp.getName(),
sp.getPackageName(),
@@ -242,27 +338,49 @@ public class MediaQualityService extends SystemService {
db.replace(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, null, values);
}
+ private boolean hasPermissionToUpdateSoundProfile(Long dbId, SoundProfile sp) {
+ SoundProfile fromDb = getSoundProfile(dbId);
+ return fromDb.getProfileType() == sp.getProfileType()
+ && fromDb.getPackageName().equals(sp.getPackageName())
+ && fromDb.getName().equals(sp.getName())
+ && fromDb.getName().equals(getPackageOfCallingUid());
+ }
+
@Override
public void removeSoundProfile(String id, UserHandle user) {
Long intId = mSoundProfileTempIdMap.getKey(id);
+ if (!hasPermissionToRemoveSoundProfile(intId)) {
+ //TODO: error handling
+ return;
+ }
+
if (intId != null) {
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
String selection = BaseParameters.PARAMETER_ID + " = ?";
String[] selectionArgs = {Long.toString(intId)};
- db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection,
+ int result = db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection,
selectionArgs);
+ if (result == 0) {
+ //TODO: error handling
+ }
mSoundProfileTempIdMap.remove(intId);
}
}
+ private boolean hasPermissionToRemoveSoundProfile(Long dbId) {
+ SoundProfile fromDb = getSoundProfile(dbId);
+ return fromDb.getName().equalsIgnoreCase(getPackageOfCallingUid());
+ }
+
@Override
public SoundProfile getSoundProfile(int type, String id, Bundle options,
UserHandle user) {
boolean includeParams =
options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_TYPE + " = ? AND "
- + BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArguments = {String.valueOf(type), id};
+ + BaseParameters.PARAMETER_ID + " = ? AND "
+ + BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {String.valueOf(type), id, getPackageOfCallingUid()};
try (
Cursor cursor = getCursorAfterQuerying(
@@ -280,13 +398,42 @@ public class MediaQualityService extends SystemService {
return null;
}
cursor.moveToFirst();
- return getSoundProfileWithTempIdFromCursor(cursor);
+ return convertCursorToSoundProfileWithTempId(cursor);
+ }
+ }
+
+ private SoundProfile getSoundProfile(Long dbId) {
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArguments = {Long.toString(dbId)};
+
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(false), selection, selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%s "
+ + "in %s. Should only ever be 0 or 1.", count, dbId,
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToSoundProfileWithTempId(cursor);
}
}
@Override
public List<SoundProfile> getSoundProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ return new ArrayList<>();
+ }
+
boolean includeParams =
options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
@@ -296,24 +443,30 @@ public class MediaQualityService extends SystemService {
}
@Override
- public List<SoundProfile> getAvailableSoundProfiles(
- Bundle options, UserHandle user) {
- String[] packageNames = mContext.getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
- if (packageNames != null && packageNames.length == 1 && !packageNames[0].isEmpty()) {
- return getSoundProfilesByPackage(packageNames[0], options, user);
+ public List<SoundProfile> getAvailableSoundProfiles(Bundle options, UserHandle user) {
+ String packageName = getPackageOfCallingUid();
+ if (packageName != null) {
+ return getSoundProfilesByPackage(packageName, options, user);
}
return new ArrayList<>();
}
@Override
public boolean setDefaultSoundProfile(String profileId, UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ return false;
+ }
// TODO: pass the profile ID to MediaQuality HAL when ready.
return false;
}
@Override
public List<String> getSoundProfilePackageNames(UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ return new ArrayList<>();
+ }
String [] column = {BaseParameters.PARAMETER_NAME};
List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
null, null);
@@ -323,6 +476,37 @@ public class MediaQualityService extends SystemService {
.collect(Collectors.toList());
}
+ private String getPackageOfCallingUid() {
+ String[] packageNames = mPackageManager.getPackagesForUid(
+ Binder.getCallingUid());
+ if (packageNames != null && packageNames.length == 1 && !packageNames[0].isEmpty()) {
+ return packageNames[0];
+ }
+ return null;
+ }
+
+ private boolean incomingPackageEqualsCallingUidPackage(String incomingPackage) {
+ return incomingPackage.equalsIgnoreCase(getPackageOfCallingUid());
+ }
+
+ private boolean hasGlobalPictureQualityServicePermission() {
+ return mPackageManager.checkPermission(android.Manifest.permission
+ .MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE,
+ mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ }
+
+ private boolean hasGlobalSoundQualityServicePermission() {
+ return mPackageManager.checkPermission(android.Manifest.permission
+ .MANAGE_GLOBAL_SOUND_QUALITY_SERVICE,
+ mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ }
+
+ private boolean hasReadColorZonesPermission() {
+ return mPackageManager.checkPermission(android.Manifest.permission
+ .READ_COLOR_ZONES,
+ mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ }
+
private void populateTempIdMap(BiMap<Long, String> map, Long id) {
if (id != null && map.getValue(id) == null) {
String uuid;
@@ -430,7 +614,7 @@ public class MediaQualityService extends SystemService {
return columns.toArray(new String[0]);
}
- private PictureProfile getPictureProfileWithTempIdFromCursor(Cursor cursor) {
+ private PictureProfile convertCursorToPictureProfileWithTempId(Cursor cursor) {
return new PictureProfile(
getTempId(mPictureProfileTempIdMap, cursor),
getType(cursor),
@@ -442,7 +626,7 @@ public class MediaQualityService extends SystemService {
);
}
- private SoundProfile getSoundProfileWithTempIdFromCursor(Cursor cursor) {
+ private SoundProfile convertCursorToSoundProfileWithTempId(Cursor cursor) {
return new SoundProfile(
getTempId(mSoundProfileTempIdMap, cursor),
getType(cursor),
@@ -502,7 +686,7 @@ public class MediaQualityService extends SystemService {
) {
List<PictureProfile> pictureProfiles = new ArrayList<>();
while (cursor.moveToNext()) {
- pictureProfiles.add(getPictureProfileWithTempIdFromCursor(cursor));
+ pictureProfiles.add(convertCursorToPictureProfileWithTempId(cursor));
}
return pictureProfiles;
}
@@ -517,30 +701,64 @@ public class MediaQualityService extends SystemService {
) {
List<SoundProfile> soundProfiles = new ArrayList<>();
while (cursor.moveToNext()) {
- soundProfiles.add(getSoundProfileWithTempIdFromCursor(cursor));
+ soundProfiles.add(convertCursorToSoundProfileWithTempId(cursor));
}
return soundProfiles;
}
}
+ private void notifyError(String profileId, int errorCode, int uid, int pid) {
+ UserState userState = getOrCreateUserStateLocked(UserHandle.USER_SYSTEM);
+ int n = userState.mCallbacks.beginBroadcast();
+
+ for (int i = 0; i < n; ++i) {
+ try {
+ IPictureProfileCallback callback = userState.mCallbacks.getBroadcastItem(i);
+ Pair<Integer, Integer> pidUid = userState.mCallbackPidUidMap.get(callback);
+
+ if (pidUid.first == pid && pidUid.second == uid) {
+ userState.mCallbacks.getBroadcastItem(i).onError(profileId, errorCode);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "failed to report added input to callback", e);
+ }
+ }
+ userState.mCallbacks.finishBroadcast();
+ }
+
@Override
public void registerPictureProfileCallback(final IPictureProfileCallback callback) {
+ int callingPid = Binder.getCallingPid();
+ int callingUid = Binder.getCallingUid();
+
+ UserState userState = getOrCreateUserStateLocked(Binder.getCallingUid());
+ userState.mCallbackPidUidMap.put(callback, Pair.create(callingPid, callingUid));
}
+
@Override
public void registerSoundProfileCallback(final ISoundProfileCallback callback) {
}
@Override
public void registerAmbientBacklightCallback(IAmbientBacklightCallback callback) {
+ if (!hasReadColorZonesPermission()) {
+ //TODO: error handling
+ }
}
@Override
public void setAmbientBacklightSettings(
AmbientBacklightSettings settings, UserHandle user) {
+ if (!hasReadColorZonesPermission()) {
+ //TODO: error handling
+ }
}
@Override
public void setAmbientBacklightEnabled(boolean enabled, UserHandle user) {
+ if (!hasReadColorZonesPermission()) {
+ //TODO: error handling
+ }
}
@Override
@@ -551,20 +769,34 @@ public class MediaQualityService extends SystemService {
@Override
public List<String> getPictureProfileAllowList(UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ //TODO: error handling
+ return new ArrayList<>();
+ }
return new ArrayList<>();
}
@Override
public void setPictureProfileAllowList(List<String> packages, UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ //TODO: error handling
+ }
}
@Override
public List<String> getSoundProfileAllowList(UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ return new ArrayList<>();
+ }
return new ArrayList<>();
}
@Override
public void setSoundProfileAllowList(List<String> packages, UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ }
}
@Override
@@ -574,6 +806,9 @@ public class MediaQualityService extends SystemService {
@Override
public void setAutoPictureQualityEnabled(boolean enabled, UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ //TODO: error handling
+ }
}
@Override
@@ -583,6 +818,9 @@ public class MediaQualityService extends SystemService {
@Override
public void setSuperResolutionEnabled(boolean enabled, UserHandle user) {
+ if (!hasGlobalPictureQualityServicePermission()) {
+ //TODO: error handling
+ }
}
@Override
@@ -592,6 +830,9 @@ public class MediaQualityService extends SystemService {
@Override
public void setAutoSoundQualityEnabled(boolean enabled, UserHandle user) {
+ if (!hasGlobalSoundQualityServicePermission()) {
+ //TODO: error handling
+ }
}
@Override
@@ -604,4 +845,38 @@ public class MediaQualityService extends SystemService {
return false;
}
}
+
+ private class MediaQualityManagerCallbackList extends
+ RemoteCallbackList<IPictureProfileCallback> {
+ @Override
+ public void onCallbackDied(IPictureProfileCallback callback) {
+ //todo
+ }
+ }
+
+ private final class UserState {
+ // A list of callbacks.
+ private final MediaQualityManagerCallbackList mCallbacks =
+ new MediaQualityManagerCallbackList();
+
+ private final Map<IPictureProfileCallback, Pair<Integer, Integer>> mCallbackPidUidMap =
+ new HashMap<>();
+
+ private UserState(Context context, int userId) {
+
+ }
+ }
+
+ private UserState getOrCreateUserStateLocked(int userId) {
+ UserState userState = getUserStateLocked(userId);
+ if (userState == null) {
+ userState = new UserState(mContext, userId);
+ mUserStates.put(userId, userState);
+ }
+ return userState;
+ }
+
+ private UserState getUserStateLocked(int userId) {
+ return mUserStates.get(userId);
+ }
}
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 0b40d64e3a09..3f2c2228e453 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -325,7 +325,7 @@ public class ConditionProviders extends ManagedServices {
for (int i = 0; i < N; i++) {
final Condition c = conditions[i];
if (mCallback != null) {
- mCallback.onConditionChanged(c.id, c);
+ mCallback.onConditionChanged(c.id, c, info.uid);
}
}
}
@@ -515,7 +515,7 @@ public class ConditionProviders extends ManagedServices {
public interface Callback {
void onServiceAdded(ComponentName component);
- void onConditionChanged(Uri id, Condition condition);
+ void onConditionChanged(Uri id, Condition condition, int callerUid);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f50e8aa7eb7b..9567c818fa18 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5903,8 +5903,9 @@ public class NotificationManagerService extends SystemService {
// TODO: b/310620812 - Remove getZenRules() when MODES_API is inlined.
@Override
public List<ZenModeConfig.ZenRule> getZenRules() throws RemoteException {
- enforcePolicyAccess(Binder.getCallingUid(), "getZenRules");
- return mZenModeHelper.getZenRules(getCallingZenUser());
+ int callingUid = Binder.getCallingUid();
+ enforcePolicyAccess(callingUid, "getZenRules");
+ return mZenModeHelper.getZenRules(getCallingZenUser(), callingUid);
}
@Override
@@ -5912,15 +5913,17 @@ public class NotificationManagerService extends SystemService {
if (!android.app.Flags.modesApi()) {
throw new IllegalStateException("getAutomaticZenRules called with flag off!");
}
- enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRules");
- return mZenModeHelper.getAutomaticZenRules(getCallingZenUser());
+ int callingUid = Binder.getCallingUid();
+ enforcePolicyAccess(callingUid, "getAutomaticZenRules");
+ return mZenModeHelper.getAutomaticZenRules(getCallingZenUser(), callingUid);
}
@Override
public AutomaticZenRule getAutomaticZenRule(String id) throws RemoteException {
Objects.requireNonNull(id, "Id is null");
- enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRule");
- return mZenModeHelper.getAutomaticZenRule(getCallingZenUser(), id);
+ int callingUid = Binder.getCallingUid();
+ enforcePolicyAccess(callingUid, "getAutomaticZenRule");
+ return mZenModeHelper.getAutomaticZenRule(getCallingZenUser(), id, callingUid);
}
@Override
@@ -6065,8 +6068,9 @@ public class NotificationManagerService extends SystemService {
@Condition.State
public int getAutomaticZenRuleState(@NonNull String id) {
Objects.requireNonNull(id, "id is null");
- enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRuleState");
- return mZenModeHelper.getAutomaticZenRuleState(getCallingZenUser(), id);
+ int callingUid = Binder.getCallingUid();
+ enforcePolicyAccess(callingUid, "getAutomaticZenRuleState");
+ return mZenModeHelper.getAutomaticZenRuleState(getCallingZenUser(), id, callingUid);
}
@Override
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index 52d0c41614d5..d44baeb58a28 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -113,15 +113,18 @@ public class ZenModeConditions implements ConditionProviders.Callback {
}
@Override
- public void onConditionChanged(Uri id, Condition condition) {
+ public void onConditionChanged(Uri id, Condition condition, int callingUid) {
if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition);
ZenModeConfig config = mHelper.getConfig();
if (config == null) return;
- final int callingUid = Binder.getCallingUid();
+ if (!Flags.fixCallingUidFromCps()) {
+ // Old behavior: overwrite with known-bad callingUid (always system_server).
+ callingUid = Binder.getCallingUid();
+ }
// This change is known to be for UserHandle.CURRENT because ConditionProviders for
// background users are not bound.
- mHelper.setAutomaticZenRuleState(UserHandle.CURRENT, id, condition,
+ mHelper.setAutomaticZenRuleStateFromConditionProvider(UserHandle.CURRENT, id, condition,
callingUid == Process.SYSTEM_UID ? ZenModeConfig.ORIGIN_SYSTEM
: ZenModeConfig.ORIGIN_APP,
callingUid);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index b571d62c0cba..0a63f3fb36d0 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -413,13 +413,13 @@ public class ZenModeHelper {
}
// TODO: b/310620812 - Make private (or inline) when MODES_API is inlined.
- public List<ZenRule> getZenRules(UserHandle user) {
+ public List<ZenRule> getZenRules(UserHandle user, int callingUid) {
List<ZenRule> rules = new ArrayList<>();
synchronized (mConfigLock) {
ZenModeConfig config = getConfigLocked(user);
if (config == null) return rules;
for (ZenRule rule : config.automaticRules.values()) {
- if (canManageAutomaticZenRule(rule)) {
+ if (canManageAutomaticZenRule(rule, callingUid)) {
rules.add(rule);
}
}
@@ -432,8 +432,8 @@ public class ZenModeHelper {
* (which means the owned rules for a regular app, and every rule for system callers) together
* with their ids.
*/
- Map<String, AutomaticZenRule> getAutomaticZenRules(UserHandle user) {
- List<ZenRule> ruleList = getZenRules(user);
+ Map<String, AutomaticZenRule> getAutomaticZenRules(UserHandle user, int callingUid) {
+ List<ZenRule> ruleList = getZenRules(user, callingUid);
HashMap<String, AutomaticZenRule> rules = new HashMap<>(ruleList.size());
for (ZenRule rule : ruleList) {
rules.put(rule.id, zenRuleToAutomaticZenRule(rule));
@@ -441,7 +441,7 @@ public class ZenModeHelper {
return rules;
}
- public AutomaticZenRule getAutomaticZenRule(UserHandle user, String id) {
+ public AutomaticZenRule getAutomaticZenRule(UserHandle user, String id, int callingUid) {
ZenRule rule;
synchronized (mConfigLock) {
ZenModeConfig config = getConfigLocked(user);
@@ -449,7 +449,7 @@ public class ZenModeHelper {
rule = config.automaticRules.get(id);
}
if (rule == null) return null;
- if (canManageAutomaticZenRule(rule)) {
+ if (canManageAutomaticZenRule(rule, callingUid)) {
return zenRuleToAutomaticZenRule(rule);
}
return null;
@@ -591,7 +591,7 @@ public class ZenModeHelper {
+ " reason=" + reason);
}
ZenModeConfig.ZenRule oldRule = config.automaticRules.get(ruleId);
- if (oldRule == null || !canManageAutomaticZenRule(oldRule)) {
+ if (oldRule == null || !canManageAutomaticZenRule(oldRule, callingUid)) {
throw new SecurityException(
"Cannot update rules not owned by your condition provider");
}
@@ -859,7 +859,7 @@ public class ZenModeHelper {
newConfig = config.copy();
ZenRule ruleToRemove = newConfig.automaticRules.get(id);
if (ruleToRemove == null) return false;
- if (canManageAutomaticZenRule(ruleToRemove)) {
+ if (canManageAutomaticZenRule(ruleToRemove, callingUid)) {
newConfig.automaticRules.remove(id);
maybePreserveRemovedRule(newConfig, ruleToRemove, origin);
if (ruleToRemove.getPkg() != null
@@ -893,7 +893,8 @@ public class ZenModeHelper {
newConfig = config.copy();
for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
- if (Objects.equals(rule.getPkg(), packageName) && canManageAutomaticZenRule(rule)) {
+ if (Objects.equals(rule.getPkg(), packageName)
+ && canManageAutomaticZenRule(rule, callingUid)) {
newConfig.automaticRules.removeAt(i);
maybePreserveRemovedRule(newConfig, rule, origin);
}
@@ -938,14 +939,14 @@ public class ZenModeHelper {
}
@Condition.State
- int getAutomaticZenRuleState(UserHandle user, String id) {
+ int getAutomaticZenRuleState(UserHandle user, String id, int callingUid) {
synchronized (mConfigLock) {
ZenModeConfig config = getConfigLocked(user);
if (config == null) {
return Condition.STATE_UNKNOWN;
}
ZenRule rule = config.automaticRules.get(id);
- if (rule == null || !canManageAutomaticZenRule(rule)) {
+ if (rule == null || !canManageAutomaticZenRule(rule, callingUid)) {
return Condition.STATE_UNKNOWN;
}
if (Flags.modesApi() && Flags.modesUi()) {
@@ -968,7 +969,7 @@ public class ZenModeHelper {
newConfig = config.copy();
ZenRule rule = newConfig.automaticRules.get(id);
if (Flags.modesApi()) {
- if (rule != null && canManageAutomaticZenRule(rule)) {
+ if (rule != null && canManageAutomaticZenRule(rule, callingUid)) {
setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule),
condition, origin, callingUid);
}
@@ -980,8 +981,8 @@ public class ZenModeHelper {
}
}
- void setAutomaticZenRuleState(UserHandle user, Uri ruleDefinition, Condition condition,
- @ConfigOrigin int origin, int callingUid) {
+ void setAutomaticZenRuleStateFromConditionProvider(UserHandle user, Uri ruleDefinition,
+ Condition condition, @ConfigOrigin int origin, int callingUid) {
checkSetRuleStateOrigin("setAutomaticZenRuleState(Uri ruleDefinition)", origin);
ZenModeConfig newConfig;
synchronized (mConfigLock) {
@@ -992,7 +993,7 @@ public class ZenModeHelper {
List<ZenRule> matchingRules = findMatchingRules(newConfig, ruleDefinition, condition);
if (Flags.modesApi()) {
for (int i = matchingRules.size() - 1; i >= 0; i--) {
- if (!canManageAutomaticZenRule(matchingRules.get(i))) {
+ if (!canManageAutomaticZenRule(matchingRules.get(i), callingUid)) {
matchingRules.remove(i);
}
}
@@ -1125,15 +1126,21 @@ public class ZenModeHelper {
return count;
}
- public boolean canManageAutomaticZenRule(ZenRule rule) {
- final int callingUid = Binder.getCallingUid();
+ public boolean canManageAutomaticZenRule(ZenRule rule, int callingUid) {
+ if (!com.android.server.notification.Flags.fixCallingUidFromCps()) {
+ // Old behavior: ignore supplied callingUid and instead obtain it here. Will be
+ // incorrect if not currently handling a Binder call.
+ callingUid = Binder.getCallingUid();
+ }
+
if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
+ // Checked specifically, because checkCallingPermission() will fail.
return true;
} else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
return true;
} else {
- String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
+ String[] packages = mPm.getPackagesForUid(callingUid);
if (packages != null) {
final int packageCount = packages.length;
for (int i = 0; i < packageCount; i++) {
@@ -2902,8 +2909,8 @@ public class ZenModeHelper {
}
/**
- * Checks that the {@code origin} supplied to {@link #setAutomaticZenRuleState} overloads makes
- * sense.
+ * Checks that the {@code origin} supplied to {@link #setAutomaticZenRuleState} or
+ * {@link #setAutomaticZenRuleStateFromConditionProvider} makes sense.
*/
private static void checkSetRuleStateOrigin(String method, @ConfigOrigin int origin) {
if (!Flags.modesApi()) {
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index f15c23e110a4..2b4d71e85dc0 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -196,4 +196,14 @@ flag {
metadata {
purpose: PURPOSE_BUGFIX
}
-} \ No newline at end of file
+}
+
+flag {
+ name: "fix_calling_uid_from_cps"
+ namespace: "systemui"
+ description: "Correctly checks zen rule ownership when a CPS notifies with a Condition"
+ bug: "379722187"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/core/java/com/android/server/pm/ResilientAtomicFile.java b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
index 3aefc5a64926..473ed6136e9a 100644
--- a/services/core/java/com/android/server/pm/ResilientAtomicFile.java
+++ b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
@@ -23,6 +23,7 @@ import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.security.FileIntegrity;
import libcore.io.IoUtils;
@@ -121,6 +122,11 @@ final class ResilientAtomicFile implements Closeable {
}
public void finishWrite(FileOutputStream str) throws IOException {
+ finishWrite(str, true /* doFsVerity */);
+ }
+
+ @VisibleForTesting
+ public void finishWrite(FileOutputStream str, final boolean doFsVerity) throws IOException {
if (mMainOutStream != str) {
throw new IllegalStateException("Invalid incoming stream.");
}
@@ -145,13 +151,15 @@ final class ResilientAtomicFile implements Closeable {
finalizeOutStream(reserveOutStream);
}
- // Protect both main and reserve using fs-verity.
- try (ParcelFileDescriptor mainPfd = ParcelFileDescriptor.dup(mainInStream.getFD());
- ParcelFileDescriptor copyPfd = ParcelFileDescriptor.dup(reserveInStream.getFD())) {
- FileIntegrity.setUpFsVerity(mainPfd);
- FileIntegrity.setUpFsVerity(copyPfd);
- } catch (IOException e) {
- Slog.e(LOG_TAG, "Failed to verity-protect " + mDebugName, e);
+ if (doFsVerity) {
+ // Protect both main and reserve using fs-verity.
+ try (ParcelFileDescriptor mainPfd = ParcelFileDescriptor.dup(mainInStream.getFD());
+ ParcelFileDescriptor copyPfd = ParcelFileDescriptor.dup(reserveInStream.getFD())) {
+ FileIntegrity.setUpFsVerity(mainPfd);
+ FileIntegrity.setUpFsVerity(copyPfd);
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Failed to verity-protect " + mDebugName, e);
+ }
}
} catch (IOException e) {
Slog.e(LOG_TAG, "Failed to write reserve copy " + mDebugName + ": " + mReserveCopy, e);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 44789e4c4de2..027da4986ce6 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -179,7 +179,7 @@ abstract class ShortcutPackageItem {
itemOut.endDocument();
os.flush();
- file.finishWrite(os);
+ mShortcutUser.mService.injectFinishWrite(file, os);
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 2785da5cbdbd..373c1ed3c386 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1008,7 +1008,7 @@ public class ShortcutService extends IShortcutService.Stub {
out.endDocument();
// Close.
- file.finishWrite(outs);
+ injectFinishWrite(file, outs);
} catch (IOException e) {
Slog.w(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(outs);
@@ -1096,7 +1096,7 @@ public class ShortcutService extends IShortcutService.Stub {
saveUserInternalLocked(userId, os, /* forBackup= */ false);
}
- file.finishWrite(os);
+ injectFinishWrite(file, os);
// Remove all dangling bitmap files.
cleanupDanglingBitmapDirectoriesLocked(userId);
@@ -5067,6 +5067,12 @@ public class ShortcutService extends IShortcutService.Stub {
return Build.FINGERPRINT;
}
+ // Injection point.
+ void injectFinishWrite(@NonNull final ResilientAtomicFile file,
+ @NonNull final FileOutputStream os) throws IOException {
+ file.finishWrite(os);
+ }
+
final void wtf(String message) {
wtf(message, /* exception= */ null);
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5ab59657d4ce..516213b32354 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -562,8 +562,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mPowerKeyHandled;
volatile boolean mBackKeyHandled;
volatile boolean mEndCallKeyHandled;
- volatile boolean mCameraGestureTriggered;
- volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
+ volatile boolean mPowerButtonLaunchGestureTriggered;
+ volatile boolean mPowerButtonLaunchGestureTriggeredDuringGoingToSleep;
/**
* {@code true} if the device is entering a low-power state; {@code false otherwise}.
@@ -5893,7 +5893,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mGestureLauncherService == null) {
return false;
}
- mCameraGestureTriggered = false;
+ mPowerButtonLaunchGestureTriggered = false;
final MutableBoolean outLaunched = new MutableBoolean(false);
final boolean intercept =
mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);
@@ -5903,9 +5903,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// detector from processing the power key later on.
return intercept;
}
- mCameraGestureTriggered = true;
+ mPowerButtonLaunchGestureTriggered = true;
if (mRequestedOrSleepingDefaultDisplay) {
- mCameraGestureTriggeredDuringGoingToSleep = true;
+ mPowerButtonLaunchGestureTriggeredDuringGoingToSleep = true;
// Wake device up early to prevent display doing redundant turning off/on stuff.
mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture();
}
@@ -6282,13 +6282,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onFinishedGoingToSleep(pmSleepReason,
- mCameraGestureTriggeredDuringGoingToSleep);
+ mPowerButtonLaunchGestureTriggeredDuringGoingToSleep);
}
if (mDisplayFoldController != null) {
mDisplayFoldController.finishedGoingToSleep();
}
- mCameraGestureTriggeredDuringGoingToSleep = false;
- mCameraGestureTriggered = false;
+ mPowerButtonLaunchGestureTriggeredDuringGoingToSleep = false;
+ mPowerButtonLaunchGestureTriggered = false;
}
// Called on the PowerManager's Notifier thread.
@@ -6319,10 +6319,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDefaultDisplayRotation.updateOrientationListener();
if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onStartedWakingUp(pmWakeReason, mCameraGestureTriggered);
+ mKeyguardDelegate.onStartedWakingUp(pmWakeReason, mPowerButtonLaunchGestureTriggered);
}
- mCameraGestureTriggered = false;
+ mPowerButtonLaunchGestureTriggered = false;
}
// Called on the PowerManager's Notifier thread.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index da8b01ac86fb..587447b8af26 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -198,7 +198,7 @@ public class KeyguardServiceDelegate {
if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
|| mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
mKeyguardService.onStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN,
- false /* cameraGestureTriggered */);
+ false /* powerButtonLaunchGestureTriggered */);
}
if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
mKeyguardService.onFinishedWakingUp();
@@ -319,10 +319,10 @@ public class KeyguardServiceDelegate {
}
public void onStartedWakingUp(
- @PowerManager.WakeReason int pmWakeReason, boolean cameraGestureTriggered) {
+ @PowerManager.WakeReason int pmWakeReason, boolean powerButtonLaunchGestureTriggered) {
if (mKeyguardService != null) {
if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
- mKeyguardService.onStartedWakingUp(pmWakeReason, cameraGestureTriggered);
+ mKeyguardService.onStartedWakingUp(pmWakeReason, powerButtonLaunchGestureTriggered);
}
mKeyguardState.interactiveState = INTERACTIVE_STATE_WAKING;
}
@@ -383,9 +383,11 @@ public class KeyguardServiceDelegate {
}
public void onFinishedGoingToSleep(
- @PowerManager.GoToSleepReason int pmSleepReason, boolean cameraGestureTriggered) {
+ @PowerManager.GoToSleepReason int pmSleepReason,
+ boolean powerButtonLaunchGestureTriggered) {
if (mKeyguardService != null) {
- mKeyguardService.onFinishedGoingToSleep(pmSleepReason, cameraGestureTriggered);
+ mKeyguardService.onFinishedGoingToSleep(pmSleepReason,
+ powerButtonLaunchGestureTriggered);
}
mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index cd789eaed1b3..f2342e0d5688 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -113,9 +113,10 @@ public class KeyguardServiceWrapper implements IKeyguardService {
@Override
public void onFinishedGoingToSleep(
- @PowerManager.GoToSleepReason int pmSleepReason, boolean cameraGestureTriggered) {
+ @PowerManager.GoToSleepReason int pmSleepReason,
+ boolean powerButtonLaunchGestureTriggered) {
try {
- mService.onFinishedGoingToSleep(pmSleepReason, cameraGestureTriggered);
+ mService.onFinishedGoingToSleep(pmSleepReason, powerButtonLaunchGestureTriggered);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
@@ -123,9 +124,9 @@ public class KeyguardServiceWrapper implements IKeyguardService {
@Override
public void onStartedWakingUp(
- @PowerManager.WakeReason int pmWakeReason, boolean cameraGestureTriggered) {
+ @PowerManager.WakeReason int pmWakeReason, boolean powerButtonLaunchGestureTriggered) {
try {
- mService.onStartedWakingUp(pmWakeReason, cameraGestureTriggered);
+ mService.onStartedWakingUp(pmWakeReason, powerButtonLaunchGestureTriggered);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
diff --git a/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java b/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
index a75d110e3cd1..17739712d65a 100644
--- a/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
+++ b/services/core/java/com/android/server/resources/ResourcesManagerShellCommand.java
@@ -88,6 +88,5 @@ public class ResourcesManagerShellCommand extends ShellCommand {
out.println(" Print this help text.");
out.println(" dump <PROCESS>");
out.println(" Dump the Resources objects in use as well as the history of Resources");
-
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 093df8c5075c..29f1f93a844f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3209,7 +3209,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
true /* forActivity */)) {
return false;
}
- if (mAppCompatController.mAllowRestrictedResizability.getAsBoolean()) {
+ if (mAppCompatController.getResizeOverrides().allowRestrictedResizability()) {
return false;
}
// If the user preference respects aspect ratio, then it becomes non-resizable.
@@ -3240,8 +3240,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// The caller will check both application and activity level property.
return true;
}
- return !AppCompatController.allowRestrictedResizability(wms.mContext.getPackageManager(),
- appInfo.packageName);
+ return !AppCompatResizeOverrides.allowRestrictedResizability(
+ wms.mContext.getPackageManager(), appInfo.packageName);
}
boolean isResizeable() {
@@ -8435,8 +8435,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
*/
@ActivityInfo.SizeChangesSupportMode
private int supportsSizeChanges() {
- if (mAppCompatController.getAppCompatResizeOverrides()
- .shouldOverrideForceNonResizeApp()) {
+ final AppCompatResizeOverrides resizeOverrides = mAppCompatController.getResizeOverrides();
+ if (resizeOverrides.shouldOverrideForceNonResizeApp()) {
return SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
}
@@ -8444,8 +8444,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return SIZE_CHANGES_SUPPORTED_METADATA;
}
- if (mAppCompatController.getAppCompatResizeOverrides()
- .shouldOverrideForceResizeApp()) {
+ if (resizeOverrides.shouldOverrideForceResizeApp()) {
return SIZE_CHANGES_SUPPORTED_OVERRIDE;
}
@@ -10221,7 +10220,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mAppCompatController.getAppCompatOrientationOverrides()
.shouldIgnoreOrientationRequestLoop());
proto.write(SHOULD_OVERRIDE_FORCE_RESIZE_APP,
- mAppCompatController.getAppCompatResizeOverrides().shouldOverrideForceResizeApp());
+ mAppCompatController.getResizeOverrides().shouldOverrideForceResizeApp());
proto.write(SHOULD_ENABLE_USER_ASPECT_RATIO_SETTINGS,
mAppCompatController.getAppCompatAspectRatioOverrides()
.shouldEnableUserAspectRatioSettings());
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index 4433d64f0d00..0967078deac3 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -15,23 +15,17 @@
*/
package com.android.server.wm;
-import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY;
-
import android.annotation.NonNull;
import android.content.pm.PackageManager;
import com.android.server.wm.utils.OptPropFactory;
import java.io.PrintWriter;
-import java.util.function.BooleanSupplier;
/**
* Allows the interaction with all the app compat policies and configurations
*/
class AppCompatController {
-
- @NonNull
- private final ActivityRecord mActivityRecord;
@NonNull
private final TransparentPolicy mTransparentPolicy;
@NonNull
@@ -50,56 +44,28 @@ class AppCompatController {
private final AppCompatLetterboxPolicy mAppCompatLetterboxPolicy;
@NonNull
private final AppCompatSizeCompatModePolicy mAppCompatSizeCompatModePolicy;
- @NonNull
- final BooleanSupplier mAllowRestrictedResizability;
AppCompatController(@NonNull WindowManagerService wmService,
@NonNull ActivityRecord activityRecord) {
- mActivityRecord = activityRecord;
final PackageManager packageManager = wmService.mContext.getPackageManager();
final OptPropFactory optPropBuilder = new OptPropFactory(packageManager,
activityRecord.packageName);
mAppCompatDeviceStateQuery = new AppCompatDeviceStateQuery(activityRecord);
mTransparentPolicy = new TransparentPolicy(activityRecord,
wmService.mAppCompatConfiguration);
- mAppCompatOverrides = new AppCompatOverrides(activityRecord,
+ mAppCompatOverrides = new AppCompatOverrides(activityRecord, packageManager,
wmService.mAppCompatConfiguration, optPropBuilder, mAppCompatDeviceStateQuery);
mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord, mAppCompatOverrides);
mAppCompatAspectRatioPolicy = new AppCompatAspectRatioPolicy(activityRecord,
mTransparentPolicy, mAppCompatOverrides);
- mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(mActivityRecord,
+ mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(activityRecord,
wmService.mAppCompatConfiguration);
- mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(mActivityRecord,
+ mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(activityRecord,
wmService.mAppCompatConfiguration);
mDesktopAppCompatAspectRatioPolicy = new DesktopAppCompatAspectRatioPolicy(activityRecord,
mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration);
- mAppCompatSizeCompatModePolicy = new AppCompatSizeCompatModePolicy(mActivityRecord,
+ mAppCompatSizeCompatModePolicy = new AppCompatSizeCompatModePolicy(activityRecord,
mAppCompatOverrides);
- mAllowRestrictedResizability = AppCompatUtils.asLazy(() -> {
- // Application level.
- if (allowRestrictedResizability(packageManager, mActivityRecord.packageName)) {
- return true;
- }
- // Activity level.
- try {
- return packageManager.getPropertyAsUser(
- PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY,
- mActivityRecord.mActivityComponent.getPackageName(),
- mActivityRecord.mActivityComponent.getClassName(),
- mActivityRecord.mUserId).getBoolean();
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- });
- }
-
- static boolean allowRestrictedResizability(PackageManager pm, String packageName) {
- try {
- return pm.getProperty(PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, packageName)
- .getBoolean();
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
}
@NonNull
@@ -138,8 +104,8 @@ class AppCompatController {
}
@NonNull
- AppCompatResizeOverrides getAppCompatResizeOverrides() {
- return mAppCompatOverrides.getAppCompatResizeOverrides();
+ AppCompatResizeOverrides getResizeOverrides() {
+ return mAppCompatOverrides.getResizeOverrides();
}
@NonNull
diff --git a/services/core/java/com/android/server/wm/AppCompatOverrides.java b/services/core/java/com/android/server/wm/AppCompatOverrides.java
index 2f03105846bd..58b37becc373 100644
--- a/services/core/java/com/android/server/wm/AppCompatOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatOverrides.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.annotation.NonNull;
+import android.content.pm.PackageManager;
import com.android.server.wm.utils.OptPropFactory;
@@ -34,13 +35,14 @@ public class AppCompatOverrides {
@NonNull
private final AppCompatFocusOverrides mAppCompatFocusOverrides;
@NonNull
- private final AppCompatResizeOverrides mAppCompatResizeOverrides;
+ private final AppCompatResizeOverrides mResizeOverrides;
@NonNull
private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
@NonNull
private final AppCompatLetterboxOverrides mAppCompatLetterboxOverrides;
AppCompatOverrides(@NonNull ActivityRecord activityRecord,
+ @NonNull PackageManager packageManager,
@NonNull AppCompatConfiguration appCompatConfiguration,
@NonNull OptPropFactory optPropBuilder,
@NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery) {
@@ -55,7 +57,8 @@ public class AppCompatOverrides {
mAppCompatReachabilityOverrides);
mAppCompatFocusOverrides = new AppCompatFocusOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
- mAppCompatResizeOverrides = new AppCompatResizeOverrides(activityRecord, optPropBuilder);
+ mResizeOverrides = new AppCompatResizeOverrides(activityRecord, packageManager,
+ optPropBuilder);
mAppCompatLetterboxOverrides = new AppCompatLetterboxOverrides(activityRecord,
appCompatConfiguration);
}
@@ -81,8 +84,8 @@ public class AppCompatOverrides {
}
@NonNull
- AppCompatResizeOverrides getAppCompatResizeOverrides() {
- return mAppCompatResizeOverrides;
+ AppCompatResizeOverrides getResizeOverrides() {
+ return mResizeOverrides;
}
@NonNull
diff --git a/services/core/java/com/android/server/wm/AppCompatResizeOverrides.java b/services/core/java/com/android/server/wm/AppCompatResizeOverrides.java
index 60c18254eca7..fa53153dd143 100644
--- a/services/core/java/com/android/server/wm/AppCompatResizeOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatResizeOverrides.java
@@ -19,13 +19,17 @@ package com.android.server.wm;
import static android.content.pm.ActivityInfo.FORCE_NON_RESIZE_APP;
import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY;
import static com.android.server.wm.AppCompatUtils.isChangeEnabled;
import android.annotation.NonNull;
+import android.content.pm.PackageManager;
import com.android.server.wm.utils.OptPropFactory;
+import java.util.function.BooleanSupplier;
+
/**
* Encapsulate app compat logic about resizability.
*/
@@ -37,11 +41,40 @@ class AppCompatResizeOverrides {
@NonNull
private final OptPropFactory.OptProp mAllowForceResizeOverrideOptProp;
+ @NonNull
+ private final BooleanSupplier mAllowRestrictedResizability;
+
AppCompatResizeOverrides(@NonNull ActivityRecord activityRecord,
+ @NonNull PackageManager packageManager,
@NonNull OptPropFactory optPropBuilder) {
mActivityRecord = activityRecord;
mAllowForceResizeOverrideOptProp = optPropBuilder.create(
PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES);
+ mAllowRestrictedResizability = AppCompatUtils.asLazy(() -> {
+ // Application level.
+ if (allowRestrictedResizability(packageManager, mActivityRecord.packageName)) {
+ return true;
+ }
+ // Activity level.
+ try {
+ return packageManager.getPropertyAsUser(
+ PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY,
+ mActivityRecord.mActivityComponent.getPackageName(),
+ mActivityRecord.mActivityComponent.getClassName(),
+ mActivityRecord.mUserId).getBoolean();
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ });
+ }
+
+ static boolean allowRestrictedResizability(PackageManager pm, String packageName) {
+ try {
+ return pm.getProperty(PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY, packageName)
+ .getBoolean();
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
}
/**
@@ -75,4 +108,9 @@ class AppCompatResizeOverrides {
return mAllowForceResizeOverrideOptProp.shouldEnableWithOptInOverrideAndOptOutProperty(
isChangeEnabled(mActivityRecord, FORCE_NON_RESIZE_APP));
}
+
+ /** @see android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY */
+ boolean allowRestrictedResizability() {
+ return mAllowRestrictedResizability.getAsBoolean();
+ }
}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 98ed6f76b2f9..54ae80cfe98a 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -103,6 +103,8 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
// again, so that the control with leash can be eventually dispatched
if (!mGivenInsetsReady && isServerVisible() && !givenInsetsPending
&& mControlTarget != null) {
+ ProtoLog.d(WM_DEBUG_IME,
+ "onPostLayout: IME control ready to be dispatched, ws=%s", ws);
mGivenInsetsReady = true;
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
@@ -118,6 +120,8 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
mStatsToken = null;
} else if (wasServerVisible && !isServerVisible()) {
+ ProtoLog.d(WM_DEBUG_IME, "onPostLayout: setImeShowing(false) was: %s, ws=%s",
+ isImeShowing(), ws);
setImeShowing(false);
}
}
@@ -621,6 +625,7 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
// request (cancelling the initial show) or hide request (aborting the initial show).
logIsScheduledAndReadyToShowIme(!visible /* aborted */);
}
+ ProtoLog.d(WM_DEBUG_IME, "receiveImeStatsToken: visible=%s", visible);
if (visible) {
ImeTracker.forLogging().onCancelled(
mStatsToken, ImeTracker.PHASE_WM_ABORT_SHOW_IME_POST_LAYOUT);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 4e030d499c25..3ef360a752f6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -112,6 +112,7 @@ import org.mockito.stubbing.Answer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -556,6 +557,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
+ void injectFinishWrite(@NonNull ResilientAtomicFile file,
+ @NonNull FileOutputStream os) throws IOException {
+ file.finishWrite(os, false /* doFsVerity */);
+ }
+
+ @Override
void wtf(String message, Throwable th) {
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index c01283a236c4..0d86d4c3fa28 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -159,7 +159,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Test for the first launch path, no settings file available.
*/
- public void FirstInitialize() {
+ public void testFirstInitialize() {
assertResetTimes(START_TIME, START_TIME + INTERVAL);
}
@@ -167,7 +167,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
* Test for {@link ShortcutService#getLastResetTimeLocked()} and
* {@link ShortcutService#getNextResetTimeLocked()}.
*/
- public void UpdateAndGetNextResetTimeLocked() {
+ public void testUpdateAndGetNextResetTimeLocked() {
assertResetTimes(START_TIME, START_TIME + INTERVAL);
// Advance clock.
@@ -196,7 +196,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Test for the restoration from saved file.
*/
- public void InitializeFromSavedFile() {
+ public void testInitializeFromSavedFile() {
mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL + 50;
assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
@@ -220,7 +220,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO Add various broken cases.
}
- public void LoadConfig() {
+ public void testLoadConfig() {
mService.updateConfigurationLocked(
ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123,"
+ ConfigConstants.KEY_MAX_SHORTCUTS + "=4,"
@@ -261,22 +261,22 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// === Test for app side APIs ===
/** Test for {@link android.content.pm.ShortcutManager#getMaxShortcutCountForActivity()} */
- public void GetMaxDynamicShortcutCount() {
+ public void testGetMaxDynamicShortcutCount() {
assertEquals(MAX_SHORTCUTS, mManager.getMaxShortcutCountForActivity());
}
/** Test for {@link android.content.pm.ShortcutManager#getRemainingCallCount()} */
- public void GetRemainingCallCount() {
+ public void testGetRemainingCallCount() {
assertEquals(MAX_UPDATES_PER_INTERVAL, mManager.getRemainingCallCount());
}
- public void GetIconMaxDimensions() {
+ public void testGetIconMaxDimensions() {
assertEquals(MAX_ICON_DIMENSION, mManager.getIconMaxWidth());
assertEquals(MAX_ICON_DIMENSION, mManager.getIconMaxHeight());
}
/** Test for {@link android.content.pm.ShortcutManager#getRateLimitResetTime()} */
- public void GetRateLimitResetTime() {
+ public void testGetRateLimitResetTime() {
assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL + 50;
@@ -284,7 +284,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals(START_TIME + 5 * INTERVAL, mManager.getRateLimitResetTime());
}
- public void SetDynamicShortcuts() {
+ public void testSetDynamicShortcuts() {
setCaller(CALLING_PACKAGE_1, USER_10);
final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.icon1);
@@ -354,7 +354,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void AddDynamicShortcuts() {
+ public void testAddDynamicShortcuts() {
setCaller(CALLING_PACKAGE_1, USER_10);
final ShortcutInfo si1 = makeShortcut("shortcut1");
@@ -402,7 +402,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PushDynamicShortcut() {
+ public void testPushDynamicShortcut() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=5,"
+ ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=1");
@@ -544,7 +544,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
eq(CALLING_PACKAGE_1), eq("s9"), eq(USER_10));
}
- public void PushDynamicShortcut_CallsToUsageStatsManagerAreThrottled()
+ public void testPushDynamicShortcut_CallsToUsageStatsManagerAreThrottled()
throws InterruptedException {
mService.updateConfigurationLocked(
ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=500");
@@ -576,6 +576,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
Mockito.reset(mMockUsageStatsManagerInternal);
for (int i = 2; i <= 10; i++) {
final ShortcutInfo si = makeShortcut("s" + i);
+ setCaller(CALLING_PACKAGE_2, USER_10);
mManager.pushDynamicShortcut(si);
}
verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
@@ -595,7 +596,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
eq(CALLING_PACKAGE_2), any(), eq(USER_10));
}
- public void UnlimitedCalls() {
+ public void testUnlimitedCalls() {
setCaller(CALLING_PACKAGE_1, USER_10);
final ShortcutInfo si1 = makeShortcut("shortcut1");
@@ -626,7 +627,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals(3, mManager.getRemainingCallCount());
}
- public void PublishWithNoActivity() {
+ public void testPublishWithNoActivity() {
// If activity is not explicitly set, use the default one.
mRunningUsers.put(USER_11, true);
@@ -732,7 +733,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PublishWithNoActivity_noMainActivityInPackage() {
+ public void testPublishWithNoActivity_noMainActivityInPackage() {
mRunningUsers.put(USER_11, true);
runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
@@ -751,7 +752,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void DeleteDynamicShortcuts() {
+ public void testDeleteDynamicShortcuts() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
final ShortcutInfo si2 = makeShortcut("shortcut2");
final ShortcutInfo si3 = makeShortcut("shortcut3");
@@ -792,7 +793,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals(2, mManager.getRemainingCallCount());
}
- public void DeleteAllDynamicShortcuts() {
+ public void testDeleteAllDynamicShortcuts() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
final ShortcutInfo si2 = makeShortcut("shortcut2");
final ShortcutInfo si3 = makeShortcut("shortcut3");
@@ -821,7 +822,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals(1, mManager.getRemainingCallCount());
}
- public void Icons() throws IOException {
+ public void testIcons() throws IOException {
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512);
@@ -1035,7 +1036,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
*/
}
- public void CleanupDanglingBitmaps() throws Exception {
+ public void testCleanupDanglingBitmaps() throws Exception {
assertBitmapDirectories(USER_10, EMPTY_STRINGS);
assertBitmapDirectories(USER_11, EMPTY_STRINGS);
@@ -1204,7 +1205,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
maxSize));
}
- public void ShrinkBitmap() {
+ public void testShrinkBitmap() {
checkShrinkBitmap(32, 32, R.drawable.black_512x512, 32);
checkShrinkBitmap(511, 511, R.drawable.black_512x512, 511);
checkShrinkBitmap(512, 512, R.drawable.black_512x512, 512);
@@ -1227,7 +1228,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
return out.getFile();
}
- public void OpenIconFileForWrite() throws IOException {
+ public void testOpenIconFileForWrite() throws IOException {
mInjectedCurrentTimeMillis = 1000;
final File p10_1_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
@@ -1301,7 +1302,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertFalse(p11_1_3.getName().contains("_"));
}
- public void UpdateShortcuts() {
+ public void testUpdateShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1"),
@@ -1432,7 +1433,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void UpdateShortcuts_icons() {
+ public void testUpdateShortcuts_icons() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1")
@@ -1526,7 +1527,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ShortcutManagerGetShortcuts_shortcutTypes() {
+ public void testShortcutManagerGetShortcuts_shortcutTypes() {
// Create 3 manifest and 3 dynamic shortcuts
addManifestShortcutResource(
@@ -1617,7 +1618,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s1", "s2");
}
- public void CachedShortcuts() {
+ public void testCachedShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
@@ -1701,7 +1702,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s2");
}
- public void CachedShortcuts_accessShortcutsPermission() {
+ public void testCachedShortcuts_accessShortcutsPermission() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
@@ -1743,7 +1744,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s3");
}
- public void CachedShortcuts_canPassShortcutLimit() {
+ public void testCachedShortcuts_canPassShortcutLimit() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=4");
@@ -1781,7 +1782,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// === Test for launcher side APIs ===
- public void GetShortcuts() {
+ public void testGetShortcuts() {
// Set up shortcuts.
@@ -1998,7 +1999,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s1", "s3");
}
- public void GetShortcuts_shortcutKinds() throws Exception {
+ public void testGetShortcuts_shortcutKinds() throws Exception {
// Create 3 manifest and 3 dynamic shortcuts
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -2109,7 +2110,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void GetShortcuts_resolveStrings() throws Exception {
+ public void testGetShortcuts_resolveStrings() throws Exception {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
ShortcutInfo si = new ShortcutInfo.Builder(mClientContext)
.setId("id")
@@ -2157,7 +2158,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void GetShortcuts_personsFlag() {
+ public void testGetShortcuts_personsFlag() {
ShortcutInfo s = new ShortcutInfo.Builder(mClientContext, "id")
.setShortLabel("label")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
@@ -2205,7 +2206,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
// TODO resource
- public void GetShortcutInfo() {
+ public void testGetShortcutInfo() {
// Create shortcuts.
setCaller(CALLING_PACKAGE_1);
final ShortcutInfo s1_1 = makeShortcut(
@@ -2280,7 +2281,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals("ABC", findById(list, "s1").getTitle());
}
- public void PinShortcutAndGetPinnedShortcuts() {
+ public void testPinShortcutAndGetPinnedShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
@@ -2361,7 +2362,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
* This is similar to the above test, except it used "disable" instead of "remove". It also
* does "enable".
*/
- public void DisableAndEnableShortcuts() {
+ public void testDisableAndEnableShortcuts() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
@@ -2486,7 +2487,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void DisableShortcuts_thenRepublish() {
+ public void testDisableShortcuts_thenRepublish() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
@@ -2556,7 +2557,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PinShortcutAndGetPinnedShortcuts_multi() {
+ public void testPinShortcutAndGetPinnedShortcuts_multi() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -2832,7 +2833,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PinShortcutAndGetPinnedShortcuts_assistant() {
+ public void testPinShortcutAndGetPinnedShortcuts_assistant() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -2888,7 +2889,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PinShortcutAndGetPinnedShortcuts_crossProfile_plusLaunch() {
+ public void testPinShortcutAndGetPinnedShortcuts_crossProfile_plusLaunch() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -3477,7 +3478,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void StartShortcut() {
+ public void testStartShortcut() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final ShortcutInfo s1_1 = makeShortcut(
@@ -3612,7 +3613,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO Check extra, etc
}
- public void LauncherCallback() throws Throwable {
+ public void testLauncherCallback() throws Throwable {
// Disable throttling for this test.
mService.updateConfigurationLocked(
ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999,"
@@ -3778,7 +3779,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
.isEmpty();
}
- public void LauncherCallback_crossProfile() throws Throwable {
+ public void testLauncherCallback_crossProfile() throws Throwable {
prepareCrossProfileDataSet();
final Handler h = new Handler(Looper.getMainLooper());
@@ -3901,7 +3902,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// === Test for persisting ===
- public void SaveAndLoadUser_empty() {
+ public void testSaveAndLoadUser_empty() {
assertTrue(mManager.setDynamicShortcuts(list()));
Log.i(TAG, "Saved state");
@@ -3918,7 +3919,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Try save and load, also stop/start the user.
*/
- public void SaveAndLoadUser() {
+ public void testSaveAndLoadUser() {
// First, create some shortcuts and save.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
@@ -4059,7 +4060,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO Check all other fields
}
- public void LoadCorruptedShortcuts() throws Exception {
+ public void testLoadCorruptedShortcuts() throws Exception {
initService();
addPackage("com.android.chrome", 0, 0);
@@ -4073,7 +4074,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false));
}
- public void SaveCorruptAndLoadUser() throws Exception {
+ public void testSaveCorruptAndLoadUser() throws Exception {
// First, create some shortcuts and save.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
@@ -4229,7 +4230,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO Check all other fields
}
- public void CleanupPackage() {
+ public void testCleanupPackage() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s0_1"))));
@@ -4506,7 +4507,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mService.saveDirtyInfo();
}
- public void CleanupPackage_republishManifests() {
+ public void testCleanupPackage_republishManifests() {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
@@ -4574,7 +4575,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HandleGonePackage_crossProfile() {
+ public void testHandleGonePackage_crossProfile() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -4846,7 +4847,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEquals(expected, spi.canRestoreTo(mService, pi, true));
}
- public void CanRestoreTo() {
+ public void testCanRestoreTo() {
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sig1");
addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 10, "sig1", "sig2");
addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 10, "sig1");
@@ -4909,7 +4910,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkCanRestoreTo(DISABLED_REASON_BACKUP_NOT_SUPPORTED, spi3, true, 10, true, "sig1");
}
- public void HandlePackageDelete() {
+ public void testHandlePackageDelete() {
checkHandlePackageDeleteInner((userId, packageName) -> {
uninstallPackage(userId, packageName);
mService.mPackageMonitor.onReceive(getTestContext(),
@@ -4917,7 +4918,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HandlePackageDisable() {
+ public void testHandlePackageDisable() {
checkHandlePackageDeleteInner((userId, packageName) -> {
disablePackage(userId, packageName);
mService.mPackageMonitor.onReceive(getTestContext(),
@@ -5049,7 +5050,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
/** Almost ame as testHandlePackageDelete, except it doesn't uninstall packages. */
- public void HandlePackageClearData() {
+ public void testHandlePackageClearData() {
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
setCaller(CALLING_PACKAGE_1, USER_10);
@@ -5125,7 +5126,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
}
- public void HandlePackageClearData_manifestRepublished() {
+ public void testHandlePackageClearData_manifestRepublished() {
mRunningUsers.put(USER_11, true);
@@ -5167,7 +5168,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HandlePackageUpdate() throws Throwable {
+ public void testHandlePackageUpdate() throws Throwable {
// Set up shortcuts and launchers.
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
@@ -5341,7 +5342,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Test the case where an updated app has resource IDs changed.
*/
- public void HandlePackageUpdate_resIdChanged() throws Exception {
+ public void testHandlePackageUpdate_resIdChanged() throws Exception {
final Icon icon1 = Icon.createWithResource(getTestContext(), /* res ID */ 1000);
final Icon icon2 = Icon.createWithResource(getTestContext(), /* res ID */ 1001);
@@ -5416,7 +5417,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HandlePackageUpdate_systemAppUpdate() {
+ public void testHandlePackageUpdate_systemAppUpdate() {
// Package1 is a system app. Package 2 is not a system app, so it's not scanned
// in this test at all.
@@ -5522,7 +5523,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mService.getUserShortcutsLocked(USER_10).getLastAppScanOsFingerprint());
}
- public void HandlePackageChanged() {
+ public void testHandlePackageChanged() {
final ComponentName ACTIVITY1 = new ComponentName(CALLING_PACKAGE_1, "act1");
final ComponentName ACTIVITY2 = new ComponentName(CALLING_PACKAGE_1, "act2");
@@ -5652,7 +5653,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HandlePackageUpdate_activityNoLongerMain() throws Throwable {
+ public void testHandlePackageUpdate_activityNoLongerMain() throws Throwable {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcutWithActivity("s1a",
@@ -5738,7 +5739,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
* - Unpinned dynamic shortcuts
* - Bitmaps
*/
- public void BackupAndRestore() {
+ public void testBackupAndRestore() {
assertFileNotExists("user-0/shortcut_dump/restore-0-start.txt");
assertFileNotExists("user-0/shortcut_dump/restore-1-payload.xml");
@@ -5759,7 +5760,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_success(/*firstRestore=*/ true);
}
- public void BackupAndRestore_backupRestoreTwice() {
+ public void testBackupAndRestore_backupRestoreTwice() {
prepareForBackupTest();
checkBackupAndRestore_success(/*firstRestore=*/ true);
@@ -5775,7 +5776,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_success(/*firstRestore=*/ false);
}
- public void BackupAndRestore_restoreToNewVersion() {
+ public void testBackupAndRestore_restoreToNewVersion() {
prepareForBackupTest();
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 2);
@@ -5784,7 +5785,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_success(/*firstRestore=*/ true);
}
- public void BackupAndRestore_restoreToSuperSetSignatures() {
+ public void testBackupAndRestore_restoreToSuperSetSignatures() {
prepareForBackupTest();
// Change package signatures.
@@ -5981,7 +5982,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void BackupAndRestore_publisherWrongSignature() {
+ public void testBackupAndRestore_publisherWrongSignature() {
prepareForBackupTest();
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sigx"); // different signature
@@ -5989,7 +5990,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_publisherNotRestored(ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH);
}
- public void BackupAndRestore_publisherNoLongerBackupTarget() {
+ public void testBackupAndRestore_publisherNoLongerBackupTarget() {
prepareForBackupTest();
updatePackageInfo(CALLING_PACKAGE_1,
@@ -6118,7 +6119,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void BackupAndRestore_launcherLowerVersion() {
+ public void testBackupAndRestore_launcherLowerVersion() {
prepareForBackupTest();
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 0); // Lower version
@@ -6127,7 +6128,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_success(/*firstRestore=*/ true);
}
- public void BackupAndRestore_launcherWrongSignature() {
+ public void testBackupAndRestore_launcherWrongSignature() {
prepareForBackupTest();
addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "sigx"); // different signature
@@ -6135,7 +6136,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
checkBackupAndRestore_launcherNotRestored(true);
}
- public void BackupAndRestore_launcherNoLongerBackupTarget() {
+ public void testBackupAndRestore_launcherNoLongerBackupTarget() {
prepareForBackupTest();
updatePackageInfo(LAUNCHER_1,
@@ -6240,7 +6241,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void BackupAndRestore_launcherAndPackageNoLongerBackupTarget() {
+ public void testBackupAndRestore_launcherAndPackageNoLongerBackupTarget() {
prepareForBackupTest();
updatePackageInfo(CALLING_PACKAGE_1,
@@ -6338,7 +6339,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void BackupAndRestore_disabled() {
+ public void testBackupAndRestore_disabled() {
prepareCrossProfileDataSet();
// Before doing backup & restore, disable s1.
@@ -6403,7 +6404,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
- public void BackupAndRestore_manifestRePublished() {
+ public void testBackupAndRestore_manifestRePublished() {
// Publish two manifest shortcuts.
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -6494,7 +6495,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
* logcat.
* - if it has allowBackup=false, we don't touch any of the existing shortcuts.
*/
- public void BackupAndRestore_appAlreadyInstalledWhenRestored() {
+ public void testBackupAndRestore_appAlreadyInstalledWhenRestored() {
// Pre-backup. Same as testBackupAndRestore_manifestRePublished().
// Publish two manifest shortcuts.
@@ -6619,7 +6620,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Test for restoring the pre-P backup format.
*/
- public void BackupAndRestore_api27format() throws Exception {
+ public void testBackupAndRestore_api27format() throws Exception {
final byte[] payload = readTestAsset("shortcut/shortcut_api27_backup.xml").getBytes();
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "22222");
@@ -6657,7 +6658,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
- public void SaveAndLoad_crossProfile() {
+ public void testSaveAndLoad_crossProfile() {
prepareCrossProfileDataSet();
dumpsysOnLogcat("Before save & load");
@@ -6860,7 +6861,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
.getPackageUserId());
}
- public void OnApplicationActive_permission() {
+ public void testOnApplicationActive_permission() {
assertExpectException(SecurityException.class, "Missing permission", () ->
mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10));
@@ -6869,7 +6870,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10);
}
- public void GetShareTargets_permission() {
+ public void testGetShareTargets_permission() {
addPackage(CHOOSER_ACTIVITY_PACKAGE, CHOOSER_ACTIVITY_UID, 10, "sig1");
mInjectedChooserActivity =
ComponentName.createRelative(CHOOSER_ACTIVITY_PACKAGE, ".ChooserActivity");
@@ -6888,7 +6889,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void HasShareTargets_permission() {
+ public void testHasShareTargets_permission() {
assertExpectException(SecurityException.class, "Missing permission", () ->
mManager.hasShareTargets(CALLING_PACKAGE_1));
@@ -6897,7 +6898,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.hasShareTargets(CALLING_PACKAGE_1);
}
- public void isSharingShortcut_permission() throws IntentFilter.MalformedMimeTypeException {
+ public void testisSharingShortcut_permission() throws IntentFilter.MalformedMimeTypeException {
setCaller(LAUNCHER_1, USER_10);
IntentFilter filter_any = new IntentFilter();
@@ -6912,18 +6913,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.hasShareTargets(CALLING_PACKAGE_1);
}
- public void Dumpsys_crossProfile() {
+ public void testDumpsys_crossProfile() {
prepareCrossProfileDataSet();
dumpsysOnLogcat("test1", /* force= */ true);
}
- public void Dumpsys_withIcons() throws IOException {
- Icons();
+ public void testDumpsys_withIcons() throws IOException {
+ testIcons();
// Dump after having some icons.
dumpsysOnLogcat("test1", /* force= */ true);
}
- public void ManifestShortcut_publishOnUnlockUser() {
+ public void testManifestShortcut_publishOnUnlockUser() {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
@@ -7137,7 +7138,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertNull(mService.getPackageShortcutForTest(LAUNCHER_1, USER_10));
}
- public void ManifestShortcut_publishOnBroadcast() {
+ public void testManifestShortcut_publishOnBroadcast() {
// First, no packages are installed.
uninstallPackage(USER_10, CALLING_PACKAGE_1);
uninstallPackage(USER_10, CALLING_PACKAGE_2);
@@ -7393,7 +7394,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_missingMandatoryFields() {
+ public void testManifestShortcuts_missingMandatoryFields() {
// Start with no apps installed.
uninstallPackage(USER_10, CALLING_PACKAGE_1);
uninstallPackage(USER_10, CALLING_PACKAGE_2);
@@ -7462,7 +7463,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_intentDefinitions() {
+ public void testManifestShortcuts_intentDefinitions() {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_4);
@@ -7604,7 +7605,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_checkAllFields() {
+ public void testManifestShortcuts_checkAllFields() {
mService.handleUnlockUser(USER_10);
// Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -7709,7 +7710,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_localeChange() throws InterruptedException {
+ public void testManifestShortcuts_localeChange() throws InterruptedException {
mService.handleUnlockUser(USER_10);
// Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -7813,7 +7814,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_updateAndDisabled_notPinned() {
+ public void testManifestShortcuts_updateAndDisabled_notPinned() {
mService.handleUnlockUser(USER_10);
// First, just publish a manifest shortcut.
@@ -7853,7 +7854,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_updateAndDisabled_pinned() {
+ public void testManifestShortcuts_updateAndDisabled_pinned() {
mService.handleUnlockUser(USER_10);
// First, just publish a manifest shortcut.
@@ -7909,7 +7910,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_duplicateInSingleActivity() {
+ public void testManifestShortcuts_duplicateInSingleActivity() {
mService.handleUnlockUser(USER_10);
// The XML has two shortcuts with the same ID.
@@ -7934,7 +7935,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ManifestShortcuts_duplicateInTwoActivities() {
+ public void testManifestShortcuts_duplicateInTwoActivities() {
mService.handleUnlockUser(USER_10);
// ShortcutActivity has shortcut ms1
@@ -7986,7 +7987,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Manifest shortcuts cannot override shortcuts that were published via the APIs.
*/
- public void ManifestShortcuts_cannotOverrideNonManifest() {
+ public void testManifestShortcuts_cannotOverrideNonManifest() {
mService.handleUnlockUser(USER_10);
// Create a non-pinned dynamic shortcut and a non-dynamic pinned shortcut.
@@ -8059,7 +8060,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Make sure the APIs won't work on manifest shortcuts.
*/
- public void ManifestShortcuts_immutable() {
+ public void testManifestShortcuts_immutable() {
mService.handleUnlockUser(USER_10);
// Create a non-pinned manifest shortcut, a pinned shortcut that was originally
@@ -8152,7 +8153,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/**
* Make sure the APIs won't work on manifest shortcuts.
*/
- public void ManifestShortcuts_tooMany() {
+ public void testManifestShortcuts_tooMany() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
@@ -8171,7 +8172,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void MaxShortcutCount_set() {
+ public void testMaxShortcutCount_set() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
@@ -8252,7 +8253,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void MaxShortcutCount_add() {
+ public void testMaxShortcutCount_add() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
@@ -8379,7 +8380,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void MaxShortcutCount_update() {
+ public void testMaxShortcutCount_update() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
@@ -8470,7 +8471,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ShortcutsPushedOutByManifest() {
+ public void testShortcutsPushedOutByManifest() {
// Change the max number of shortcuts.
mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
@@ -8578,7 +8579,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void ReturnedByServer() {
+ public void testReturnedByServer() {
// Package 1 updated, with manifest shortcuts.
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -8624,7 +8625,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void IsForegroundDefaultLauncher_true() {
+ public void testIsForegroundDefaultLauncher_true() {
// random uid in the USER_10 range.
final int uid = 1000024;
@@ -8635,7 +8636,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
- public void IsForegroundDefaultLauncher_defaultButNotForeground() {
+ public void testIsForegroundDefaultLauncher_defaultButNotForeground() {
// random uid in the USER_10 range.
final int uid = 1000024;
@@ -8645,7 +8646,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertFalse(mInternal.isForegroundDefaultLauncher("default", uid));
}
- public void IsForegroundDefaultLauncher_foregroundButNotDefault() {
+ public void testIsForegroundDefaultLauncher_foregroundButNotDefault() {
// random uid in the USER_10 range.
final int uid = 1000024;
@@ -8655,7 +8656,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertFalse(mInternal.isForegroundDefaultLauncher("another", uid));
}
- public void ParseShareTargetsFromManifest() {
+ public void testParseShareTargetsFromManifest() {
// These values must exactly match the content of shortcuts_share_targets.xml resource
List<ShareTargetInfo> expectedValues = new ArrayList<>();
expectedValues.add(new ShareTargetInfo(
@@ -8707,7 +8708,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
}
- public void ShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
+ public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
List<ShareTargetInfo> expectedValues = new ArrayList<>();
expectedValues.add(new ShareTargetInfo(
new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
@@ -8773,7 +8774,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
}
- public void IsSharingShortcut() throws IntentFilter.MalformedMimeTypeException {
+ public void testIsSharingShortcut() throws IntentFilter.MalformedMimeTypeException {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_share_targets);
@@ -8823,7 +8824,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
filter_any));
}
- public void IsSharingShortcut_PinnedAndCachedOnlyShortcuts()
+ public void testIsSharingShortcut_PinnedAndCachedOnlyShortcuts()
throws IntentFilter.MalformedMimeTypeException {
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -8880,7 +8881,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
filter_any));
}
- public void AddingShortcuts_ExcludesHiddenFromLauncherShortcuts() {
+ public void testAddingShortcuts_ExcludesHiddenFromLauncherShortcuts() {
final ShortcutInfo s1 = makeShortcutExcludedFromLauncher("s1");
final ShortcutInfo s2 = makeShortcutExcludedFromLauncher("s2");
final ShortcutInfo s3 = makeShortcutExcludedFromLauncher("s3");
@@ -8901,7 +8902,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void UpdateShortcuts_ExcludesHiddenFromLauncherShortcuts() {
+ public void testUpdateShortcuts_ExcludesHiddenFromLauncherShortcuts() {
final ShortcutInfo s1 = makeShortcut("s1");
final ShortcutInfo s2 = makeShortcut("s2");
final ShortcutInfo s3 = makeShortcut("s3");
@@ -8914,7 +8915,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
- public void PinHiddenShortcuts_ThrowsException() {
+ public void testPinHiddenShortcuts_ThrowsException() {
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
assertThrown(IllegalArgumentException.class, () -> {
mManager.requestPinShortcut(makeShortcutExcludedFromLauncher("s1"), null);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java
index af7f703e9c31..b33233107766 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ConditionProvidersTest.java
@@ -101,9 +101,12 @@ public class ConditionProvidersTest extends UiServiceTestCase {
mProviders.notifyConditions("package", msi, conditionsToNotify);
- verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]));
- verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1]));
- verify(mCallback).onConditionChanged(eq(Uri.parse("c")), eq(conditionsToNotify[2]));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]),
+ eq(100));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1]),
+ eq(100));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("c")), eq(conditionsToNotify[2]),
+ eq(100));
verifyNoMoreInteractions(mCallback);
}
@@ -121,8 +124,10 @@ public class ConditionProvidersTest extends UiServiceTestCase {
mProviders.notifyConditions("package", msi, conditionsToNotify);
- verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]));
- verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1]));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]),
+ eq(100));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[1]),
+ eq(100));
verifyNoMoreInteractions(mCallback);
}
@@ -141,8 +146,10 @@ public class ConditionProvidersTest extends UiServiceTestCase {
mProviders.notifyConditions("package", msi, conditionsToNotify);
- verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]));
- verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[3]));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("a")), eq(conditionsToNotify[0]),
+ eq(100));
+ verify(mCallback).onConditionChanged(eq(Uri.parse("b")), eq(conditionsToNotify[3]),
+ eq(100));
verifyNoMoreInteractions(mCallback);
}
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 301165f8151d..7885c9b902e2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -11213,7 +11213,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// Representative used to verify getCallingZenUser().
mBinderService.getAutomaticZenRules();
- verify(zenModeHelper).getAutomaticZenRules(eq(UserHandle.CURRENT));
+ verify(zenModeHelper).getAutomaticZenRules(eq(UserHandle.CURRENT), anyInt());
}
@Test
@@ -11225,7 +11225,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// Representative used to verify getCallingZenUser().
mBinderService.getAutomaticZenRules();
- verify(zenModeHelper).getAutomaticZenRules(eq(Binder.getCallingUserHandle()));
+ verify(zenModeHelper).getAutomaticZenRules(eq(Binder.getCallingUserHandle()), anyInt());
}
/** Prepares for a zen-related test that uses a mocked {@link ZenModeHelper}. */
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 1884bbd39bb9..6ef078b6da8a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -291,7 +291,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return FlagsParameterization.allCombinationsOf(FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING);
+ return FlagsParameterization.allCombinationsOf(FLAG_MODES_UI, FLAG_BACKUP_RESTORE_LOGGING,
+ com.android.server.notification.Flags.FLAG_FIX_CALLING_UID_FROM_CPS);
}
public ZenModeHelperTest(FlagsParameterization flags) {
@@ -2617,7 +2618,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
@Test
- public void testSetAutomaticZenRuleState_nullPkg() {
+ public void testSetAutomaticZenRuleStateFromConditionProvider_nullPkg() {
AutomaticZenRule zenRule = new AutomaticZenRule("name",
null,
new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"),
@@ -2627,10 +2628,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
String id = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT, null, zenRule,
ORIGIN_APP, "test", CUSTOM_PKG_UID);
- mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, zenRule.getConditionId(),
- new Condition(zenRule.getConditionId(), "", STATE_TRUE),
- ORIGIN_APP,
- CUSTOM_PKG_UID);
+ mZenModeHelper.setAutomaticZenRuleStateFromConditionProvider(UserHandle.CURRENT,
+ zenRule.getConditionId(), new Condition(zenRule.getConditionId(), "", STATE_TRUE),
+ ORIGIN_APP, CUSTOM_PKG_UID);
ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
assertEquals(STATE_TRUE, ruleInConfig.condition.state);
@@ -2726,8 +2726,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ORIGIN_SYSTEM, "test", SYSTEM_UID);
Condition condition = new Condition(sharedUri, "", STATE_TRUE);
- mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, sharedUri, condition,
- ORIGIN_SYSTEM, SYSTEM_UID);
+ mZenModeHelper.setAutomaticZenRuleStateFromConditionProvider(UserHandle.CURRENT, sharedUri,
+ condition, ORIGIN_SYSTEM, SYSTEM_UID);
for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
if (rule.id.equals(id)) {
@@ -2741,8 +2741,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
condition = new Condition(sharedUri, "", STATE_FALSE);
- mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, sharedUri, condition,
- ORIGIN_SYSTEM, SYSTEM_UID);
+ mZenModeHelper.setAutomaticZenRuleStateFromConditionProvider(UserHandle.CURRENT, sharedUri,
+ condition, ORIGIN_SYSTEM, SYSTEM_UID);
for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
if (rule.id.equals(id)) {
@@ -2780,9 +2780,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(zde)
.build(),
- ORIGIN_APP, "reasons", 0);
+ ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(
new ZenDeviceEffects.Builder()
.setShouldDisplayGrayscale(true)
@@ -2814,9 +2815,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(zde)
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(zde);
}
@@ -2845,7 +2847,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ORIGIN_USER_IN_SYSTEMUI,
"reasons", 0);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(zde);
}
@@ -2863,7 +2866,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(original)
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
ZenDeviceEffects updateFromApp = new ZenDeviceEffects.Builder()
.setShouldUseNightMode(true) // Good
@@ -2875,9 +2878,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(updateFromApp)
.build(),
- ORIGIN_APP, "reasons", 0);
+ ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(
new ZenDeviceEffects.Builder()
.setShouldUseNightMode(true) // From update.
@@ -2898,7 +2902,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(original)
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
ZenDeviceEffects updateFromSystem = new ZenDeviceEffects.Builder()
.setShouldUseNightMode(true) // Good
@@ -2908,9 +2912,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
new AutomaticZenRule.Builder("Rule", CONDITION_ID)
.setDeviceEffects(updateFromSystem)
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(updateFromSystem);
}
@@ -2926,7 +2931,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setOwner(OWNER)
.setDeviceEffects(original)
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
ZenDeviceEffects updateFromUser = new ZenDeviceEffects.Builder()
.setShouldUseNightMode(true)
@@ -2939,9 +2944,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
new AutomaticZenRule.Builder("Rule", CONDITION_ID)
.setDeviceEffects(updateFromUser)
.build(),
- ORIGIN_USER_IN_SYSTEMUI, "reasons", 0);
+ ORIGIN_USER_IN_SYSTEMUI, "reasons", SYSTEM_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
assertThat(savedRule.getDeviceEffects()).isEqualTo(updateFromUser);
}
@@ -2959,15 +2965,16 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // default is stars
.build())
.build(),
- ORIGIN_APP, "reasons", 0);
+ ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId,
new AutomaticZenRule.Builder("Rule", CONDITION_ID)
// no zen policy
.build(),
- ORIGIN_APP, "reasons", 0);
+ ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls())
.isEqualTo(STATE_DISALLOW);
}
@@ -2988,7 +2995,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.allowReminders(true)
.build())
.build(),
- ORIGIN_SYSTEM, "reasons", 0);
+ ORIGIN_SYSTEM, "reasons", SYSTEM_UID);
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId,
new AutomaticZenRule.Builder("Rule", CONDITION_ID)
@@ -2996,9 +3003,10 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
.build())
.build(),
- ORIGIN_APP, "reasons", 0);
+ ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
- AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls())
.isEqualTo(STATE_ALLOW); // from update
assertThat(savedRule.getZenPolicy().getPriorityCallSenders())
@@ -4441,7 +4449,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
rule.triggerDescription = TRIGGER_DESC;
mZenModeHelper.mConfig.automaticRules.put(rule.id, rule);
- AutomaticZenRule actual = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, rule.id);
+ AutomaticZenRule actual = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, rule.id,
+ SYSTEM_UID);
assertEquals(NAME, actual.getName());
assertEquals(OWNER, actual.getOwner());
@@ -4508,16 +4517,17 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// Checks the name can be changed by the app because the user has not modified it.
AutomaticZenRule azrUpdate = new AutomaticZenRule.Builder(rule)
.setName("NewName")
.build();
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate, ORIGIN_APP,
- "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ "reason", CUSTOM_PKG_UID);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
assertThat(rule.getName()).isEqualTo("NewName");
// The user modifies some other field in the rule, which makes the rule as a whole not
@@ -4534,8 +4544,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setName("NewAppName")
.build();
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate, ORIGIN_APP,
- "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ "reason", CUSTOM_PKG_UID);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
assertThat(rule.getName()).isEqualTo("NewAppName");
// The user modifies the name.
@@ -4544,7 +4554,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
assertThat(rule.getName()).isEqualTo("UserProvidedName");
// The app is no longer able to modify the name.
@@ -4552,8 +4562,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.setName("NewAppName")
.build();
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate, ORIGIN_APP,
- "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ "reason", CUSTOM_PKG_UID);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
assertThat(rule.getName()).isEqualTo("UserProvidedName");
}
@@ -4568,8 +4578,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// Modifies the filter, icon, zen policy, and device effects
ZenPolicy policy = new ZenPolicy.Builder(rule.getZenPolicy())
@@ -4589,7 +4600,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Update the rule with the AZR from origin user.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
// UPDATE_ORIGIN_USER should change the bitmask and change the values.
assertThat(rule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY);
@@ -4625,8 +4636,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// Modifies the icon, zen policy and device effects
ZenPolicy policy = new ZenPolicy.Builder(rule.getZenPolicy())
@@ -4646,7 +4658,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Update the rule with the AZR from origin systemUI.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate, ORIGIN_SYSTEM,
"reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
// UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI should change the value but NOT update the bitmask.
assertThat(rule.getIconResId()).isEqualTo(ICON_RES_ID);
@@ -4675,8 +4687,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
ZenPolicy policy = new ZenPolicy.Builder()
.allowReminders(true)
@@ -4693,7 +4706,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Since the rule is not already user modified, UPDATE_ORIGIN_APP can modify the rule.
// The bitmask is not modified.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azrUpdate, ORIGIN_APP,
- "reason", SYSTEM_UID);
+ "reason", CUSTOM_PKG_UID);
ZenRule storedRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
assertThat(storedRule.userModifiedFields).isEqualTo(0);
@@ -4717,9 +4730,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Zen rule update coming from the app again. This cannot fully update the rule, because
// the rule is already considered user modified.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleIdUser, azrUpdate, ORIGIN_APP,
- "reason", SYSTEM_UID);
+ "reason", CUSTOM_PKG_UID);
AutomaticZenRule ruleUser = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- ruleIdUser);
+ ruleIdUser, CUSTOM_PKG_UID);
// The app can only change the value if the rule is not already user modified,
// so the rule is not changed, and neither is the bitmask.
@@ -4749,8 +4762,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build())
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// The values are modified but the bitmask is not.
assertThat(rule.getZenPolicy().getPriorityCategoryReminders())
@@ -4771,7 +4785,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
AutomaticZenRule azr = new AutomaticZenRule.Builder(azrBase)
// Sets Device Effects to null
@@ -4781,8 +4795,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Zen rule update coming from app, but since the rule isn't already
// user modified, it can be updated.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azr, ORIGIN_APP, "reason",
- SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// When AZR's ZenDeviceEffects is null, the updated rule's device effects are kept.
assertThat(rule.getDeviceEffects()).isEqualTo(zde);
@@ -4797,8 +4812,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
AutomaticZenRule azr = new AutomaticZenRule.Builder(azrBase)
// Set zen policy to null
@@ -4808,8 +4822,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Zen rule update coming from app, but since the rule isn't already
// user modified, it can be updated.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azr, ORIGIN_APP, "reason",
- SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// When AZR's ZenPolicy is null, we expect the updated rule's policy to be unchanged
// (equivalent to the provided policy, with additional fields filled in with defaults).
@@ -4829,8 +4844,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
// Create a fully populated ZenPolicy.
ZenPolicy policy = new ZenPolicy.Builder()
@@ -4860,7 +4874,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Default config defined in getDefaultConfigParser() is used as the original rule.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azr,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
// New ZenPolicy differs from the default config
assertThat(rule.getZenPolicy()).isNotNull();
@@ -4890,8 +4905,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
// Adds the rule using the app, to avoid having any user modified bits set.
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
- mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", SYSTEM_UID);
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ mContext.getPackageName(), azrBase, ORIGIN_APP, "reason", CUSTOM_PKG_UID);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
ZenDeviceEffects deviceEffects = new ZenDeviceEffects.Builder()
.setShouldDisplayGrayscale(true)
@@ -4903,7 +4919,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Applies the update to the rule.
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, azr,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID);
// New ZenDeviceEffects is used; all fields considered set, since previously were null.
assertThat(rule.getDeviceEffects()).isNotNull();
@@ -5286,7 +5302,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, update,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- AutomaticZenRule result = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule result = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
assertThat(result).isNotNull();
assertThat(result.getOwner().getClassName()).isEqualTo("brand.new.cps");
}
@@ -5306,7 +5323,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId, update,
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
- AutomaticZenRule result = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule result = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID);
assertThat(result).isNotNull();
assertThat(result.getOwner().getClassName()).isEqualTo("old.third.party.cps");
}
@@ -5518,8 +5536,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
mContext.getPackageName(), rule, ORIGIN_APP, "add it", CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId).getCreationTime())
- .isEqualTo(1000);
+ assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID).getCreationTime()).isEqualTo(1000);
// User customizes it.
AutomaticZenRule userUpdate = new AutomaticZenRule.Builder(rule)
@@ -5546,7 +5564,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// - ZenPolicy is the one that the user had set.
// - rule still has the user-modified fields.
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getCreationTime()).isEqualTo(1000); // And not 3000.
assertThat(newRuleId).isEqualTo(ruleId);
assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);
@@ -5575,8 +5593,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
mContext.getPackageName(), rule, ORIGIN_APP, "add it", CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId).getCreationTime())
- .isEqualTo(1000);
+ assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID).getCreationTime()).isEqualTo(1000);
// App deletes it.
mTestClock.advanceByMillis(1000);
@@ -5592,7 +5610,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Verify that the rule was recreated. This means id and creation time are new.
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getCreationTime()).isEqualTo(3000);
assertThat(newRuleId).isNotEqualTo(ruleId);
}
@@ -5609,8 +5627,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
mContext.getPackageName(), rule, ORIGIN_APP, "add it", CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId).getCreationTime())
- .isEqualTo(1000);
+ assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID)
+ .getCreationTime()).isEqualTo(1000);
// User customizes it.
mTestClock.advanceByMillis(1000);
@@ -5637,7 +5655,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Verify that the rule was recreated. This means id and creation time are new, and the rule
// matches the latest data supplied to addAZR.
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getCreationTime()).isEqualTo(4000);
assertThat(newRuleId).isNotEqualTo(ruleId);
assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY);
@@ -5660,8 +5678,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.build();
String ruleId = mZenModeHelper.addAutomaticZenRule(UserHandle.CURRENT,
mContext.getPackageName(), rule, ORIGIN_APP, "add it", CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId).getCreationTime())
- .isEqualTo(1000);
+ assertThat(mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ CUSTOM_PKG_UID).getCreationTime()).isEqualTo(1000);
// User customizes it.
mTestClock.advanceByMillis(1000);
@@ -5686,7 +5704,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Verify that the rule was recreated. This means id and creation time are new.
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getCreationTime()).isEqualTo(4000);
assertThat(newRuleId).isNotEqualTo(ruleId);
}
@@ -5728,7 +5746,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// Verify that the rule was NOT restored:
assertThat(newRuleId).isNotEqualTo(ruleId);
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);
assertThat(finalRule.getOwner()).isEqualTo(new ComponentName("second", "owner"));
@@ -5869,7 +5887,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// The rule is restored...
assertThat(newRuleId).isEqualTo(ruleId);
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);
// ... but it is NOT active
@@ -5923,7 +5941,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
// The rule is restored...
assertThat(newRuleId).isEqualTo(ruleId);
AutomaticZenRule finalRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- newRuleId);
+ newRuleId, CUSTOM_PKG_UID);
assertThat(finalRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALARMS);
// ... but it is NEITHER active NOR snoozed.
@@ -6005,22 +6023,22 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ORIGIN_APP, "reasons", CUSTOM_PKG_UID);
// Null condition -> STATE_FALSE
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id))
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id, CUSTOM_PKG_UID))
.isEqualTo(Condition.STATE_FALSE);
mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, id, CONDITION_TRUE, ORIGIN_APP,
CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id))
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id, CUSTOM_PKG_UID))
.isEqualTo(Condition.STATE_TRUE);
mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, id, CONDITION_FALSE, ORIGIN_APP,
CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id))
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id, CUSTOM_PKG_UID))
.isEqualTo(Condition.STATE_FALSE);
mZenModeHelper.removeAutomaticZenRule(UserHandle.CURRENT, id, ORIGIN_APP, "",
CUSTOM_PKG_UID);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id))
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, id, CUSTOM_PKG_UID))
.isEqualTo(Condition.STATE_UNKNOWN);
}
@@ -6036,8 +6054,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.setConfig(config, null, ORIGIN_INIT, "", SYSTEM_UID);
assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, "systemRule"))
- .isEqualTo(Condition.STATE_UNKNOWN);
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, "systemRule",
+ CUSTOM_PKG_UID)).isEqualTo(Condition.STATE_UNKNOWN);
}
@Test
@@ -6063,7 +6081,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
@Test
@EnableFlags(FLAG_MODES_API)
- public void setAutomaticZenRuleState_conditionForNotOwnedRule_ignored() {
+ public void setAutomaticZenRuleStateFromConditionProvider_conditionForNotOwnedRule_ignored() {
// Assume existence of an other-package-owned rule that is currently ACTIVE.
assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_OFF);
ZenRule otherRule = newZenRule("another.package", Instant.now(), null);
@@ -6075,7 +6093,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertThat(mZenModeHelper.getZenMode()).isEqualTo(ZEN_MODE_ALARMS);
// Should be ignored.
- mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, otherRule.conditionId,
+ mZenModeHelper.setAutomaticZenRuleStateFromConditionProvider(UserHandle.CURRENT,
+ otherRule.conditionId,
new Condition(otherRule.conditionId, "off", Condition.STATE_FALSE),
ORIGIN_APP, CUSTOM_PKG_UID);
@@ -6182,7 +6201,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// From user, update that rule's interruption filter.
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
.setInterruptionFilter(INTERRUPTION_FILTER_ALARMS)
.build();
@@ -6214,7 +6234,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
.isEqualTo(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
// From user, update something in that rule, but not the interruption filter.
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
.setName("Renamed")
.build();
@@ -6315,7 +6336,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
String ruleId = ZenModeConfig.implicitRuleId(mContext.getPackageName());
// User chooses a new name.
- AutomaticZenRule azr = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule azr = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId,
new AutomaticZenRule.Builder(azr).setName("User chose this").build(),
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
@@ -6414,7 +6436,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.mConfig.getZenPolicy()).allowMedia(true).build();
// From user, update that rule's policy.
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
ZenPolicy userUpdateZenPolicy = new ZenPolicy.Builder().disallowAllSounds()
.allowAlarms(true).build();
AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
@@ -6456,7 +6479,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.mConfig.getZenPolicy()).allowMedia(true).build();
// From user, update something in that rule, but not the ZenPolicy.
- AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule)
.setName("Rule renamed, not touching policy")
.build();
@@ -6509,7 +6533,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
String ruleId = ZenModeConfig.implicitRuleId(mContext.getPackageName());
// User chooses a new name.
- AutomaticZenRule azr = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId);
+ AutomaticZenRule azr = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID);
mZenModeHelper.updateAutomaticZenRule(UserHandle.CURRENT, ruleId,
new AutomaticZenRule.Builder(azr).setName("User chose this").build(),
ORIGIN_USER_IN_SYSTEMUI, "reason", SYSTEM_UID);
@@ -6645,7 +6670,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
new AutomaticZenRule.Builder("Rule", CONDITION_ID).setIconResId(resourceId).build(),
ORIGIN_APP, "reason", CUSTOM_PKG_UID);
AutomaticZenRule storedRule = mZenModeHelper.getAutomaticZenRule(UserHandle.CURRENT,
- ruleId);
+ ruleId, CUSTOM_PKG_UID);
assertThat(storedRule.getIconResId()).isEqualTo(0);
}
@@ -7087,8 +7112,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID);
implicitRule = getZenRule(implicitRuleId(CUSTOM_PKG_NAME));
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, implicitRule.id))
- .isEqualTo(STATE_TRUE);
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, implicitRule.id,
+ CUSTOM_PKG_UID)).isEqualTo(STATE_TRUE);
assertThat(implicitRule.isActive()).isTrue();
assertThat(implicitRule.getConditionOverride()).isEqualTo(OVERRIDE_NONE);
}
@@ -7108,8 +7133,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID);
implicitRule = getZenRule(implicitRuleId(CUSTOM_PKG_NAME));
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, implicitRule.id))
- .isEqualTo(STATE_FALSE);
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, implicitRule.id,
+ CUSTOM_PKG_UID)).isEqualTo(STATE_FALSE);
assertThat(implicitRule.isActive()).isFalse();
assertThat(implicitRule.getConditionOverride()).isEqualTo(OVERRIDE_NONE);
}
@@ -7177,7 +7202,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, ruleId,
new Condition(rule.getConditionId(), "manual-on", STATE_TRUE, SOURCE_USER_ACTION),
ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId, SYSTEM_UID))
.isEqualTo(STATE_TRUE);
ZenRule zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_ACTIVATE);
@@ -7192,14 +7217,14 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
if (Flags.modesUi()) {
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
- .isEqualTo(STATE_TRUE);
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID)).isEqualTo(STATE_TRUE);
zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_ACTIVATE);
assertThat(zenRule.condition).isNull();
} else {
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
- .isEqualTo(STATE_FALSE);
+ assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId,
+ SYSTEM_UID)).isEqualTo(STATE_FALSE);
}
}
@@ -7218,7 +7243,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mZenModeHelper.setAutomaticZenRuleState(UserHandle.CURRENT, ruleId,
new Condition(rule.getConditionId(), "snooze", STATE_FALSE, SOURCE_USER_ACTION),
ORIGIN_USER_IN_SYSTEMUI, SYSTEM_UID);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
+ assertThat(
+ mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID))
.isEqualTo(STATE_FALSE);
ZenRule zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_DEACTIVATE);
@@ -7232,7 +7258,8 @@ public class ZenModeHelperTest extends UiServiceTestCase {
TypedXmlPullParser parser = getParserForByteStream(xmlBytes);
mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL, null);
- assertThat(mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId))
+ assertThat(
+ mZenModeHelper.getAutomaticZenRuleState(UserHandle.CURRENT, ruleId, CUSTOM_PKG_UID))
.isEqualTo(STATE_TRUE);
zenRule = mZenModeHelper.mConfig.automaticRules.get(ruleId);
assertThat(zenRule.getConditionOverride()).isEqualTo(OVERRIDE_NONE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java
index b8d554b405d1..98a4fb3c473f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatResizeOverridesTest.java
@@ -184,12 +184,12 @@ public class AppCompatResizeOverridesTest extends WindowTestsBase {
void checkShouldOverrideForceResizeApp(boolean expected) {
Assert.assertEquals(expected, activity().top().mAppCompatController
- .getAppCompatResizeOverrides().shouldOverrideForceResizeApp());
+ .getResizeOverrides().shouldOverrideForceResizeApp());
}
void checkShouldOverrideForceNonResizeApp(boolean expected) {
Assert.assertEquals(expected, activity().top().mAppCompatController
- .getAppCompatResizeOverrides().shouldOverrideForceNonResizeApp());
+ .getResizeOverrides().shouldOverrideForceNonResizeApp());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index b6e393d7be0c..03d904283e83 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -342,8 +342,8 @@ public class AppTransitionTests extends WindowTestsBase {
public void testCancelRemoteAnimationWhenFreeze() {
final DisplayContent dc = createNewDisplay(Display.STATE_ON);
doReturn(false).when(dc).onDescendantOrientationChanged(any());
- final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
- dc, "exiting app");
+ final WindowState exitingAppWindow = newWindowBuilder("exiting app",
+ TYPE_BASE_APPLICATION).setDisplay(dc).build();
final ActivityRecord exitingActivity = exitingAppWindow.mActivityRecord;
// Wait until everything in animation handler get executed to prevent the exiting window
// from being removed during WindowSurfacePlacer Traversal.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
index 14276ae21899..7033d79d0ee1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
@@ -266,10 +266,10 @@ public class DisplayContentDeferredUpdateTests extends WindowTestsBase {
mSetFlagsRule.enableFlags(Flags.FLAG_WAIT_FOR_TRANSITION_ON_DISPLAY_SWITCH);
prepareSecondaryDisplay();
- final WindowState defaultDisplayWindow = createWindow(/* parent= */ null,
- TYPE_BASE_APPLICATION, mDisplayContent, "DefaultDisplayWindow");
- final WindowState secondaryDisplayWindow = createWindow(/* parent= */ null,
- TYPE_BASE_APPLICATION, mSecondaryDisplayContent, "SecondaryDisplayWindow");
+ final WindowState defaultDisplayWindow = newWindowBuilder("DefaultDisplayWindow",
+ TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
+ final WindowState secondaryDisplayWindow = newWindowBuilder("SecondaryDisplayWindow",
+ TYPE_BASE_APPLICATION).setDisplay(mSecondaryDisplayContent).build();
makeWindowVisibleAndNotDrawn(defaultDisplayWindow, secondaryDisplayWindow);
// Mark as display switching only for the default display as we filter out
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index bd15bc42e811..347d1bc1becc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -379,13 +379,11 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);
- final WindowState firstActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
- "firstActivityWin");
+ final WindowState firstActivityWin = newWindowBuilder("firstActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mFirstActivity).build();
spyOn(firstActivityWin);
- final WindowState secondActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity,
- "firstActivityWin");
+ final WindowState secondActivityWin = newWindowBuilder("secondActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mSecondActivity).build();
spyOn(secondActivityWin);
// firstActivityWin should be the target
@@ -424,13 +422,11 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
setupImeWindow();
final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);
- final WindowState firstActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
- "firstActivityWin");
+ final WindowState firstActivityWin = newWindowBuilder("firstActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mFirstActivity).build();
spyOn(firstActivityWin);
- final WindowState secondActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity,
- "secondActivityWin");
+ final WindowState secondActivityWin = newWindowBuilder("secondActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mSecondActivity).build();
spyOn(secondActivityWin);
// firstActivityWin should be the target
@@ -464,9 +460,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);
- final WindowState firstActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
- "firstActivityWin");
+ final WindowState firstActivityWin = newWindowBuilder("firstActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mFirstActivity).build();
spyOn(firstActivityWin);
// firstActivityWin should be the target
doReturn(true).when(firstActivityWin).canBeImeTarget();
@@ -499,9 +494,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
// firstActivityWin should be the target
- final WindowState firstActivityWin =
- createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
- "firstActivityWin");
+ final WindowState firstActivityWin = newWindowBuilder("firstActivityWin",
+ TYPE_APPLICATION_STARTING).setWindowToken(mFirstActivity).build();
spyOn(firstActivityWin);
doReturn(true).when(firstActivityWin).canBeImeTarget();
WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);
@@ -560,8 +554,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
}
private void setupImeWindow() {
- final WindowState imeWindow = createWindow(null /* parent */,
- TYPE_INPUT_METHOD, mDisplay, "mImeWindow");
+ final WindowState imeWindow = newWindowBuilder("mImeWindow", TYPE_INPUT_METHOD).setDisplay(
+ mDisplay).build();
imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
mDisplay.mInputMethodWindow = imeWindow;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index dc4adcc4315b..299717393028 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -878,8 +878,10 @@ public class TaskFragmentTest extends WindowTestsBase {
.build();
final ActivityRecord activity0 = tf0.getTopMostActivity();
final ActivityRecord activity1 = tf1.getTopMostActivity();
- final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, activity0, "win0");
- final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity1, "win1");
+ final WindowState win0 = newWindowBuilder("win0", TYPE_BASE_APPLICATION).setWindowToken(
+ activity0).build();
+ final WindowState win1 = newWindowBuilder("win1", TYPE_BASE_APPLICATION).setWindowToken(
+ activity1).build();
doReturn(false).when(mDisplayContent).shouldImeAttachedToApp();
mDisplayContent.setImeInputTarget(win0);
@@ -1174,8 +1176,8 @@ public class TaskFragmentTest extends WindowTestsBase {
}
private WindowState createAppWindow(ActivityRecord app, String name) {
- final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, app, name,
- 0 /* ownerId */, false /* ownerCanAddInternalSystemWindow */, new TestIWindow());
+ final WindowState win = newWindowBuilder(name, TYPE_BASE_APPLICATION).setWindowToken(
+ app).setClientWindow(new TestIWindow()).build();
mWm.mWindowMap.put(win.mClient.asBinder(), win);
return win;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index f145b40d2292..f9250f9ecf5d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -63,7 +63,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testAppRemoved() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mCache.putSnapshot(window.getTask(), createSnapshot());
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
mCache.onAppRemoved(window.mActivityRecord);
@@ -72,7 +72,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testAppDied() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mCache.putSnapshot(window.getTask(), createSnapshot());
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
mCache.onAppDied(window.mActivityRecord);
@@ -81,7 +81,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testTaskRemoved() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mCache.putSnapshot(window.getTask(), createSnapshot());
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
mCache.onIdRemoved(window.getTask().mTaskId);
@@ -90,7 +90,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testReduced_notCached() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mPersister.persistSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
assertNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
@@ -105,7 +105,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testRestoreFromDisk() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mPersister.persistSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
assertNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
@@ -117,7 +117,7 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
@Test
public void testClearCache() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mCache.putSnapshot(window.getTask(), mSnapshot);
assertEquals(mSnapshot, mCache.getSnapshot(window.getTask().mTaskId,
false /* isLowResolution */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index c6b2a6b8d42f..1bca53aff034 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -74,8 +74,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
@Test
public void testGetClosingApps_closing() {
- final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
- "closingWindow");
+ final WindowState closingWindow = newWindowBuilder("closingWindow",
+ FIRST_APPLICATION_WINDOW).build();
closingWindow.mActivityRecord.commitVisibility(
false /* visible */, true /* performLayout */);
final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
@@ -88,8 +88,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
@Test
public void testGetClosingApps_notClosing() {
- final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
- "closingWindow");
+ final WindowState closingWindow = newWindowBuilder("closingWindow",
+ FIRST_APPLICATION_WINDOW).build();
final WindowState openingWindow = createAppWindow(closingWindow.getTask(),
FIRST_APPLICATION_WINDOW, "openingWindow");
closingWindow.mActivityRecord.commitVisibility(
@@ -105,8 +105,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
@Test
public void testGetClosingApps_skipClosingAppsSnapshotTasks() {
- final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
- "closingWindow");
+ final WindowState closingWindow = newWindowBuilder("closingWindow",
+ FIRST_APPLICATION_WINDOW).build();
closingWindow.mActivityRecord.commitVisibility(
false /* visible */, true /* performLayout */);
final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
@@ -133,19 +133,19 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
@Test
public void testGetSnapshotMode() {
- final WindowState disabledWindow = createWindow(null,
- FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
+ final WindowState disabledWindow = newWindowBuilder("disabledWindow",
+ FIRST_APPLICATION_WINDOW).setDisplay(mDisplayContent).build();
disabledWindow.mActivityRecord.setRecentsScreenshotEnabled(false);
assertEquals(SNAPSHOT_MODE_APP_THEME,
mWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
- final WindowState normalWindow = createWindow(null,
- FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow");
+ final WindowState normalWindow = newWindowBuilder("normalWindow",
+ FIRST_APPLICATION_WINDOW).setDisplay(mDisplayContent).build();
assertEquals(SNAPSHOT_MODE_REAL,
mWm.mTaskSnapshotController.getSnapshotMode(normalWindow.getTask()));
- final WindowState secureWindow = createWindow(null,
- FIRST_APPLICATION_WINDOW, mDisplayContent, "secureWindow");
+ final WindowState secureWindow = newWindowBuilder("secureWindow",
+ FIRST_APPLICATION_WINDOW).setDisplay(mDisplayContent).build();
secureWindow.mAttrs.flags |= FLAG_SECURE;
assertEquals(SNAPSHOT_MODE_APP_THEME,
mWm.mTaskSnapshotController.getSnapshotMode(secureWindow.getTask()));
@@ -297,8 +297,8 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
spyOn(mWm.mTaskSnapshotController);
doReturn(false).when(mWm.mTaskSnapshotController).shouldDisableSnapshots();
- final WindowState normalWindow = createWindow(null,
- FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow");
+ final WindowState normalWindow = newWindowBuilder("normalWindow",
+ FIRST_APPLICATION_WINDOW).setDisplay(mDisplayContent).build();
final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
.setTopActivityComponent(normalWindow.mActivityRecord.mActivityComponent).build();
doReturn(snapshot).when(mWm.mTaskSnapshotController).snapshot(any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
index 9bde0663d4a3..51ea498811fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
@@ -41,7 +41,7 @@ import java.io.File;
* Test class for {@link TaskSnapshotPersister} and {@link AppSnapshotLoader}
*
* Build/Install/Run:
- * atest TaskSnapshotPersisterLoaderTest
+ * atest TaskSnapshotLowResDisabledTest
*/
@MediumTest
@Presubmit
@@ -126,7 +126,7 @@ public class TaskSnapshotLowResDisabledTest extends TaskSnapshotPersisterTestBas
@Test
public void testReduced_notCached() {
- final WindowState window = createWindow(null, FIRST_APPLICATION_WINDOW, "window");
+ final WindowState window = newWindowBuilder("window", FIRST_APPLICATION_WINDOW).build();
mPersister.persistSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId, createSnapshot());
mSnapshotPersistQueue.waitForQueueEmpty();
assertNull(mCache.getSnapshot(window.getTask().mTaskId, false /* isLowResolution */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 1fa657822189..5ed2df30518b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -504,8 +504,8 @@ public class WindowContainerTests extends WindowTestsBase {
assertTrue(child.isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
assertFalse(child.isAnimating(PARENTS, ANIMATION_TYPE_SCREEN_ROTATION));
- final WindowState windowState = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
- mDisplayContent, "TestWindowState");
+ final WindowState windowState = newWindowBuilder("TestWindowState",
+ TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
WindowContainer parent = windowState.getParent();
spyOn(windowState.mSurfaceAnimator);
doReturn(true).when(windowState.mSurfaceAnimator).isAnimating();
@@ -1045,8 +1045,8 @@ public class WindowContainerTests extends WindowTestsBase {
// An animating window with mRemoveOnExit can be removed by handleCompleteDeferredRemoval
// once it no longer animates.
- final WindowState exitingWindow = createWindow(null, TYPE_APPLICATION_OVERLAY,
- displayContent, "exiting window");
+ final WindowState exitingWindow = newWindowBuilder("exiting window",
+ TYPE_APPLICATION_OVERLAY).setDisplay(displayContent).build();
exitingWindow.startAnimation(exitingWindow.getPendingTransaction(),
mock(AnimationAdapter.class), false /* hidden */,
SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION);
@@ -1063,7 +1063,7 @@ public class WindowContainerTests extends WindowTestsBase {
final ActivityRecord r = new TaskBuilder(mSupervisor).setCreateActivity(true)
.setDisplay(displayContent).build().getTopMostActivity();
// Add a window and make the activity animating so the removal of activity is deferred.
- createWindow(null, TYPE_BASE_APPLICATION, r, "win");
+ newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(r).build();
doReturn(true).when(r).isAnimating(anyInt(), anyInt());
displayContent.remove();
@@ -1216,7 +1216,8 @@ public class WindowContainerTests extends WindowTestsBase {
public void testFreezeInsets() {
final Task task = createTask(mDisplayContent);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
- final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+ activity).build();
// Set visibility to false, verify the main window of the task will be set the frozen
// insets state immediately.
@@ -1233,7 +1234,8 @@ public class WindowContainerTests extends WindowTestsBase {
final Task rootTask = createTask(mDisplayContent);
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
- final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+ activity).build();
task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
spyOn(win);
doReturn(true).when(task).okToAnimate();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 72935cb546d9..8606581539ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -49,9 +49,10 @@ public class WindowContainerTraversalTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_DOCK_DIVIDER, W_INPUT_METHOD })
@Test
public void testDockedDividerPosition() {
- final WindowState splitScreenWindow = createWindow(null,
- WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
- mDisplayContent, "splitScreenWindow");
+ final WindowState splitScreenWindow = newWindowBuilder("splitScreenWindow",
+ TYPE_BASE_APPLICATION).setWindowingMode(
+ WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay(
+ mDisplayContent).build();
mDisplayContent.setImeLayeringTarget(splitScreenWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 50e0e181cd68..513ba1d49258 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -154,9 +154,11 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsParentWindowHidden() {
- final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
- final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
- final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
+ final WindowState parentWindow = newWindowBuilder("parentWindow", TYPE_APPLICATION).build();
+ final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
+ final WindowState child2 = newWindowBuilder("child2", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
// parentWindow is initially set to hidden.
assertTrue(parentWindow.mHidden);
@@ -172,10 +174,12 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsChildWindow() {
- final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
- final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
- final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
- final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
+ final WindowState parentWindow = newWindowBuilder("parentWindow", TYPE_APPLICATION).build();
+ final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
+ final WindowState child2 = newWindowBuilder("child2", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
+ final WindowState randomWindow = newWindowBuilder("randomWindow", TYPE_APPLICATION).build();
assertFalse(parentWindow.isChildWindow());
assertTrue(child1.isChildWindow());
@@ -185,12 +189,15 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testHasChild() {
- final WindowState win1 = createWindow(null, TYPE_APPLICATION, "win1");
- final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, "win11");
- final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, "win12");
- final WindowState win2 = createWindow(null, TYPE_APPLICATION, "win2");
- final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, "win21");
- final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");
+ final WindowState win1 = newWindowBuilder("win1", TYPE_APPLICATION).build();
+ final WindowState win11 = newWindowBuilder("win11", FIRST_SUB_WINDOW).setParent(
+ win1).build();
+ final WindowState win12 = newWindowBuilder("win12", FIRST_SUB_WINDOW).setParent(
+ win1).build();
+ final WindowState win2 = newWindowBuilder("win2", TYPE_APPLICATION).build();
+ final WindowState win21 = newWindowBuilder("win21", FIRST_SUB_WINDOW).setParent(
+ win2).build();
+ final WindowState randomWindow = newWindowBuilder("randomWindow", TYPE_APPLICATION).build();
assertTrue(win1.hasChild(win11));
assertTrue(win1.hasChild(win12));
@@ -206,9 +213,11 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testGetParentWindow() {
- final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
- final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
- final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
+ final WindowState parentWindow = newWindowBuilder("parentWindow", TYPE_APPLICATION).build();
+ final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
+ final WindowState child2 = newWindowBuilder("child2", FIRST_SUB_WINDOW).setParent(
+ parentWindow).build();
assertNull(parentWindow.getParentWindow());
assertEquals(parentWindow, child1.getParentWindow());
@@ -217,8 +226,8 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testOverlayWindowHiddenWhenSuspended() {
- final WindowState overlayWindow = spy(createWindow(null, TYPE_APPLICATION_OVERLAY,
- "overlayWindow"));
+ final WindowState overlayWindow = spy(
+ newWindowBuilder("overlayWindow", TYPE_APPLICATION_OVERLAY).build());
overlayWindow.setHiddenWhileSuspended(true);
verify(overlayWindow).hide(true /* doAnimation */, true /* requestAnim */);
overlayWindow.setHiddenWhileSuspended(false);
@@ -227,9 +236,11 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testGetTopParentWindow() {
- final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
- final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
- final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
+ final WindowState root = newWindowBuilder("root", TYPE_APPLICATION).build();
+ final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+ root).build();
+ final WindowState child2 = newWindowBuilder("child2", FIRST_SUB_WINDOW).setParent(
+ child1).build();
assertEquals(root, root.getTopParentWindow());
assertEquals(root, child1.getTopParentWindow());
@@ -244,7 +255,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsOnScreen_hiddenByPolicy() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
+ final WindowState window = newWindowBuilder("window", TYPE_APPLICATION).build();
window.setHasSurface(true);
assertTrue(window.isOnScreen());
window.hide(false /* doAnimation */, false /* requestAnim */);
@@ -273,8 +284,8 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCanBeImeTarget() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
- final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");
+ final WindowState appWindow = newWindowBuilder("appWindow", TYPE_APPLICATION).build();
+ final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_INPUT_METHOD).build();
// Setting FLAG_NOT_FOCUSABLE prevents the window from being an IME target.
appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
@@ -328,16 +339,17 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testGetWindow() {
- final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
- final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
- final WindowState mediaOverlayChild = createWindow(root,
- TYPE_APPLICATION_MEDIA_OVERLAY, "mediaOverlayChild");
- final WindowState attachedDialogChild = createWindow(root,
- TYPE_APPLICATION_ATTACHED_DIALOG, "attachedDialogChild");
- final WindowState subPanelChild = createWindow(root,
- TYPE_APPLICATION_SUB_PANEL, "subPanelChild");
- final WindowState aboveSubPanelChild = createWindow(root,
- TYPE_APPLICATION_ABOVE_SUB_PANEL, "aboveSubPanelChild");
+ final WindowState root = newWindowBuilder("root", TYPE_APPLICATION).build();
+ final WindowState mediaChild = newWindowBuilder("mediaChild",
+ TYPE_APPLICATION_MEDIA).setParent(root).build();
+ final WindowState mediaOverlayChild = newWindowBuilder("mediaOverlayChild",
+ TYPE_APPLICATION_MEDIA_OVERLAY).setParent(root).build();
+ final WindowState attachedDialogChild = newWindowBuilder("attachedDialogChild",
+ TYPE_APPLICATION_ATTACHED_DIALOG).setParent(root).build();
+ final WindowState subPanelChild = newWindowBuilder("subPanelChild",
+ TYPE_APPLICATION_SUB_PANEL).setParent(root).build();
+ final WindowState aboveSubPanelChild = newWindowBuilder("aboveSubPanelChild",
+ TYPE_APPLICATION_ABOVE_SUB_PANEL).setParent(root).build();
final LinkedList<WindowState> windows = new LinkedList<>();
@@ -358,7 +370,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testDestroySurface() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).build();
win.mHasSurface = win.mAnimatingExit = true;
win.mWinAnimator.mSurfaceControl = mock(SurfaceControl.class);
win.onExitAnimationDone();
@@ -384,8 +396,10 @@ public class WindowStateTests extends WindowTestsBase {
// Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
// calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same activity.
final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
- final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
+ final WindowState first = newWindowBuilder("first", TYPE_APPLICATION).setWindowToken(
+ activity).build();
+ final WindowState second = newWindowBuilder("second", TYPE_APPLICATION).setWindowToken(
+ activity).build();
testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
true /* expectedCurrentLaunchCanTurnScreenOn */);
@@ -423,10 +437,10 @@ public class WindowStateTests extends WindowTestsBase {
// Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
// activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
final WindowToken windowToken = createTestWindowToken(FIRST_SUB_WINDOW, mDisplayContent);
- final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
- "firstWindow");
- final WindowState secondWindow = createWindow(null, TYPE_APPLICATION, windowToken,
- "secondWindow");
+ final WindowState firstWindow = newWindowBuilder("firstWindow",
+ TYPE_APPLICATION).setWindowToken(windowToken).build();
+ final WindowState secondWindow = newWindowBuilder("secondWindow",
+ TYPE_APPLICATION).setWindowToken(windowToken).build();
firstWindow.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
secondWindow.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
@@ -459,7 +473,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCanAffectSystemUiFlags() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
app.mActivityRecord.setVisible(true);
assertTrue(app.canAffectSystemUiFlags());
app.mActivityRecord.setVisible(false);
@@ -471,7 +485,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCanAffectSystemUiFlags_starting() {
- final WindowState app = createWindow(null, TYPE_APPLICATION_STARTING, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION_STARTING).build();
app.mActivityRecord.setVisible(true);
app.mStartingData = new SnapshotStartingData(mWm, null, 0);
assertFalse(app.canAffectSystemUiFlags());
@@ -481,7 +495,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCanAffectSystemUiFlags_disallow() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
app.mActivityRecord.setVisible(true);
assertTrue(app.canAffectSystemUiFlags());
app.getTask().setCanAffectSystemUiFlags(false);
@@ -538,9 +552,11 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsSelfOrAncestorWindowAnimating() {
- final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
- final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
- final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");
+ final WindowState root = newWindowBuilder("root", TYPE_APPLICATION).build();
+ final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+ root).build();
+ final WindowState child2 = newWindowBuilder("child2", FIRST_SUB_WINDOW).setParent(
+ child1).build();
assertFalse(child2.isSelfOrAncestorWindowAnimatingExit());
child2.mAnimatingExit = true;
assertTrue(child2.isSelfOrAncestorWindowAnimatingExit());
@@ -551,7 +567,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testDeferredRemovalByAnimating() {
- final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ final WindowState appWindow = newWindowBuilder("appWindow", TYPE_APPLICATION).build();
makeWindowVisible(appWindow);
spyOn(appWindow.mWinAnimator);
doReturn(true).when(appWindow.mWinAnimator).getShown();
@@ -571,8 +587,9 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testOnExitAnimationDone() {
- final WindowState parent = createWindow(null, TYPE_APPLICATION, "parent");
- final WindowState child = createWindow(parent, TYPE_APPLICATION_PANEL, "child");
+ final WindowState parent = newWindowBuilder("parent", TYPE_APPLICATION).build();
+ final WindowState child = newWindowBuilder("child", TYPE_APPLICATION_PANEL).setParent(
+ parent).build();
final SurfaceControl.Transaction t = parent.getPendingTransaction();
child.startAnimation(t, mock(AnimationAdapter.class), false /* hidden */,
SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION);
@@ -609,7 +626,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testLayoutSeqResetOnReparent() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
app.mLayoutSeq = 1;
mDisplayContent.mLayoutSeq = 1;
@@ -622,7 +639,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testDisplayIdUpdatedOnReparent() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
// fake a different display
app.mInputWindowHandle.setDisplayId(mDisplayContent.getDisplayId() + 1);
app.onDisplayChanged(mDisplayContent);
@@ -633,7 +650,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testApplyWithNextDraw() {
- final WindowState win = createWindow(null, TYPE_APPLICATION_OVERLAY, "app");
+ final WindowState win = newWindowBuilder("app", TYPE_APPLICATION_OVERLAY).build();
final SurfaceControl.Transaction[] handledT = { null };
// The normal case that the draw transaction is applied with finishing drawing.
win.applyWithNextDraw(t -> handledT[0] = t);
@@ -657,7 +674,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testSeamlesslyRotateWindow() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
final SurfaceControl.Transaction t = spy(StubTransaction.class);
makeWindowVisible(app);
@@ -707,7 +724,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testVisibilityChangeSwitchUser() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState window = newWindowBuilder("app", TYPE_APPLICATION).build();
window.mHasSurface = true;
spyOn(window);
doReturn(false).when(window).showForAllUsers();
@@ -729,8 +746,9 @@ public class WindowStateTests extends WindowTestsBase {
final CompatModePackages cmp = mWm.mAtmService.mCompatModePackages;
spyOn(cmp);
doReturn(overrideScale).when(cmp).getCompatScale(anyString(), anyInt());
- final WindowState w = createWindow(null, TYPE_APPLICATION_OVERLAY, "win");
- final WindowState child = createWindow(w, TYPE_APPLICATION_PANEL, "child");
+ final WindowState w = newWindowBuilder("win", TYPE_APPLICATION_OVERLAY).build();
+ final WindowState child = newWindowBuilder("child", TYPE_APPLICATION_PANEL).setParent(
+ w).build();
assertTrue(w.hasCompatScale());
assertTrue(child.hasCompatScale());
@@ -788,7 +806,8 @@ public class WindowStateTests extends WindowTestsBase {
// Child window without scale (e.g. different app) should apply inverse scale of parent.
doReturn(1f).when(cmp).getCompatScale(anyString(), anyInt());
- final WindowState child2 = createWindow(w, TYPE_APPLICATION_SUB_PANEL, "child2");
+ final WindowState child2 = newWindowBuilder("child2", TYPE_APPLICATION_SUB_PANEL).setParent(
+ w).build();
makeWindowVisible(w, child2);
clearInvocations(t);
child2.prepareSurfaces();
@@ -798,10 +817,10 @@ public class WindowStateTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_ABOVE_ACTIVITY, W_NOTIFICATION_SHADE })
@Test
public void testRequestDrawIfNeeded() {
- final WindowState startingApp = createWindow(null /* parent */,
- TYPE_BASE_APPLICATION, "startingApp");
- final WindowState startingWindow = createWindow(null /* parent */,
- TYPE_APPLICATION_STARTING, startingApp.mToken, "starting");
+ final WindowState startingApp = newWindowBuilder("startingApp",
+ TYPE_BASE_APPLICATION).build();
+ final WindowState startingWindow = newWindowBuilder("starting",
+ TYPE_APPLICATION_STARTING).setWindowToken(startingApp.mToken).build();
startingApp.mActivityRecord.mStartingWindow = startingWindow;
final WindowState keyguardHostWindow = mNotificationShadeWindow;
final WindowState allDrawnApp = mAppWindow;
@@ -878,7 +897,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testRequestResizeForBlastSync() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "window");
+ final WindowState win = newWindowBuilder("window", TYPE_APPLICATION).build();
makeWindowVisible(win);
makeLastConfigReportedToClient(win, true /* visible */);
win.mLayoutSeq = win.getDisplayContent().mLayoutSeq;
@@ -926,8 +945,8 @@ public class WindowStateTests extends WindowTestsBase {
final Task task = createTask(mDisplayContent);
final TaskFragment embeddedTf = createTaskFragmentWithEmbeddedActivity(task, organizer);
final ActivityRecord embeddedActivity = embeddedTf.getTopMostActivity();
- final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION, embeddedActivity,
- "App window");
+ final WindowState win = newWindowBuilder("App window", TYPE_APPLICATION).setWindowToken(
+ embeddedActivity).build();
doReturn(true).when(embeddedActivity).isVisible();
embeddedActivity.setVisibleRequested(true);
makeWindowVisible(win);
@@ -949,14 +968,14 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
- final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
+ final WindowState win0 = newWindowBuilder("win0", TYPE_APPLICATION).build();
win0.mActivityRecord.setVisibleRequested(false);
assertFalse(win0.canReceiveTouchInput());
}
@Test
public void testCantReceiveTouchWhenNotFocusable() {
- final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
+ final WindowState win0 = newWindowBuilder("win0", TYPE_APPLICATION).build();
final Task rootTask = win0.mActivityRecord.getRootTask();
spyOn(rootTask);
when(rootTask.shouldIgnoreInput()).thenReturn(true);
@@ -969,7 +988,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testUpdateInputWindowHandle() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).build();
win.mAttrs.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
win.mAttrs.flags = FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH;
final InputWindowHandle handle = new InputWindowHandle(
@@ -1026,7 +1045,7 @@ public class WindowStateTests extends WindowTestsBase {
@DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX)
@Test
public void testTouchRegionUsesLetterboxBoundsIfTransformedBoundsAndLetterboxScrolling() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).build();
// Transformed bounds used for size of touchable region if letterbox inner bounds are empty.
final Rect transformedBounds = new Rect(0, 0, 300, 500);
@@ -1051,7 +1070,7 @@ public class WindowStateTests extends WindowTestsBase {
@DisableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX)
@Test
public void testTouchRegionUsesLetterboxBoundsIfNullTransformedBoundsAndLetterboxScrolling() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).build();
// Fragment bounds used for size of touchable region if letterbox inner bounds are empty
// and Transform bounds are null.
@@ -1083,7 +1102,7 @@ public class WindowStateTests extends WindowTestsBase {
@EnableFlags(Flags.FLAG_SCROLLING_FROM_LETTERBOX)
@Test
public void testTouchRegionUsesTransformedBoundsIfLetterboxScrolling() {
- final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).build();
// Transformed bounds used for size of touchable region if letterbox inner bounds are empty.
final Rect transformedBounds = new Rect(0, 0, 300, 500);
@@ -1109,7 +1128,7 @@ public class WindowStateTests extends WindowTestsBase {
public void testHasActiveVisibleWindow() {
final int uid = ActivityBuilder.DEFAULT_FAKE_UID;
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid);
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).setOwnerId(uid).build();
app.mActivityRecord.setVisible(false);
app.mActivityRecord.setVisibility(false);
assertFalse(mAtm.hasActiveVisibleWindow(uid));
@@ -1120,15 +1139,17 @@ public class WindowStateTests extends WindowTestsBase {
// Make the activity invisible and add a visible toast. The uid should have no active
// visible window because toast can be misused by legacy app to bypass background check.
app.mActivityRecord.setVisibility(false);
- final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay", uid);
- final WindowState toast = createWindow(null, TYPE_TOAST, app.mToken, "toast", uid);
+ final WindowState overlay = newWindowBuilder("overlay",
+ TYPE_APPLICATION_OVERLAY).setOwnerId(uid).build();
+ final WindowState toast = newWindowBuilder("toast", TYPE_TOAST).setWindowToken(
+ app.mToken).setOwnerId(uid).build();
toast.onSurfaceShownChanged(true);
assertFalse(mAtm.hasActiveVisibleWindow(uid));
// Though starting window should belong to system. Make sure it is ignored to avoid being
// allow-list unexpectedly, see b/129563343.
- final WindowState starting =
- createWindow(null, TYPE_APPLICATION_STARTING, app.mToken, "starting", uid);
+ final WindowState starting = newWindowBuilder("starting",
+ TYPE_APPLICATION_STARTING).setWindowToken(app.mToken).setOwnerId(uid).build();
starting.onSurfaceShownChanged(true);
assertFalse(mAtm.hasActiveVisibleWindow(uid));
@@ -1145,8 +1166,8 @@ public class WindowStateTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
@Test
public void testNeedsRelativeLayeringToIme_notAttached() {
- WindowState sameTokenWindow = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken,
- "SameTokenWindow");
+ WindowState sameTokenWindow = newWindowBuilder("SameTokenWindow",
+ TYPE_BASE_APPLICATION).setWindowToken(mAppWindow.mToken).build();
mDisplayContent.setImeLayeringTarget(mAppWindow);
makeWindowVisible(mImeWindow);
sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -1158,8 +1179,8 @@ public class WindowStateTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
@Test
public void testNeedsRelativeLayeringToIme_startingWindow() {
- WindowState sameTokenWindow = createWindow(null, TYPE_APPLICATION_STARTING,
- mAppWindow.mToken, "SameTokenWindow");
+ WindowState sameTokenWindow = newWindowBuilder("SameTokenWindow",
+ TYPE_APPLICATION_STARTING).setWindowToken(mAppWindow.mToken).build();
mDisplayContent.setImeLayeringTarget(mAppWindow);
makeWindowVisible(mImeWindow);
sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -1169,9 +1190,9 @@ public class WindowStateTests extends WindowTestsBase {
@UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
@Test
public void testNeedsRelativeLayeringToIme_systemDialog() {
- WindowState systemDialogWindow = createWindow(null, TYPE_SECURE_SYSTEM_OVERLAY,
- mDisplayContent,
- "SystemDialog", true);
+ WindowState systemDialogWindow = newWindowBuilder("SystemDialog",
+ TYPE_SECURE_SYSTEM_OVERLAY).setDisplay(
+ mDisplayContent).setOwnerCanAddInternalSystemWindow(true).build();
mDisplayContent.setImeLayeringTarget(mAppWindow);
mAppWindow.getTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
makeWindowVisible(mImeWindow);
@@ -1182,20 +1203,21 @@ public class WindowStateTests extends WindowTestsBase {
@UseTestDisplay(addWindows = {W_INPUT_METHOD})
@Test
public void testNeedsRelativeLayeringToIme_notificationShadeShouldNotHideSystemDialog() {
- WindowState systemDialogWindow = createWindow(null, TYPE_SECURE_SYSTEM_OVERLAY,
- mDisplayContent,
- "SystemDialog", true);
+ WindowState systemDialogWindow = newWindowBuilder("SystemDialog",
+ TYPE_SECURE_SYSTEM_OVERLAY).setDisplay(
+ mDisplayContent).setOwnerCanAddInternalSystemWindow(true).build();
mDisplayContent.setImeLayeringTarget(systemDialogWindow);
makeWindowVisible(mImeWindow);
- WindowState notificationShade = createWindow(null, TYPE_NOTIFICATION_SHADE,
- mDisplayContent, "NotificationShade", true);
+ WindowState notificationShade = newWindowBuilder("NotificationShade",
+ TYPE_NOTIFICATION_SHADE).setDisplay(
+ mDisplayContent).setOwnerCanAddInternalSystemWindow(true).build();
notificationShade.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
assertFalse(notificationShade.needsRelativeLayeringToIme());
}
@Test
public void testSetFreezeInsetsState() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
spyOn(app);
doReturn(true).when(app).isVisible();
@@ -1216,7 +1238,7 @@ public class WindowStateTests extends WindowTestsBase {
verify(app).notifyInsetsChanged();
// Verify that invisible non-activity window won't dispatch insets changed.
- final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay");
+ final WindowState overlay = newWindowBuilder("overlay", TYPE_APPLICATION_OVERLAY).build();
makeWindowVisible(overlay);
assertTrue(overlay.isReadyToDispatchInsetsState());
overlay.mHasSurface = false;
@@ -1244,9 +1266,9 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testAdjustImeInsetsVisibilityWhenSwitchingApps() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
- final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
+ final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build();
+ final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build();
spyOn(imeWindow);
doReturn(true).when(imeWindow).isVisible();
mDisplayContent.mInputMethodWindow = imeWindow;
@@ -1279,10 +1301,11 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
- ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2");
- final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
+ final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowingMode(
+ WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay(
+ mDisplayContent).build();
+ final WindowState imeWindow = newWindowBuilder("imeWindow", TYPE_APPLICATION).build();
spyOn(imeWindow);
doReturn(true).when(imeWindow).isVisible();
mDisplayContent.mInputMethodWindow = imeWindow;
@@ -1321,8 +1344,8 @@ public class WindowStateTests extends WindowTestsBase {
@SetupWindows(addWindows = W_ACTIVITY)
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
- WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
- mAppWindow.mToken, "app");
+ WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).setWindowToken(
+ mAppWindow.mToken).build();
mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
spyOn(app);
@@ -1349,8 +1372,8 @@ public class WindowStateTests extends WindowTestsBase {
@SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD, W_NOTIFICATION_SHADE })
@Test
public void testNotificationShadeHasImeInsetsWhenMultiWindow() {
- WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
- mAppWindow.mToken, "app");
+ WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).setWindowToken(
+ mAppWindow.mToken).build();
// Simulate entering multi-window mode and windowing mode is multi-window.
app.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -1376,7 +1399,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testRequestedVisibility() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
app.mActivityRecord.setVisible(false);
app.mActivityRecord.setVisibility(false);
assertFalse(app.isVisibleRequested());
@@ -1391,7 +1414,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testKeepClearAreas() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
+ final WindowState window = newWindowBuilder("window", TYPE_APPLICATION).build();
makeWindowVisible(window);
final Rect keepClearArea1 = new Rect(0, 0, 10, 10);
@@ -1433,7 +1456,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testUnrestrictedKeepClearAreas() {
- final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
+ final WindowState window = newWindowBuilder("window", TYPE_APPLICATION).build();
makeWindowVisible(window);
final Rect keepClearArea1 = new Rect(0, 0, 10, 10);
@@ -1481,8 +1504,9 @@ public class WindowStateTests extends WindowTestsBase {
final InputMethodManagerInternal immi = InputMethodManagerInternal.get();
spyOn(immi);
- final WindowState imeTarget = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
- createActivityRecord(mDisplayContent), "imeTarget");
+ final WindowState imeTarget = newWindowBuilder("imeTarget",
+ TYPE_BASE_APPLICATION).setWindowToken(
+ createActivityRecord(mDisplayContent)).build();
imeTarget.mActivityRecord.setVisibleRequested(true);
makeWindowVisible(imeTarget);
@@ -1562,8 +1586,8 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsSecureLocked_flagSecureSet() {
- WindowState window = createWindow(null /* parent */, TYPE_APPLICATION, "test-window",
- 1 /* ownerId */);
+ WindowState window = newWindowBuilder("test-window", TYPE_APPLICATION).setOwnerId(
+ 1).build();
window.mAttrs.flags |= WindowManager.LayoutParams.FLAG_SECURE;
assertTrue(window.isSecureLocked());
@@ -1571,8 +1595,8 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testIsSecureLocked_flagSecureNotSet() {
- WindowState window = createWindow(null /* parent */, TYPE_APPLICATION, "test-window",
- 1 /* ownerId */);
+ WindowState window = newWindowBuilder("test-window", TYPE_APPLICATION).setOwnerId(
+ 1).build();
assertFalse(window.isSecureLocked());
}
@@ -1581,8 +1605,8 @@ public class WindowStateTests extends WindowTestsBase {
public void testIsSecureLocked_disableSecureWindows() {
assumeTrue(Build.IS_DEBUGGABLE);
- WindowState window = createWindow(null /* parent */, TYPE_APPLICATION, "test-window",
- 1 /* ownerId */);
+ WindowState window = newWindowBuilder("test-window", TYPE_APPLICATION).setOwnerId(
+ 1).build();
window.mAttrs.flags |= WindowManager.LayoutParams.FLAG_SECURE;
ContentResolver cr = useFakeSettingsProvider();
@@ -1617,8 +1641,10 @@ public class WindowStateTests extends WindowTestsBase {
String testPackage = "test";
int ownerId1 = 20;
int ownerId2 = 21;
- final WindowState window1 = createWindow(null, TYPE_APPLICATION, "window1", ownerId1);
- final WindowState window2 = createWindow(null, TYPE_APPLICATION, "window2", ownerId2);
+ final WindowState window1 = newWindowBuilder("window1", TYPE_APPLICATION).setOwnerId(
+ ownerId1).build();
+ final WindowState window2 = newWindowBuilder("window2", TYPE_APPLICATION).setOwnerId(
+ ownerId2).build();
// Setting packagename for targeted feature
window1.mAttrs.packageName = testPackage;
@@ -1638,7 +1664,8 @@ public class WindowStateTests extends WindowTestsBase {
public void testIsSecureLocked_sensitiveContentBlockOrClearScreenCaptureForApp() {
String testPackage = "test";
int ownerId = 20;
- final WindowState window = createWindow(null, TYPE_APPLICATION, "window", ownerId);
+ final WindowState window = newWindowBuilder("window", TYPE_APPLICATION).setOwnerId(
+ ownerId).build();
window.mAttrs.packageName = testPackage;
assertFalse(window.isSecureLocked());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index f226b9d29ca0..a02c3db1e636 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -74,11 +74,16 @@ public class WindowTokenTests extends WindowTestsBase {
assertEquals(0, token.getWindowsCount());
- final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
- final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
- final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
- final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
- final WindowState window3 = createWindow(null, TYPE_APPLICATION, token, "window3");
+ final WindowState window1 = newWindowBuilder("window1", TYPE_APPLICATION).setWindowToken(
+ token).build();
+ final WindowState window11 = newWindowBuilder("window11", FIRST_SUB_WINDOW).setParent(
+ window1).setWindowToken(token).build();
+ final WindowState window12 = newWindowBuilder("window12", FIRST_SUB_WINDOW).setParent(
+ window1).setWindowToken(token).build();
+ final WindowState window2 = newWindowBuilder("window2", TYPE_APPLICATION).setWindowToken(
+ token).build();
+ final WindowState window3 = newWindowBuilder("window3", TYPE_APPLICATION).setWindowToken(
+ token).build();
token.addWindow(window1);
// NOTE: Child windows will not be added to the token as window containers can only
@@ -105,8 +110,10 @@ public class WindowTokenTests extends WindowTestsBase {
public void testAddWindow_assignsLayers() {
final TestWindowToken token1 = createTestWindowToken(0, mDisplayContent);
final TestWindowToken token2 = createTestWindowToken(0, mDisplayContent);
- final WindowState window1 = createWindow(null, TYPE_STATUS_BAR, token1, "window1");
- final WindowState window2 = createWindow(null, TYPE_STATUS_BAR, token2, "window2");
+ final WindowState window1 = newWindowBuilder("window1", TYPE_STATUS_BAR).setWindowToken(
+ token1).build();
+ final WindowState window2 = newWindowBuilder("window2", TYPE_STATUS_BAR).setWindowToken(
+ token2).build();
token1.addWindow(window1);
token2.addWindow(window2);
@@ -122,8 +129,10 @@ public class WindowTokenTests extends WindowTestsBase {
assertEquals(token, dc.getWindowToken(token.token));
- final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
- final WindowState window2 = createWindow(null, TYPE_APPLICATION, token, "window2");
+ final WindowState window1 = newWindowBuilder("window1", TYPE_APPLICATION).setWindowToken(
+ token).build();
+ final WindowState window2 = newWindowBuilder("window2", TYPE_APPLICATION).setWindowToken(
+ token).build();
window2.removeImmediately();
// The token should still be mapped in the display content since it still has a child.
@@ -147,8 +156,10 @@ public class WindowTokenTests extends WindowTestsBase {
// Verify that the token is on the display
assertNotNull(mDisplayContent.getWindowToken(token.token));
- final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
- final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
+ final WindowState window1 = newWindowBuilder("window1", TYPE_TOAST).setWindowToken(
+ token).build();
+ final WindowState window2 = newWindowBuilder("window2", TYPE_TOAST).setWindowToken(
+ token).build();
mDisplayContent.removeWindowToken(token.token, true /* animateExit */);
// Verify that the token is no longer mapped on the display
@@ -231,7 +242,8 @@ public class WindowTokenTests extends WindowTestsBase {
assertNull(fromClientToken.mSurfaceControl);
- createWindow(null, TYPE_APPLICATION_OVERLAY, fromClientToken, "window");
+ newWindowBuilder("window", TYPE_APPLICATION_OVERLAY).setWindowToken(
+ fromClientToken).build();
assertNotNull(fromClientToken.mSurfaceControl);
final WindowToken nonClientToken = new WindowToken.Builder(mDisplayContent.mWmService,
@@ -285,7 +297,7 @@ public class WindowTokenTests extends WindowTestsBase {
// Simulate an app window to be the IME layering target, assume the app window has no
// frozen insets state by default.
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
mDisplayContent.setImeLayeringTarget(app);
assertNull(app.getFrozenInsetsState());
assertTrue(app.isImeLayeringTarget());
@@ -299,7 +311,8 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testRemoveWindowToken_noAnimateExitWhenSet() {
final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
- final WindowState win = createWindow(null, TYPE_APPLICATION, token, "win");
+ final WindowState win = newWindowBuilder("win", TYPE_APPLICATION).setWindowToken(
+ token).build();
makeWindowVisible(win);
assertTrue(win.isOnScreen());
spyOn(win);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 4f60106db93d..84e21181a7b9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -221,7 +221,7 @@ public class ZOrderingTests extends WindowTestsBase {
}
WindowState createWindow(String name) {
- return createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, name);
+ return newWindowBuilder(name, TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
}
@Test
@@ -263,12 +263,12 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
- final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
- TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
- "imeAppTargetChildAboveWindow");
- final WindowState imeAppTargetChildBelowWindow = createWindow(imeAppTarget,
- TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
- "imeAppTargetChildBelowWindow");
+ final WindowState imeAppTargetChildAboveWindow = newWindowBuilder(
+ "imeAppTargetChildAboveWindow", TYPE_APPLICATION_ATTACHED_DIALOG).setParent(
+ imeAppTarget).setWindowToken(imeAppTarget.mToken).build();
+ final WindowState imeAppTargetChildBelowWindow = newWindowBuilder(
+ "imeAppTargetChildBelowWindow", TYPE_APPLICATION_MEDIA_OVERLAY).setParent(
+ imeAppTarget).setWindowToken(imeAppTarget.mToken).build();
mDisplayContent.setImeLayeringTarget(imeAppTarget);
makeWindowVisible(mImeWindow);
@@ -313,9 +313,9 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForImeNonAppImeTarget() {
- final WindowState imeSystemOverlayTarget = createWindow(null, TYPE_SYSTEM_OVERLAY,
- mDisplayContent, "imeSystemOverlayTarget",
- true /* ownerCanAddInternalSystemWindow */);
+ final WindowState imeSystemOverlayTarget = newWindowBuilder("imeSystemOverlayTarget",
+ TYPE_SYSTEM_OVERLAY).setDisplay(mDisplayContent).setOwnerCanAddInternalSystemWindow(
+ true).build();
mDisplayContent.setImeLayeringTarget(imeSystemOverlayTarget);
mDisplayContent.assignChildLayers(mTransaction);
@@ -354,18 +354,19 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testStackLayers() {
final WindowState anyWindow1 = createWindow("anyWindow");
- final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
- ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
- "pinnedStackWindow");
- final WindowState dockedStackWindow = createWindow(null,
- WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
- mDisplayContent, "dockedStackWindow");
- final WindowState assistantStackWindow = createWindow(null,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
- mDisplayContent, "assistantStackWindow");
- final WindowState homeActivityWindow = createWindow(null, WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_HOME, TYPE_BASE_APPLICATION,
- mDisplayContent, "homeActivityWindow");
+ final WindowState pinnedStackWindow = newWindowBuilder("pinnedStackWindow",
+ TYPE_BASE_APPLICATION).setWindowingMode(WINDOWING_MODE_PINNED).setActivityType(
+ ACTIVITY_TYPE_STANDARD).setDisplay(mDisplayContent).build();
+ final WindowState dockedStackWindow = newWindowBuilder("dockedStackWindow",
+ TYPE_BASE_APPLICATION).setWindowingMode(
+ WINDOWING_MODE_MULTI_WINDOW).setActivityType(ACTIVITY_TYPE_STANDARD).setDisplay(
+ mDisplayContent).build();
+ final WindowState assistantStackWindow = newWindowBuilder("assistantStackWindow",
+ TYPE_BASE_APPLICATION).setWindowingMode(WINDOWING_MODE_FULLSCREEN).setActivityType(
+ ACTIVITY_TYPE_ASSISTANT).setDisplay(mDisplayContent).build();
+ final WindowState homeActivityWindow = newWindowBuilder("homeActivityWindow",
+ TYPE_BASE_APPLICATION).setWindowingMode(WINDOWING_MODE_FULLSCREEN).setActivityType(
+ ACTIVITY_TYPE_HOME).setDisplay(mDisplayContent).build();
final WindowState anyWindow2 = createWindow("anyWindow2");
mDisplayContent.assignChildLayers(mTransaction);
@@ -383,13 +384,12 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForSysUiPanels() {
- final WindowState navBarPanel =
- createWindow(null, TYPE_NAVIGATION_BAR_PANEL, mDisplayContent, "NavBarPanel");
- final WindowState statusBarPanel =
- createWindow(null, TYPE_STATUS_BAR_ADDITIONAL, mDisplayContent,
- "StatusBarAdditional");
- final WindowState statusBarSubPanel =
- createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, mDisplayContent, "StatusBarSubPanel");
+ final WindowState navBarPanel = newWindowBuilder("NavBarPanel",
+ TYPE_NAVIGATION_BAR_PANEL).setDisplay(mDisplayContent).build();
+ final WindowState statusBarPanel = newWindowBuilder("StatusBarAdditional",
+ TYPE_STATUS_BAR_ADDITIONAL).setDisplay(mDisplayContent).build();
+ final WindowState statusBarSubPanel = newWindowBuilder("StatusBarSubPanel",
+ TYPE_STATUS_BAR_SUB_PANEL).setDisplay(mDisplayContent).build();
mDisplayContent.assignChildLayers(mTransaction);
// Ime should be above all app windows and below system windows if it is targeting an app
@@ -401,15 +401,16 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForImeOnPopupImeLayeringTarget() {
- final WindowState imeAppTarget = createWindow(null, TYPE_APPLICATION,
- mAppWindow.mActivityRecord, "imeAppTarget");
+ final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
+ TYPE_APPLICATION).setWindowToken(mAppWindow.mActivityRecord).build();
mDisplayContent.setImeInputTarget(imeAppTarget);
mDisplayContent.setImeLayeringTarget(imeAppTarget);
mDisplayContent.setImeControlTarget(imeAppTarget);
// Set a popup IME layering target and keeps the original IME control target behinds it.
- final WindowState popupImeTargetWin = createWindow(imeAppTarget,
- TYPE_APPLICATION_SUB_PANEL, mAppWindow.mActivityRecord, "popupImeTargetWin");
+ final WindowState popupImeTargetWin = newWindowBuilder("popupImeTargetWin",
+ TYPE_APPLICATION_SUB_PANEL).setParent(imeAppTarget).setWindowToken(
+ mAppWindow.mActivityRecord).build();
mDisplayContent.setImeLayeringTarget(popupImeTargetWin);
mDisplayContent.updateImeParent();
@@ -424,11 +425,11 @@ public class ZOrderingTests extends WindowTestsBase {
// then we can drop all negative layering on the windowing side.
final WindowState anyWindow = createWindow("anyWindow");
- final WindowState child = createWindow(anyWindow, TYPE_APPLICATION_MEDIA, mDisplayContent,
- "TypeApplicationMediaChild");
- final WindowState mediaOverlayChild = createWindow(anyWindow,
- TYPE_APPLICATION_MEDIA_OVERLAY,
- mDisplayContent, "TypeApplicationMediaOverlayChild");
+ final WindowState child = newWindowBuilder("TypeApplicationMediaChild",
+ TYPE_APPLICATION_MEDIA).setParent(anyWindow).setDisplay(mDisplayContent).build();
+ final WindowState mediaOverlayChild = newWindowBuilder("TypeApplicationMediaOverlayChild",
+ TYPE_APPLICATION_MEDIA_OVERLAY).setParent(anyWindow).setDisplay(
+ mDisplayContent).build();
mDisplayContent.assignChildLayers(mTransaction);
@@ -440,14 +441,17 @@ public class ZOrderingTests extends WindowTestsBase {
public void testAssignWindowLayers_ForPostivelyZOrderedSubtype() {
final WindowState anyWindow = createWindow("anyWindow");
final ArrayList<WindowState> childList = new ArrayList<>();
- childList.add(createWindow(anyWindow, TYPE_APPLICATION_PANEL, mDisplayContent,
- "TypeApplicationPanelChild"));
- childList.add(createWindow(anyWindow, TYPE_APPLICATION_SUB_PANEL, mDisplayContent,
- "TypeApplicationSubPanelChild"));
- childList.add(createWindow(anyWindow, TYPE_APPLICATION_ATTACHED_DIALOG, mDisplayContent,
- "TypeApplicationAttachedDialogChild"));
- childList.add(createWindow(anyWindow, TYPE_APPLICATION_ABOVE_SUB_PANEL, mDisplayContent,
- "TypeApplicationAboveSubPanelPanelChild"));
+ childList.add(newWindowBuilder("TypeApplicationPanelChild",
+ TYPE_APPLICATION_PANEL).setParent(anyWindow).setDisplay(mDisplayContent).build());
+ childList.add(newWindowBuilder("TypeApplicationSubPanelChild",
+ TYPE_APPLICATION_SUB_PANEL).setParent(anyWindow).setDisplay(
+ mDisplayContent).build());
+ childList.add(newWindowBuilder("TypeApplicationAttachedDialogChild",
+ TYPE_APPLICATION_ATTACHED_DIALOG).setParent(anyWindow).setDisplay(
+ mDisplayContent).build());
+ childList.add(newWindowBuilder("TypeApplicationAboveSubPanelPanelChild",
+ TYPE_APPLICATION_ABOVE_SUB_PANEL).setParent(anyWindow).setDisplay(
+ mDisplayContent).build());
final LayerRecordingTransaction t = mTransaction;
mDisplayContent.assignChildLayers(t);
@@ -469,8 +473,8 @@ public class ZOrderingTests extends WindowTestsBase {
// Create a popupWindow
assertWindowHigher(mImeWindow, mAppWindow);
- final WindowState popupWindow = createWindow(mAppWindow, TYPE_APPLICATION_PANEL,
- mDisplayContent, "PopupWindow");
+ final WindowState popupWindow = newWindowBuilder("PopupWindow",
+ TYPE_APPLICATION_PANEL).setParent(mAppWindow).setDisplay(mDisplayContent).build();
spyOn(popupWindow);
mDisplayContent.assignChildLayers(mTransaction);
@@ -492,8 +496,9 @@ public class ZOrderingTests extends WindowTestsBase {
makeWindowVisible(mImeWindow);
// Create a popupWindow
- final WindowState systemDialogWindow = createWindow(null, TYPE_SECURE_SYSTEM_OVERLAY,
- mDisplayContent, "SystemDialog", true);
+ final WindowState systemDialogWindow = newWindowBuilder("SystemDialog",
+ TYPE_SECURE_SYSTEM_OVERLAY).setDisplay(
+ mDisplayContent).setOwnerCanAddInternalSystemWindow(true).build();
systemDialogWindow.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
spyOn(systemDialogWindow);
diff --git a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
index b5dfb631609c..e18fad3eda79 100644
--- a/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
@@ -78,6 +78,9 @@ public interface SatelliteTransmissionUpdateCallback {
/**
* Called when framework receives a request to send a datagram.
*
+ * Informs external apps that device is working on sending a datagram out and is in the process
+ * of checking if all the conditions required to send datagrams are met.
+ *
* @param datagramType The type of the requested datagram.
*/
@FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
diff --git a/tools/aapt2/cmd/Command.cpp b/tools/aapt2/cmd/Command.cpp
index 449d93dd8c0b..20315561cceb 100644
--- a/tools/aapt2/cmd/Command.cpp
+++ b/tools/aapt2/cmd/Command.cpp
@@ -53,61 +53,67 @@ std::string GetSafePath(StringPiece arg) {
void Command::AddRequiredFlag(StringPiece name, StringPiece description, std::string* value,
uint32_t flags) {
- auto func = [value, flags](StringPiece arg) -> bool {
+ auto func = [value, flags](StringPiece arg, std::ostream*) -> bool {
*value = (flags & Command::kPath) ? GetSafePath(arg) : std::string(arg);
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ true, /* num_args */ 1, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ true, /* num_args */ 1, std::move(func)));
}
void Command::AddRequiredFlagList(StringPiece name, StringPiece description,
std::vector<std::string>* value, uint32_t flags) {
- auto func = [value, flags](StringPiece arg) -> bool {
+ auto func = [value, flags](StringPiece arg, std::ostream*) -> bool {
value->push_back((flags & Command::kPath) ? GetSafePath(arg) : std::string(arg));
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ true, /* num_args */ 1, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ true, /* num_args */ 1, std::move(func)));
}
void Command::AddOptionalFlag(StringPiece name, StringPiece description,
std::optional<std::string>* value, uint32_t flags) {
- auto func = [value, flags](StringPiece arg) -> bool {
+ auto func = [value, flags](StringPiece arg, std::ostream*) -> bool {
*value = (flags & Command::kPath) ? GetSafePath(arg) : std::string(arg);
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ false, /* num_args */ 1, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ false, /* num_args */ 1, std::move(func)));
}
void Command::AddOptionalFlagList(StringPiece name, StringPiece description,
std::vector<std::string>* value, uint32_t flags) {
- auto func = [value, flags](StringPiece arg) -> bool {
+ auto func = [value, flags](StringPiece arg, std::ostream*) -> bool {
value->push_back((flags & Command::kPath) ? GetSafePath(arg) : std::string(arg));
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ false, /* num_args */ 1, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ false, /* num_args */ 1, std::move(func)));
}
void Command::AddOptionalFlagList(StringPiece name, StringPiece description,
std::unordered_set<std::string>* value) {
- auto func = [value](StringPiece arg) -> bool {
+ auto func = [value](StringPiece arg, std::ostream* out_error) -> bool {
value->emplace(arg);
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ false, /* num_args */ 1, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ false, /* num_args */ 1, std::move(func)));
}
void Command::AddOptionalSwitch(StringPiece name, StringPiece description, bool* value) {
- auto func = [value](StringPiece arg) -> bool {
+ auto func = [value](StringPiece arg, std::ostream* out_error) -> bool {
*value = true;
return true;
};
- flags_.emplace_back(Flag(name, description, /* required */ false, /* num_args */ 0, func));
+ flags_.emplace_back(
+ Flag(name, description, /* required */ false, /* num_args */ 0, std::move(func)));
}
void Command::AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand, bool experimental) {
@@ -172,19 +178,74 @@ void Command::Usage(std::ostream* out) {
argline = " ";
}
}
- *out << " " << std::setw(kWidth) << std::left << "-h"
- << "Displays this help menu\n";
out->flush();
}
-int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_error) {
+const std::string& Command::addEnvironmentArg(const Flag& flag, const char* env) {
+ if (*env && flag.num_args > 0) {
+ return environment_args_.emplace_back(flag.name + '=' + env);
+ }
+ return flag.name;
+}
+
+//
+// Looks for the flags specified in the environment and adds them to |args|.
+// Expected format:
+// - _AAPT2_UPPERCASE_NAME are added before all of the command line flags, so it's
+// a default for the flag that may get overridden by the command line.
+// - AAPT2_UPPERCASE_NAME_ are added after them, making this to be the final value
+// even if there was something on the command line.
+// - All dashes in the flag name get replaced with underscores, the rest of it is
+// intact.
+//
+// E.g.
+// --set-some-flag becomes either _AAPT2_SET_SOME_FLAG or AAPT2_SET_SOME_FLAG_
+// --set-param=2 is _AAPT2_SET_SOME_FLAG=2
+//
+// Values get passed as it, with no processing or quoting.
+//
+// This way one can make sure aapt2 has the flags they need even when it is
+// launched in a way they can't control, e.g. deep inside a build.
+//
+void Command::parseFlagsFromEnvironment(std::vector<StringPiece>& args) {
+ // If the first argument is a subcommand then skip it and prepend the flags past that (the root
+ // command should only have a single '-h' flag anyway).
+ const int insert_pos = args.empty() ? 0 : args.front().starts_with('-') ? 0 : 1;
+
+ std::string env_name;
+ for (const Flag& flag : flags_) {
+ // First, the prefix version.
+ env_name.assign("_AAPT2_");
+ // Append the uppercased flag name, skipping all dashes in front and replacing them with
+ // underscores later.
+ auto name_start = flag.name.begin();
+ while (name_start != flag.name.end() && *name_start == '-') {
+ ++name_start;
+ }
+ std::transform(name_start, flag.name.end(), std::back_inserter(env_name),
+ [](char c) { return c == '-' ? '_' : toupper(c); });
+ if (auto prefix_env = getenv(env_name.c_str())) {
+ args.insert(args.begin() + insert_pos, addEnvironmentArg(flag, prefix_env));
+ }
+ // Now reuse the same name variable to construct a suffix version: append the
+ // underscore and just skip the one in front.
+ env_name += '_';
+ if (auto suffix_env = getenv(env_name.c_str() + 1)) {
+ args.push_back(addEnvironmentArg(flag, suffix_env));
+ }
+ }
+}
+
+int Command::Execute(std::vector<StringPiece>& args, std::ostream* out_error) {
TRACE_NAME_ARGS("Command::Execute", args);
std::vector<std::string> file_args;
+ parseFlagsFromEnvironment(args);
+
for (size_t i = 0; i < args.size(); i++) {
StringPiece arg = args[i];
if (*(arg.data()) != '-') {
- // Continue parsing as the subcommand if the first argument matches one of the subcommands
+ // Continue parsing as a subcommand if the first argument matches one of the subcommands
if (i == 0) {
for (auto& subcommand : subcommands_) {
if (arg == subcommand->name_ || (!subcommand->short_name_.empty()
@@ -211,37 +272,67 @@ int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_err
return 1;
}
+ static constexpr auto matchShortArg = [](std::string_view arg, const Flag& flag) static {
+ return flag.name.starts_with("--") &&
+ arg.compare(0, 2, std::string_view(flag.name.c_str() + 1, 2)) == 0;
+ };
+
bool match = false;
for (Flag& flag : flags_) {
- // Allow both "--arg value" and "--arg=value" syntax.
+ // Allow both "--arg value" and "--arg=value" syntax, and look for the cases where we can
+ // safely deduce the "--arg" flag from the short "-a" version when there's no value expected
+ bool matched_current = false;
if (arg.starts_with(flag.name) &&
(arg.size() == flag.name.size() || (flag.num_args > 0 && arg[flag.name.size()] == '='))) {
- if (flag.num_args > 0) {
- if (arg.size() == flag.name.size()) {
- i++;
- if (i >= args.size()) {
- *out_error << flag.name << " missing argument.\n\n";
- Usage(out_error);
- return 1;
- }
- arg = args[i];
- } else {
- arg.remove_prefix(flag.name.size() + 1);
- // Disallow empty arguments after '='.
- if (arg.empty()) {
- *out_error << flag.name << " has empty argument.\n\n";
- Usage(out_error);
- return 1;
- }
+ matched_current = true;
+ } else if (flag.num_args == 0 && matchShortArg(arg, flag)) {
+ matched_current = true;
+ // It matches, now need to make sure no other flag would match as well.
+ // This is really inefficient, but we don't expect to have enough flags for it to matter
+ // (famous last words).
+ for (const Flag& other_flag : flags_) {
+ if (&other_flag == &flag) {
+ continue;
+ }
+ if (matchShortArg(arg, other_flag)) {
+ matched_current = false; // ambiguous, skip this match
+ break;
+ }
+ }
+ }
+ if (!matched_current) {
+ continue;
+ }
+
+ if (flag.num_args > 0) {
+ if (arg.size() == flag.name.size()) {
+ i++;
+ if (i >= args.size()) {
+ *out_error << flag.name << " missing argument.\n\n";
+ Usage(out_error);
+ return 1;
}
- flag.action(arg);
+ arg = args[i];
} else {
- flag.action({});
+ arg.remove_prefix(flag.name.size() + 1);
+ // Disallow empty arguments after '='.
+ if (arg.empty()) {
+ *out_error << flag.name << " has empty argument.\n\n";
+ Usage(out_error);
+ return 1;
+ }
+ }
+ if (!flag.action(arg, out_error)) {
+ return 1;
+ }
+ } else {
+ if (!flag.action({}, out_error)) {
+ return 1;
}
- flag.found = true;
- match = true;
- break;
}
+ flag.found = true;
+ match = true;
+ break;
}
if (!match) {
diff --git a/tools/aapt2/cmd/Command.h b/tools/aapt2/cmd/Command.h
index 1416e980ed19..767ca9b0de9f 100644
--- a/tools/aapt2/cmd/Command.h
+++ b/tools/aapt2/cmd/Command.h
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#ifndef AAPT_COMMAND_H
-#define AAPT_COMMAND_H
+#pragma once
+#include <deque>
#include <functional>
+#include <memory>
#include <optional>
#include <ostream>
#include <string>
@@ -30,10 +31,17 @@ namespace aapt {
class Command {
public:
- explicit Command(android::StringPiece name) : name_(name), full_subcommand_name_(name){};
+ explicit Command(android::StringPiece name) : Command(name, {}) {
+ }
explicit Command(android::StringPiece name, android::StringPiece short_name)
- : name_(name), short_name_(short_name), full_subcommand_name_(name){};
+ : name_(name), short_name_(short_name), full_subcommand_name_(name) {
+ flags_.emplace_back("--help", "Displays this help menu", false, 0,
+ [this](android::StringPiece arg, std::ostream* out) {
+ Usage(out);
+ return false;
+ });
+ }
Command(Command&&) = default;
Command& operator=(Command&&) = default;
@@ -76,41 +84,51 @@ class Command {
// Parses the command line arguments, sets the flag variable values, and runs the action of
// the command. If the arguments fail to parse to the command and its subcommands, then the action
// will not be run and the usage will be printed instead.
- int Execute(const std::vector<android::StringPiece>& args, std::ostream* outError);
+ int Execute(std::vector<android::StringPiece>& args, std::ostream* out_error);
+
+ // Same, but for a temporary vector of args.
+ int Execute(std::vector<android::StringPiece>&& args, std::ostream* out_error) {
+ return Execute(args, out_error);
+ }
// The action to preform when the command is executed.
virtual int Action(const std::vector<std::string>& args) = 0;
private:
struct Flag {
- explicit Flag(android::StringPiece name, android::StringPiece description,
- const bool is_required, const size_t num_args,
- std::function<bool(android::StringPiece value)>&& action)
+ explicit Flag(android::StringPiece name, android::StringPiece description, bool is_required,
+ const size_t num_args,
+ std::function<bool(android::StringPiece value, std::ostream* out_err)>&& action)
: name(name),
description(description),
- is_required(is_required),
+ action(std::move(action)),
num_args(num_args),
- action(std::move(action)) {
+ is_required(is_required) {
}
- const std::string name;
- const std::string description;
- const bool is_required;
- const size_t num_args;
- const std::function<bool(android::StringPiece value)> action;
+ std::string name;
+ std::string description;
+ std::function<bool(android::StringPiece value, std::ostream* out_error)> action;
+ size_t num_args;
+ bool is_required;
bool found = false;
};
+ const std::string& addEnvironmentArg(const Flag& flag, const char* env);
+ void parseFlagsFromEnvironment(std::vector<android::StringPiece>& args);
+
std::string name_;
std::string short_name_;
- std::string description_ = "";
+ std::string description_;
std::string full_subcommand_name_;
std::vector<Flag> flags_;
std::vector<std::unique_ptr<Command>> subcommands_;
std::vector<std::unique_ptr<Command>> experimental_subcommands_;
+ // A collection of arguments loaded from environment variables, with stable positions
+ // in memory - we add them to the vector of string views so the pointers may not change,
+ // with or without short string buffer utilization in std::string.
+ std::deque<std::string> environment_args_;
};
} // namespace aapt
-
-#endif // AAPT_COMMAND_H
diff --git a/tools/aapt2/cmd/Command_test.cpp b/tools/aapt2/cmd/Command_test.cpp
index 20d87e0025c3..2a3cb2a0c65d 100644
--- a/tools/aapt2/cmd/Command_test.cpp
+++ b/tools/aapt2/cmd/Command_test.cpp
@@ -118,4 +118,45 @@ TEST(CommandTest, OptionsWithValues) {
EXPECT_NE(0, command.Execute({"--flag1"s, "2"s}, &std::cerr));
}
+TEST(CommandTest, ShortOptions) {
+ TestCommand command;
+ bool flag = false;
+ command.AddOptionalSwitch("--flag", "", &flag);
+
+ ASSERT_EQ(0, command.Execute({"--flag"s}, &std::cerr));
+ EXPECT_TRUE(flag);
+
+ // Short version of a switch should work.
+ flag = false;
+ ASSERT_EQ(0, command.Execute({"-f"s}, &std::cerr));
+ EXPECT_TRUE(flag);
+
+ // Ambiguous names shouldn't parse via short options.
+ command.AddOptionalSwitch("--flag-2", "", &flag);
+ ASSERT_NE(0, command.Execute({"-f"s}, &std::cerr));
+
+ // But when we have a proper flag like that it should still work.
+ flag = false;
+ command.AddOptionalSwitch("-f", "", &flag);
+ ASSERT_EQ(0, command.Execute({"-f"s}, &std::cerr));
+ EXPECT_TRUE(flag);
+
+ // A regular short flag works fine as well.
+ flag = false;
+ command.AddOptionalSwitch("-d", "", &flag);
+ ASSERT_EQ(0, command.Execute({"-d"s}, &std::cerr));
+ EXPECT_TRUE(flag);
+
+ // A flag with a value only works via its long name syntax.
+ std::optional<std::string> val;
+ command.AddOptionalFlag("--with-val", "", &val);
+ ASSERT_EQ(0, command.Execute({"--with-val"s, "1"s}, &std::cerr));
+ EXPECT_TRUE(val);
+ EXPECT_STREQ("1", val->c_str());
+
+ // Make sure the flags that require a value can't be parsed via short syntax, -w=blah
+ // looks weird.
+ ASSERT_NE(0, command.Execute({"-w"s, "2"s}, &std::cerr));
+}
+
} // namespace aapt \ No newline at end of file