summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING8
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/system-current.txt2
-rw-r--r--core/java/android/content/res/Element.java7
-rw-r--r--core/java/android/os/PerformanceHintManager.java25
-rw-r--r--core/java/android/os/PowerManager.java9
-rw-r--r--core/java/android/os/TEST_MAPPING7
-rw-r--r--core/java/android/view/inputmethod/RemoteInputConnectionImpl.java12
-rw-r--r--core/java/android/widget/HorizontalScrollView.java5
-rw-r--r--core/java/android/widget/ScrollView.java5
-rw-r--r--core/java/com/android/internal/app/NetInitiatedActivity.java130
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java48
-rw-r--r--core/java/com/android/internal/os/TEST_MAPPING11
-rw-r--r--core/java/com/android/internal/power/TEST_MAPPING6
-rw-r--r--core/jni/android_media_AudioSystem.cpp9
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/Android.bp1
-rw-r--r--core/tests/coretests/AndroidManifest.xml22
-rw-r--r--core/tests/coretests/AndroidTest.xml1
-rw-r--r--core/tests/coretests/BstatsTestApp/OWNERS1
-rw-r--r--core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml118
-rw-r--r--core/tests/coretests/res/layout/activity_scroll_view.xml118
-rw-r--r--core/tests/coretests/src/android/os/PerformanceHintManagerTest.java18
-rw-r--r--core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java34
-rw-r--r--core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java71
-rw-r--r--core/tests/coretests/src/android/widget/ScrollViewActivity.java (renamed from packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt)27
-rw-r--r--core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java71
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java28
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java281
-rw-r--r--location/java/android/location/LocationManagerInternal.java6
-rw-r--r--location/java/com/android/internal/location/GpsNetInitiatedHandler.java483
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java2
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt6
-rw-r--r--packages/SystemUI/res/layout/keyguard_bottom_area.xml36
-rw-r--r--packages/SystemUI/res/values/flags.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java22
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java37
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt141
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/DisplayTracker.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt80
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt115
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt55
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt53
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java105
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt60
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt135
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt192
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt125
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt431
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt9
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt10
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java10
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java23
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java5
-rw-r--r--services/core/java/com/android/server/am/TEST_MAPPING26
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java7
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java7
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java102
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssManagerService.java12
-rw-r--r--services/core/java/com/android/server/location/gnss/hal/GnssNative.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerInternalBase.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java7
-rw-r--r--services/core/java/com/android/server/power/TEST_MAPPING13
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java9
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp68
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java3
-rw-r--r--services/tests/powerstatstests/Android.bp52
-rw-r--r--services/tests/powerstatstests/AndroidManifest.xml32
-rw-r--r--services/tests/powerstatstests/AndroidTest.xml35
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/Android.bp (renamed from core/tests/coretests/BstatsTestApp/Android.bp)0
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/AndroidManifest.xml (renamed from core/tests/coretests/BstatsTestApp/AndroidManifest.xml)0
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java (renamed from core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java)0
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java (renamed from core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java)4
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java (renamed from core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java)0
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java (renamed from core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java)0
-rw-r--r--services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java (renamed from core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java)0
-rw-r--r--services/tests/powerstatstests/OWNERS (renamed from services/tests/servicestests/src/com/android/server/powerstats/OWNERS)3
-rw-r--r--services/tests/powerstatstests/TEST_MAPPING22
-rw-r--r--services/tests/powerstatstests/res/xml/irq_device_map_1.xml (renamed from services/tests/servicestests/res/xml/irq_device_map_1.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/irq_device_map_2.xml (renamed from services/tests/servicestests/res/xml/irq_device_map_2.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/irq_device_map_3.xml (renamed from services/tests/servicestests/res/xml/irq_device_map_3.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/power_profile_test_legacy_modem.xml (renamed from services/tests/servicestests/res/xml/power_profile_test_legacy_modem.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator.xml (renamed from services/tests/servicestests/res/xml/power_profile_test_modem_calculator.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator_multiactive.xml (renamed from services/tests/servicestests/res/xml/power_profile_test_modem_calculator_multiactive.xml)0
-rw-r--r--services/tests/powerstatstests/res/xml/power_profile_test_modem_default.xml (renamed from services/tests/servicestests/res/xml/power_profile_test_modem_default.xml)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCounterTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCounterTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java)2
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsManagerTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java)16
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSensorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSensorTest.java)16
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsServTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsServTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java)16
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimerTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimerTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java)16
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java)2
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/MockClock.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/MockClock.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/OWNERS (renamed from services/tests/servicestests/src/com/android/server/power/stats/OWNERS)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/UserPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/UserPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java)2
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java)2
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java (renamed from services/tests/servicestests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java (renamed from services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java)0
-rw-r--r--services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java (renamed from services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java)0
-rw-r--r--services/tests/servicestests/Android.bp1
-rw-r--r--services/tests/servicestests/AndroidTest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java132
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt11
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTests.java72
-rw-r--r--services/usage/java/com/android/server/usage/TEST_MAPPING13
-rw-r--r--telecomm/java/android/telecom/Call.java4
-rw-r--r--telecomm/java/android/telecom/Phone.java3
-rw-r--r--tests/testables/src/android/testing/TestableResources.java12
187 files changed, 2852 insertions, 1704 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index 6a4a52a5658b..9ec799f73b41 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -4,7 +4,6 @@
"name": "CtsUsageStatsTestCases",
"options": [
{"include-filter": "android.app.usage.cts.UsageStatsTest"},
- {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
{"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.MediumTest"},
@@ -12,6 +11,13 @@
]
},
{
+ "name": "CtsBRSTestCases",
+ "options": [
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {"exclude-annotation": "org.junit.Ignore"}
+ ]
+ },
+ {
"name": "FrameworksServicesTests",
"options": [
{"include-filter": "com.android.server.usage"},
diff --git a/core/api/current.txt b/core/api/current.txt
index 3392d250d426..0b10d648e36f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -33699,7 +33699,7 @@ package android.os {
method public boolean isInteractive();
method public boolean isLowPowerStandbyEnabled();
method public boolean isPowerSaveMode();
- method public boolean isRebootingUserspaceSupported();
+ method @Deprecated public boolean isRebootingUserspaceSupported();
method @Deprecated public boolean isScreenOn();
method public boolean isSustainedPerformanceModeSupported();
method public boolean isWakeLockLevelSupported(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a02fd84ce33c..eca2015fa3ed 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10748,7 +10748,7 @@ package android.os {
field @RequiresPermission(android.Manifest.permission.MANAGE_LOW_POWER_STANDBY) public static final String ACTION_LOW_POWER_STANDBY_PORTS_CHANGED = "android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED";
field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
- field public static final String REBOOT_USERSPACE = "userspace";
+ field @Deprecated public static final String REBOOT_USERSPACE = "userspace";
field public static final int SOUND_TRIGGER_MODE_ALL_DISABLED = 2; // 0x2
field public static final int SOUND_TRIGGER_MODE_ALL_ENABLED = 0; // 0x0
field public static final int SOUND_TRIGGER_MODE_CRITICAL_ONLY = 1; // 0x1
diff --git a/core/java/android/content/res/Element.java b/core/java/android/content/res/Element.java
index a86c0c9a4463..0438ecce78ef 100644
--- a/core/java/android/content/res/Element.java
+++ b/core/java/android/content/res/Element.java
@@ -128,6 +128,7 @@ public class Element {
protected static final String TAG_ATTR_VALUE = "value";
protected static final String TAG_ATTR_VERSION_NAME = "versionName";
protected static final String TAG_ATTR_WRITE_PERMISSION = "writePermission";
+ protected static final String TAG_ATTR_ZYGOTE_PRELOAD_NAME = "zygotePreloadName";
// The length of mTagCounters corresponds to the number of tags defined in getCounterIdx. If new
// tags are added then the size here should be increased to match.
@@ -374,6 +375,7 @@ public class Element {
case TAG_ATTR_TASK_AFFINITY:
case TAG_ATTR_WRITE_PERMISSION:
case TAG_ATTR_VERSION_NAME:
+ case TAG_ATTR_ZYGOTE_PRELOAD_NAME:
return MAX_ATTR_LEN_NAME;
case TAG_ATTR_PATH:
case TAG_ATTR_PATH_ADVANCED_PATTERN:
@@ -488,6 +490,7 @@ public class Element {
case R.styleable.AndroidManifestApplication_requiredAccountType:
case R.styleable.AndroidManifestApplication_restrictedAccountType:
case R.styleable.AndroidManifestApplication_taskAffinity:
+ case R.styleable.AndroidManifestApplication_zygotePreloadName:
return MAX_ATTR_LEN_NAME;
default:
return DEFAULT_MAX_STRING_ATTR_LENGTH;
@@ -738,6 +741,7 @@ public class Element {
switch (name) {
case TAG_ATTR_BACKUP_AGENT:
case TAG_ATTR_NAME:
+ case TAG_ATTR_ZYGOTE_PRELOAD_NAME:
return true;
default:
return false;
@@ -766,7 +770,8 @@ public class Element {
return index == R.styleable.AndroidManifestActivityAlias_targetActivity;
case TAG_APPLICATION:
return index == R.styleable.AndroidManifestApplication_backupAgent
- || index == R.styleable.AndroidManifestApplication_name;
+ || index == R.styleable.AndroidManifestApplication_name
+ || index == R.styleable.AndroidManifestApplication_zygotePreloadName;
case TAG_INSTRUMENTATION:
return index == R.styleable.AndroidManifestInstrumentation_name;
case TAG_PROVIDER:
diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java
index 977ef60c43b6..bcea7978a804 100644
--- a/core/java/android/os/PerformanceHintManager.java
+++ b/core/java/android/os/PerformanceHintManager.java
@@ -55,15 +55,20 @@ public final class PerformanceHintManager {
* duration.
*
* @param tids The list of threads to be associated with this session. They must be part of
- * this process' thread group.
+ * this process' thread group
* @param initialTargetWorkDurationNanos The desired duration in nanoseconds for the new
- * session.
+ * session
* @return the new session if it is supported on this device, null if hint session is not
- * supported on this device.
+ * supported on this device or the tid doesn't belong to the application
+ * @throws IllegalArgumentException if the thread id list is empty, or
+ * initialTargetWorkDurationNanos is non-positive
*/
@Nullable
public Session createHintSession(@NonNull int[] tids, long initialTargetWorkDurationNanos) {
- Preconditions.checkNotNull(tids, "tids cannot be null");
+ Objects.requireNonNull(tids, "tids cannot be null");
+ if (tids.length == 0) {
+ throw new IllegalArgumentException("thread id list can't be empty.");
+ }
Preconditions.checkArgumentPositive(initialTargetWorkDurationNanos,
"the hint target duration should be positive.");
long nativeSessionPtr = nativeCreateSession(mNativeManagerPtr, tids,
@@ -75,7 +80,7 @@ public final class PerformanceHintManager {
/**
* Get preferred update rate information for this device.
*
- * @return the preferred update rate supported by device software.
+ * @return the preferred update rate supported by device software
*/
public long getPreferredUpdateRateNanos() {
return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr);
@@ -209,7 +214,7 @@ public final class PerformanceHintManager {
/**
* Sends performance hints to inform the hint session of changes in the workload.
*
- * @param hint The hint to send to the session.
+ * @param hint The hint to send to the session
*
* @hide
*/
@@ -230,11 +235,11 @@ public final class PerformanceHintManager {
* Note that this is not an oneway method.
*
* @param tids The list of threads to be associated with this session. They must be
- * part of this app's thread group.
+ * part of this app's thread group
*
- * @throws IllegalStateException if the hint session is not in the foreground.
- * @throws IllegalArgumentException if the thread id list is empty.
- * @throws SecurityException if any thread id doesn't belong to the application.
+ * @throws IllegalStateException if the hint session is not in the foreground
+ * @throws IllegalArgumentException if the thread id list is empty
+ * @throws SecurityException if any thread id doesn't belong to the application
*/
public void setThreads(@NonNull int[] tids) {
if (mNativeSessionPtr == 0) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index c6b9d20b450d..d676509d9317 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -33,7 +33,6 @@ import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.service.dreams.Sandman;
-import android.sysprop.InitProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -868,6 +867,8 @@ public final class PowerManager {
/**
* The 'reason' value used for rebooting userspace.
+ *
+ * @deprecated userspace reboot is not supported
* @hide
*/
@SystemApi
@@ -1824,16 +1825,18 @@ public final class PowerManager {
* <p>This method exists solely for the sake of re-using same logic between {@code PowerManager}
* and {@code PowerManagerService}.
*
+ * @deprecated TODO(b/292469129): remove this method.
* @hide
*/
public static boolean isRebootingUserspaceSupportedImpl() {
- return InitProperties.is_userspace_reboot_supported().orElse(false);
+ return false;
}
/**
* Returns {@code true} if this device supports rebooting userspace.
+ *
+ * @deprecated userspace reboot is deprecated, this method always returns {@code false}.
*/
- // TODO(b/138605180): add link to documentation once it's ready.
public boolean isRebootingUserspaceSupported() {
return isRebootingUserspaceSupportedImpl();
}
diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING
index dae9b5ea6a43..60622f18fe3b 100644
--- a/core/java/android/os/TEST_MAPPING
+++ b/core/java/android/os/TEST_MAPPING
@@ -99,13 +99,10 @@
"BatteryStats[^/]*\\.java",
"BatteryUsageStats[^/]*\\.java",
"PowerComponents\\.java",
+ "PowerMonitor[^/]*\\.java",
"[^/]*BatteryConsumer[^/]*\\.java"
],
- "name": "FrameworksServicesTests",
- "options": [
- { "include-filter": "com.android.server.power.stats" },
- { "exclude-filter": "com.android.server.power.stats.BatteryStatsTests" }
- ]
+ "name": "PowerStatsTests"
},
{
"file_patterns": [
diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
index 987ac2e90240..d588c487844b 100644
--- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java
@@ -809,11 +809,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
return; // cancelled
}
InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
- if (ic == null) {
+ if (ic == null || !isActive()) {
Log.w(TAG, "finishComposingTextFromImm on inactive InputConnection");
return;
}
@@ -837,11 +833,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
return; // cancelled
}
InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
- if (ic == null) {
+ if (ic == null && !isActive()) {
Log.w(TAG, "finishComposingText on inactive InputConnection");
return;
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 1d6778b8a4a9..55b2251ac196 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1498,6 +1498,11 @@ public class HorizontalScrollView extends FrameLayout {
* @return The unconsumed delta after the EdgeEffects have had an opportunity to consume.
*/
private int consumeFlingInStretch(int unconsumed) {
+ int scrollX = getScrollX();
+ if (scrollX < 0 || scrollX > getScrollRange()) {
+ // We've overscrolled, so don't stretch
+ return unconsumed;
+ }
if (unconsumed > 0 && mEdgeGlowLeft != null && mEdgeGlowLeft.getDistance() != 0f) {
int size = getWidth();
float deltaDistance = -unconsumed * FLING_DESTRETCH_FACTOR / size;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index eeb6b43a89f2..d330ebf73323 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1566,6 +1566,11 @@ public class ScrollView extends FrameLayout {
* @return The unconsumed delta after the EdgeEffects have had an opportunity to consume.
*/
private int consumeFlingInStretch(int unconsumed) {
+ int scrollY = getScrollY();
+ if (scrollY < 0 || scrollY > getScrollRange()) {
+ // We've overscrolled, so don't stretch
+ return unconsumed;
+ }
if (unconsumed > 0 && mEdgeGlowTop != null && mEdgeGlowTop.getDistance() != 0f) {
int size = getHeight();
float deltaDistance = -unconsumed * FLING_DESTRETCH_FACTOR / size;
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
deleted file mode 100644
index f34aabbeded6..000000000000
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.location.LocationManagerInternal;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.R;
-import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.server.LocalServices;
-
-/**
- * This activity is shown to the user for them to accept or deny network-initiated
- * requests. It uses the alert dialog style. It will be launched from a notification.
- */
-public class NetInitiatedActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final String TAG = "NetInitiatedActivity";
-
- private static final boolean DEBUG = true;
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
- private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE;
-
- private static final int GPS_NO_RESPONSE_TIME_OUT = 1;
- // Received ID from intent, -1 when no notification is in progress
- private int notificationId = -1;
- private int timeout = -1;
- private int default_response = -1;
- private int default_response_timeout = 6;
-
- private final Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case GPS_NO_RESPONSE_TIME_OUT: {
- if (notificationId != -1) {
- sendUserResponse(default_response);
- }
- finish();
- }
- break;
- default:
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-
- // Set up the "dialog"
- final Intent intent = getIntent();
- final AlertController.AlertParams p = mAlertParams;
- Context context = getApplicationContext();
- p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
- p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
- p.mPositiveButtonText = String.format(context.getString(R.string.gpsVerifYes));
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = String.format(context.getString(R.string.gpsVerifNo));
- p.mNegativeButtonListener = this;
-
- notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
- timeout = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TIMEOUT, default_response_timeout);
- default_response = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_DEFAULT_RESPONSE, GpsNetInitiatedHandler.GPS_NI_RESPONSE_ACCEPT);
- if (DEBUG) Log.d(TAG, "onCreate() : notificationId: " + notificationId + " timeout: " + timeout + " default_response:" + default_response);
-
- mHandler.sendMessageDelayed(mHandler.obtainMessage(GPS_NO_RESPONSE_TIME_OUT), (timeout * 1000));
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (DEBUG) Log.d(TAG, "onResume");
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- if (DEBUG) Log.d(TAG, "onPause");
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
- if (which == POSITIVE_BUTTON) {
- sendUserResponse(GpsNetInitiatedHandler.GPS_NI_RESPONSE_ACCEPT);
- }
- if (which == NEGATIVE_BUTTON) {
- sendUserResponse(GpsNetInitiatedHandler.GPS_NI_RESPONSE_DENY);
- }
-
- // No matter what, finish the activity
- finish();
- notificationId = -1;
- }
-
- // Respond to NI Handler under GnssLocationProvider, 1 = accept, 2 = deny
- private void sendUserResponse(int response) {
- if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response);
- LocationManagerInternal lm = LocalServices.getService(LocationManagerInternal.class);
- lm.sendNiResponse(notificationId, response);
- }
-}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 2445daf89b64..ac15f11ee989 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -40,6 +40,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UiThread;
@@ -68,6 +69,7 @@ import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Insets;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
@@ -93,6 +95,7 @@ import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
@@ -488,6 +491,14 @@ public class ResolverActivity extends Activity implements
rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
mResolverDrawerLayout = rdl;
+
+ for (int i = 0, size = mMultiProfilePagerAdapter.getCount(); i < size; i++) {
+ View view = mMultiProfilePagerAdapter.getItem(i).rootView.findViewById(
+ R.id.resolver_list);
+ if (view != null) {
+ view.setAccessibilityDelegate(new AppListAccessibilityDelegate(rdl));
+ }
+ }
}
mProfileView = findViewById(R.id.profile_button);
@@ -2607,4 +2618,41 @@ public class ResolverActivity extends Activity implements
}
return resolveInfo.userHandle;
}
+
+ /**
+ * An a11y delegate that expands resolver drawer when gesture navigation reaches a partially
+ * invisible target in the list.
+ */
+ private static class AppListAccessibilityDelegate extends View.AccessibilityDelegate {
+ private final ResolverDrawerLayout mDrawer;
+ @Nullable
+ private final View mBottomBar;
+ private final Rect mRect = new Rect();
+
+ private AppListAccessibilityDelegate(ResolverDrawerLayout drawer) {
+ mDrawer = drawer;
+ mBottomBar = mDrawer.findViewById(R.id.button_bar_container);
+ }
+
+ @Override
+ public boolean onRequestSendAccessibilityEvent(@androidx.annotation.NonNull ViewGroup host,
+ @NonNull View child,
+ @NonNull AccessibilityEvent event) {
+ boolean result = super.onRequestSendAccessibilityEvent(host, child, event);
+ if (result && event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
+ && mDrawer.isCollapsed()) {
+ child.getBoundsOnScreen(mRect);
+ int childTop = mRect.top;
+ int childBottom = mRect.bottom;
+ mDrawer.getBoundsOnScreen(mRect, true);
+ int bottomBarHeight = mBottomBar == null ? 0 : mBottomBar.getHeight();
+ int drawerTop = mRect.top;
+ int drawerBottom = mRect.bottom - bottomBarHeight;
+ if (drawerTop > childTop || childBottom > drawerBottom) {
+ mDrawer.setCollapsed(false);
+ }
+ }
+ return result;
+ }
+ }
}
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index 60b160ad18c2..d552e0b8c643 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -38,11 +38,18 @@
],
"name": "FrameworksServicesTests",
"options": [
- { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
- { "include-filter": "com.android.server.power.stats.BatteryStatsTests" }
+ { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }
]
},
{
+ "file_patterns": [
+ "Battery[^/]*\\.java",
+ "Kernel[^/]*\\.java",
+ "[^/]*Power[^/]*\\.java"
+ ],
+ "name": "PowerStatsTests"
+ },
+ {
"name": "FrameworksCoreTests",
"options": [
{
diff --git a/core/java/com/android/internal/power/TEST_MAPPING b/core/java/com/android/internal/power/TEST_MAPPING
index c6cab183d970..1946f5cc99eb 100644
--- a/core/java/com/android/internal/power/TEST_MAPPING
+++ b/core/java/com/android/internal/power/TEST_MAPPING
@@ -8,11 +8,7 @@
]
},
{
- "name": "FrameworksServicesTests",
- "options": [
- { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
- { "include-filter": "com.android.server.power.stats.BatteryStatsTests" }
- ]
+ "name": "PowerStatsTests"
}
]
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 4cf17b78f489..199854818989 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -523,13 +523,14 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
}
jclass clazz = env->FindClass(kClassPathName);
- const char* zechars = regId.string();
- jstring zestring = env->NewStringUTF(zechars);
+ const char *regIdString = regId.string();
+ jstring regIdJString = env->NewStringUTF(regIdString);
env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
- event, zestring, val);
+ event, regIdJString, val);
- env->ReleaseStringUTFChars(zestring, zechars);
+ const char *regIdJChars = env->GetStringUTFChars(regIdJString, NULL);
+ env->ReleaseStringUTFChars(regIdJString, regIdJChars);
env->DeleteLocalRef(clazz);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 86cf80e8847c..67710f64e1e4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -821,7 +821,6 @@
<protected-broadcast android:name="android.intent.action.PROFILE_REMOVED" />
<protected-broadcast android:name="com.android.internal.telephony.cat.SMS_SENT_ACTION" />
<protected-broadcast android:name="com.android.internal.telephony.cat.SMS_DELIVERY_ACTION" />
- <protected-broadcast android:name="com.android.internal.telephony.data.ACTION_RETRY" />
<protected-broadcast android:name="android.companion.virtual.action.VIRTUAL_DEVICE_REMOVED" />
<protected-broadcast android:name="com.android.internal.intent.action.FLASH_NOTIFICATION_START_PREVIEW" />
<protected-broadcast android:name="com.android.internal.intent.action.FLASH_NOTIFICATION_STOP_PREVIEW" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a11eaa91b2a6..d828f33ca514 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1786,10 +1786,6 @@
<string name="biometric_dialog_default_title">Verify it\u2019s you</string>
<!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face). [CHAR LIMIT=70] -->
<string name="biometric_dialog_default_subtitle">Use your biometric to continue</string>
- <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with fingerprint. [CHAR LIMIT=70] -->
- <string name="biometric_dialog_fingerprint_subtitle">Use your fingerprint to continue</string>
- <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with face. [CHAR LIMIT=70] -->
- <string name="biometric_dialog_face_subtitle">Use your face to continue</string>
<!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with a biometric (e.g. fingerprint or face) or their screen lock credential (i.e. PIN, pattern, or password). [CHAR LIMIT=90] -->
<string name="biometric_or_screen_lock_dialog_default_subtitle">Use your biometric or screen lock to continue</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5806e93d4a93..63f29a8fc1c6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2585,8 +2585,6 @@
<java-symbol type="string" name="biometric_or_screen_lock_app_setting_name" />
<java-symbol type="string" name="biometric_dialog_default_title" />
<java-symbol type="string" name="biometric_dialog_default_subtitle" />
- <java-symbol type="string" name="biometric_dialog_face_subtitle" />
- <java-symbol type="string" name="biometric_dialog_fingerprint_subtitle" />
<java-symbol type="string" name="biometric_or_screen_lock_dialog_default_subtitle" />
<java-symbol type="string" name="biometric_error_hw_unavailable" />
<java-symbol type="string" name="biometric_error_user_canceled" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index c7aaeb0339bd..c14da299c6ef 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -91,7 +91,6 @@ android_test {
java_resources: [":ApkVerityTestCertDer"],
data: [
- ":BstatsTestApp",
":BinderDeathRecipientHelperApp1",
":BinderDeathRecipientHelperApp2",
":com.android.cts.helpers.aosp",
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 129de649a4b5..31755efb88ed 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -231,6 +231,28 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.HorizontalScrollViewActivity"
+ android:label="HorizontalScrollViewActivity"
+ android:screenOrientation="portrait"
+ android:exported="true"
+ android:theme="@android:style/Theme.Material.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.ScrollViewActivity"
+ android:label="ScrollViewActivity"
+ android:screenOrientation="portrait"
+ android:exported="true"
+ android:theme="@android:style/Theme.Material.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.widget.DatePickerActivity"
android:label="DatePickerActivity"
android:screenOrientation="portrait"
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 3e4c47b36ed9..05b309b2cd52 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -20,7 +20,6 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="FrameworksCoreTests.apk" />
- <option name="test-file-name" value="BstatsTestApp.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
</target_preparer>
diff --git a/core/tests/coretests/BstatsTestApp/OWNERS b/core/tests/coretests/BstatsTestApp/OWNERS
deleted file mode 100644
index 4068e2bc03b7..000000000000
--- a/core/tests/coretests/BstatsTestApp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /BATTERY_STATS_OWNERS
diff --git a/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml b/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml
new file mode 100644
index 000000000000..866e1a95c3f5
--- /dev/null
+++ b/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/horizontal_scroll_view">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ </LinearLayout>
+</HorizontalScrollView>
diff --git a/core/tests/coretests/res/layout/activity_scroll_view.xml b/core/tests/coretests/res/layout/activity_scroll_view.xml
new file mode 100644
index 000000000000..61fabf8ee437
--- /dev/null
+++ b/core/tests/coretests/res/layout/activity_scroll_view.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2015 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
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/scroll_view">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#F00"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#880"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#0F0"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#088"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#00F"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ <View
+ android:background="#808"
+ android:layout_width="100dp"
+ android:layout_height="100dp" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
index 2c03fdc2ef0d..b0826ab77035 100644
--- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
@@ -69,6 +69,24 @@ public class PerformanceHintManagerTest {
}
@Test
+ public void testCreateHintSession_noTids() {
+ assertThrows(NullPointerException.class, () -> {
+ mPerformanceHintManager.createHintSession(
+ null, DEFAULT_TARGET_NS);
+ });
+ assertThrows(IllegalArgumentException.class, () -> {
+ mPerformanceHintManager.createHintSession(
+ new int[]{}, DEFAULT_TARGET_NS);
+ });
+ }
+
+ @Test
+ public void testCreateHintSession_invalidTids() {
+ assertNull(mPerformanceHintManager.createHintSession(
+ new int[]{-1}, DEFAULT_TARGET_NS));
+ }
+
+ @Test
public void testGetPreferredUpdateRateNanos() {
if (createSession() != null) {
assertTrue(mPerformanceHintManager.getPreferredUpdateRateNanos() > 0);
diff --git a/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java b/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java
new file mode 100644
index 000000000000..21013545008c
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * An activity for testing the TextView widget.
+ */
+public class HorizontalScrollViewActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_horizontal_scroll_view);
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java b/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java
new file mode 100644
index 000000000000..86f26e59e370
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 android.widget;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.util.PollingCheck;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Presubmit
+public class HorizontalScrollViewFunctionalTest {
+ private HorizontalScrollViewActivity mActivity;
+ private HorizontalScrollView mHorizontalScrollView;
+ @Rule
+ public ActivityTestRule<HorizontalScrollViewActivity> mActivityRule = new ActivityTestRule<>(
+ HorizontalScrollViewActivity.class);
+
+ @Before
+ public void setUp() throws Exception {
+ mActivity = mActivityRule.getActivity();
+ mHorizontalScrollView = mActivity.findViewById(R.id.horizontal_scroll_view);
+ }
+
+ @Test
+ public void testScrollAfterFlingTop() {
+ mHorizontalScrollView.scrollTo(100, 0);
+ mHorizontalScrollView.fling(-10000);
+ PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowLeft.getDistance() > 0);
+ PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowLeft.getDistance() == 0f);
+ assertEquals(0, mHorizontalScrollView.getScrollX());
+ }
+
+ @Test
+ public void testScrollAfterFlingBottom() {
+ int childWidth = mHorizontalScrollView.getChildAt(0).getWidth();
+ int maxScroll = childWidth - mHorizontalScrollView.getWidth();
+ mHorizontalScrollView.scrollTo(maxScroll - 100, 0);
+ mHorizontalScrollView.fling(10000);
+ PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowRight.getDistance() > 0);
+ PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowRight.getDistance() == 0f);
+ assertEquals(maxScroll, mHorizontalScrollView.getScrollX());
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt b/core/tests/coretests/src/android/widget/ScrollViewActivity.java
index c8f46a72d64f..899d63163aa4 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneTransitionModel.kt
+++ b/core/tests/coretests/src/android/widget/ScrollViewActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 The Android Open Source Project
+ * 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.
@@ -14,12 +14,21 @@
* limitations under the License.
*/
-package com.android.systemui.scene.shared.model
+package android.widget;
-/** Models a transition between two scenes. */
-data class SceneTransitionModel(
- /** The scene we transitioned away from. */
- val from: SceneKey,
- /** The scene we transitioned into. */
- val to: SceneKey,
-)
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * An activity for testing the TextView widget.
+ */
+public class ScrollViewActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_scroll_view);
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java b/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java
new file mode 100644
index 000000000000..a49bb6af13d2
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 android.widget;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.util.PollingCheck;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Presubmit
+public class ScrollViewFunctionalTest {
+ private ScrollViewActivity mActivity;
+ private ScrollView mScrollView;
+ @Rule
+ public ActivityTestRule<ScrollViewActivity> mActivityRule = new ActivityTestRule<>(
+ ScrollViewActivity.class);
+
+ @Before
+ public void setUp() throws Exception {
+ mActivity = mActivityRule.getActivity();
+ mScrollView = mActivity.findViewById(R.id.scroll_view);
+ }
+
+ @Test
+ public void testScrollAfterFlingTop() {
+ mScrollView.scrollTo(0, 100);
+ mScrollView.fling(-10000);
+ PollingCheck.waitFor(() -> mScrollView.mEdgeGlowTop.getDistance() > 0);
+ PollingCheck.waitFor(() -> mScrollView.mEdgeGlowTop.getDistance() == 0f);
+ assertEquals(0, mScrollView.getScrollY());
+ }
+
+ @Test
+ public void testScrollAfterFlingBottom() {
+ int childHeight = mScrollView.getChildAt(0).getHeight();
+ int maxScroll = childHeight - mScrollView.getHeight();
+ mScrollView.scrollTo(0, maxScroll - 100);
+ mScrollView.fling(10000);
+ PollingCheck.waitFor(() -> mScrollView.mEdgeGlowBottom.getDistance() > 0);
+ PollingCheck.waitFor(() -> mScrollView.mEdgeGlowBottom.getDistance() == 0f);
+ assertEquals(maxScroll, mScrollView.getScrollY());
+ }
+}
+
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index ee6996d3d23d..2c100653dae0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -661,14 +661,26 @@ public class BubblePositioner {
final boolean startOnLeft =
mContext.getResources().getConfiguration().getLayoutDirection()
!= LAYOUT_DIRECTION_RTL;
- final float startingVerticalOffset = mContext.getResources().getDimensionPixelOffset(
- R.dimen.bubble_stack_starting_offset_y);
- // TODO: placement bug here because mPositionRect doesn't handle the overhanging edge
- return new BubbleStackView.RelativeStackPosition(
- startOnLeft,
- startingVerticalOffset / mPositionRect.height())
- .getAbsolutePositionInRegion(getAllowableStackPositionRegion(
- 1 /* default starts with 1 bubble */));
+ final RectF allowableStackPositionRegion = getAllowableStackPositionRegion(
+ 1 /* default starts with 1 bubble */);
+ if (isLargeScreen()) {
+ // We want the stack to be visually centered on the edge, so we need to base it
+ // of a rect that includes insets.
+ final float desiredY = mScreenRect.height() / 2f - (mBubbleSize / 2f);
+ final float offset = desiredY / mScreenRect.height();
+ return new BubbleStackView.RelativeStackPosition(
+ startOnLeft,
+ offset)
+ .getAbsolutePositionInRegion(allowableStackPositionRegion);
+ } else {
+ final float startingVerticalOffset = mContext.getResources().getDimensionPixelOffset(
+ R.dimen.bubble_stack_starting_offset_y);
+ // TODO: placement bug here because mPositionRect doesn't handle the overhanging edge
+ return new BubbleStackView.RelativeStackPosition(
+ startOnLeft,
+ startingVerticalOffset / mPositionRect.height())
+ .getAbsolutePositionInRegion(allowableStackPositionRegion);
+ }
}
/**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
new file mode 100644
index 000000000000..139724f709c7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
@@ -0,0 +1,281 @@
+/*
+ * 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.wm.shell.bubbles;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.View.LAYOUT_DIRECTION_LTR;
+import static android.view.View.LAYOUT_DIRECTION_RTL;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests operations and the resulting state managed by {@link BubblePositioner}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class BubblePositionerTest extends ShellTestCase {
+
+ private static final int MIN_WIDTH_FOR_TABLET = 600;
+
+ private BubblePositioner mPositioner;
+ private Configuration mConfiguration;
+
+ @Mock
+ private WindowManager mWindowManager;
+ @Mock
+ private WindowMetrics mWindowMetrics;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mConfiguration = spy(new Configuration());
+ TestableResources testableResources = mContext.getOrCreateTestableResources();
+ testableResources.overrideConfiguration(mConfiguration);
+
+ mPositioner = new BubblePositioner(mContext, mWindowManager);
+ }
+
+ @Test
+ public void testUpdate() {
+ Insets insets = Insets.of(10, 20, 5, 15);
+ Rect screenBounds = new Rect(0, 0, 1000, 1200);
+ Rect availableRect = new Rect(screenBounds);
+ availableRect.inset(insets);
+
+ new WindowManagerConfig()
+ .setInsets(insets)
+ .setScreenBounds(screenBounds)
+ .setUpConfig();
+ mPositioner.update();
+
+ assertThat(mPositioner.getAvailableRect()).isEqualTo(availableRect);
+ assertThat(mPositioner.isLandscape()).isFalse();
+ assertThat(mPositioner.isLargeScreen()).isFalse();
+ assertThat(mPositioner.getInsets()).isEqualTo(insets);
+ }
+
+ @Test
+ public void testShowBubblesVertically_phonePortrait() {
+ new WindowManagerConfig().setOrientation(ORIENTATION_PORTRAIT).setUpConfig();
+ mPositioner.update();
+
+ assertThat(mPositioner.showBubblesVertically()).isFalse();
+ }
+
+ @Test
+ public void testShowBubblesVertically_phoneLandscape() {
+ new WindowManagerConfig().setOrientation(ORIENTATION_LANDSCAPE).setUpConfig();
+ mPositioner.update();
+
+ assertThat(mPositioner.isLandscape()).isTrue();
+ assertThat(mPositioner.showBubblesVertically()).isTrue();
+ }
+
+ @Test
+ public void testShowBubblesVertically_tablet() {
+ new WindowManagerConfig().setLargeScreen().setUpConfig();
+ mPositioner.update();
+
+ assertThat(mPositioner.showBubblesVertically()).isTrue();
+ }
+
+ /** If a resting position hasn't been set, calling it will return the default position. */
+ @Test
+ public void testGetRestingPosition_returnsDefaultPosition() {
+ new WindowManagerConfig().setUpConfig();
+ mPositioner.update();
+
+ PointF restingPosition = mPositioner.getRestingPosition();
+ PointF defaultPosition = mPositioner.getDefaultStartPosition();
+
+ assertThat(restingPosition).isEqualTo(defaultPosition);
+ }
+
+ /** If a resting position has been set, it'll return that instead of the default position. */
+ @Test
+ public void testGetRestingPosition_returnsRestingPosition() {
+ new WindowManagerConfig().setUpConfig();
+ mPositioner.update();
+
+ PointF restingPosition = new PointF(100, 100);
+ mPositioner.setRestingPosition(restingPosition);
+
+ assertThat(mPositioner.getRestingPosition()).isEqualTo(restingPosition);
+ }
+
+ /** Test that the default resting position on phone is in upper left. */
+ @Test
+ public void testGetRestingPosition_bubble_onPhone() {
+ new WindowManagerConfig().setUpConfig();
+ mPositioner.update();
+
+ RectF allowableStackRegion =
+ mPositioner.getAllowableStackPositionRegion(1 /* bubbleCount */);
+ PointF restingPosition = mPositioner.getRestingPosition();
+
+ assertThat(restingPosition.x).isEqualTo(allowableStackRegion.left);
+ assertThat(restingPosition.y).isEqualTo(getDefaultYPosition());
+ }
+
+ @Test
+ public void testGetRestingPosition_bubble_onPhone_RTL() {
+ new WindowManagerConfig().setLayoutDirection(LAYOUT_DIRECTION_RTL).setUpConfig();
+ mPositioner.update();
+
+ RectF allowableStackRegion =
+ mPositioner.getAllowableStackPositionRegion(1 /* bubbleCount */);
+ PointF restingPosition = mPositioner.getRestingPosition();
+
+ assertThat(restingPosition.x).isEqualTo(allowableStackRegion.right);
+ assertThat(restingPosition.y).isEqualTo(getDefaultYPosition());
+ }
+
+ /** Test that the default resting position on tablet is middle left. */
+ @Test
+ public void testGetRestingPosition_chatBubble_onTablet() {
+ new WindowManagerConfig().setLargeScreen().setUpConfig();
+ mPositioner.update();
+
+ RectF allowableStackRegion =
+ mPositioner.getAllowableStackPositionRegion(1 /* bubbleCount */);
+ PointF restingPosition = mPositioner.getRestingPosition();
+
+ assertThat(restingPosition.x).isEqualTo(allowableStackRegion.left);
+ assertThat(restingPosition.y).isEqualTo(getDefaultYPosition());
+ }
+
+ @Test
+ public void testGetRestingPosition_chatBubble_onTablet_RTL() {
+ new WindowManagerConfig().setLargeScreen().setLayoutDirection(
+ LAYOUT_DIRECTION_RTL).setUpConfig();
+ mPositioner.update();
+
+ RectF allowableStackRegion =
+ mPositioner.getAllowableStackPositionRegion(1 /* bubbleCount */);
+ PointF restingPosition = mPositioner.getRestingPosition();
+
+ assertThat(restingPosition.x).isEqualTo(allowableStackRegion.right);
+ assertThat(restingPosition.y).isEqualTo(getDefaultYPosition());
+ }
+
+ /**
+ * Calculates the Y position bubbles should be placed based on the config. Based on
+ * the calculations in {@link BubblePositioner#getDefaultStartPosition()} and
+ * {@link BubbleStackView.RelativeStackPosition}.
+ */
+ private float getDefaultYPosition() {
+ final boolean isTablet = mPositioner.isLargeScreen();
+
+ // On tablet the position is centered, on phone it is an offset from the top.
+ final float desiredY = isTablet
+ ? mPositioner.getScreenRect().height() / 2f - (mPositioner.getBubbleSize() / 2f)
+ : mContext.getResources().getDimensionPixelOffset(
+ R.dimen.bubble_stack_starting_offset_y);
+ // Since we're visually centering the bubbles on tablet, use total screen height rather
+ // than the available height.
+ final float height = isTablet
+ ? mPositioner.getScreenRect().height()
+ : mPositioner.getAvailableRect().height();
+ float offsetPercent = desiredY / height;
+ offsetPercent = Math.max(0f, Math.min(1f, offsetPercent));
+ final RectF allowableStackRegion =
+ mPositioner.getAllowableStackPositionRegion(1 /* bubbleCount */);
+ return allowableStackRegion.top + allowableStackRegion.height() * offsetPercent;
+ }
+
+ /**
+ * Sets up window manager to return config values based on what you need for the test.
+ * By default it sets up a portrait phone without any insets.
+ */
+ private class WindowManagerConfig {
+ private Rect mScreenBounds = new Rect(0, 0, 1000, 2000);
+ private boolean mIsLargeScreen = false;
+ private int mOrientation = ORIENTATION_PORTRAIT;
+ private int mLayoutDirection = LAYOUT_DIRECTION_LTR;
+ private Insets mInsets = Insets.of(0, 0, 0, 0);
+
+ public WindowManagerConfig setScreenBounds(Rect screenBounds) {
+ mScreenBounds = screenBounds;
+ return this;
+ }
+
+ public WindowManagerConfig setLargeScreen() {
+ mIsLargeScreen = true;
+ return this;
+ }
+
+ public WindowManagerConfig setOrientation(int orientation) {
+ mOrientation = orientation;
+ return this;
+ }
+
+ public WindowManagerConfig setLayoutDirection(int layoutDirection) {
+ mLayoutDirection = layoutDirection;
+ return this;
+ }
+
+ public WindowManagerConfig setInsets(Insets insets) {
+ mInsets = insets;
+ return this;
+ }
+
+ public void setUpConfig() {
+ mConfiguration.smallestScreenWidthDp = mIsLargeScreen
+ ? MIN_WIDTH_FOR_TABLET
+ : MIN_WIDTH_FOR_TABLET - 1;
+ mConfiguration.orientation = mOrientation;
+
+ when(mConfiguration.getLayoutDirection()).thenReturn(mLayoutDirection);
+ WindowInsets windowInsets = mock(WindowInsets.class);
+ when(windowInsets.getInsetsIgnoringVisibility(anyInt())).thenReturn(mInsets);
+ when(mWindowMetrics.getWindowInsets()).thenReturn(windowInsets);
+ when(mWindowMetrics.getBounds()).thenReturn(mScreenBounds);
+ when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
+ }
+ }
+}
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index d59756d02348..a48cc19995c9 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -87,12 +87,6 @@ public abstract class LocationManagerInternal {
public abstract boolean isProvider(@Nullable String provider, @NonNull CallerIdentity identity);
/**
- * Should only be used by GNSS code.
- */
- // TODO: there is no reason for this to exist as part of any API. move all the logic into gnss
- public abstract void sendNiResponse(int notifId, int userResponse);
-
- /**
* Returns the GNSS provided time.
*
* @return LocationTime object that includes the current time, according to the GNSS location
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index fba4249260ef..ee2510ff9695 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -18,28 +18,14 @@ package com.android.internal.location;
import android.Manifest;
import android.annotation.RequiresPermission;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.INetInitiatedListener;
import android.location.LocationManager;
-import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.util.Log;
-import com.android.internal.R;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.telephony.GsmAlphabet;
-
-import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
/**
@@ -53,95 +39,20 @@ public class GpsNetInitiatedHandler {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- // string constants for defining data fields in NI Intent
- public static final String NI_INTENT_KEY_NOTIF_ID = "notif_id";
- public static final String NI_INTENT_KEY_TITLE = "title";
- public static final String NI_INTENT_KEY_MESSAGE = "message";
- public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
- public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";
-
- // the extra command to send NI response to GnssLocationProvider
- public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";
-
- // the extra command parameter names in the Bundle
- public static final String NI_EXTRA_CMD_NOTIF_ID = "notif_id";
- public static final String NI_EXTRA_CMD_RESPONSE = "response";
-
- // these need to match GpsNiType constants in gps_ni.h
- public static final int GPS_NI_TYPE_VOICE = 1;
- public static final int GPS_NI_TYPE_UMTS_SUPL = 2;
- public static final int GPS_NI_TYPE_UMTS_CTRL_PLANE = 3;
- public static final int GPS_NI_TYPE_EMERGENCY_SUPL = 4;
-
- // these need to match GpsUserResponseType constants in gps_ni.h
- public static final int GPS_NI_RESPONSE_ACCEPT = 1;
- public static final int GPS_NI_RESPONSE_DENY = 2;
- public static final int GPS_NI_RESPONSE_NORESP = 3;
- public static final int GPS_NI_RESPONSE_IGNORE = 4;
-
- // these need to match GpsNiNotifyFlags constants in gps_ni.h
- public static final int GPS_NI_NEED_NOTIFY = 0x0001;
- public static final int GPS_NI_NEED_VERIFY = 0x0002;
- public static final int GPS_NI_PRIVACY_OVERRIDE = 0x0004;
-
- // these need to match GpsNiEncodingType in gps_ni.h
- public static final int GPS_ENC_NONE = 0;
- public static final int GPS_ENC_SUPL_GSM_DEFAULT = 1;
- public static final int GPS_ENC_SUPL_UTF8 = 2;
- public static final int GPS_ENC_SUPL_UCS2 = 3;
- public static final int GPS_ENC_UNKNOWN = -1;
-
private final Context mContext;
private final TelephonyManager mTelephonyManager;
// parent gps location provider
private final LocationManager mLocationManager;
- // configuration of notificaiton behavior
- private boolean mPlaySounds = false;
- private boolean mPopupImmediately = true;
-
- // read the SUPL_ES form gps.conf
- private volatile boolean mIsSuplEsEnabled;
-
// Set to true if the phone is having emergency call.
private volatile boolean mIsInEmergencyCall;
- // If Location function is enabled.
- private volatile boolean mIsLocationEnabled = false;
-
- private final INetInitiatedListener mNetInitiatedListener;
-
- // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
- @UnsupportedAppUsage
- static private boolean mIsHexInput = true;
// End time of emergency call, and extension, if set
private volatile long mCallEndElapsedRealtimeMillis = 0;
private volatile long mEmergencyExtensionMillis = 0;
- public static class GpsNiNotification
- {
- @android.compat.annotation.UnsupportedAppUsage
- public GpsNiNotification() {
- }
- public int notificationId;
- public int niType;
- public boolean needNotify;
- public boolean needVerify;
- public boolean privacyOverride;
- public int timeout;
- public int defaultResponse;
- @UnsupportedAppUsage
- public String requestorId;
- @UnsupportedAppUsage
- public String text;
- @UnsupportedAppUsage
- public int requestorIdEncoding;
- @UnsupportedAppUsage
- public int textEncoding;
- }
-
/** Callbacks for Emergency call events. */
public interface EmergencyCallCallback {
/** Callback invoked when an emergency call starts */
@@ -182,72 +93,20 @@ public class GpsNetInitiatedHandler {
// reference here.
private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
- /**
- * The notification that is shown when a network-initiated notification
- * (and verification) event is received.
- * <p>
- * This is lazily created, so use {@link #setNINotification()}.
- */
- private Notification.Builder mNiNotificationBuilder;
-
private final EmergencyCallCallback mEmergencyCallCallback;
public GpsNetInitiatedHandler(Context context,
- INetInitiatedListener netInitiatedListener,
EmergencyCallCallback emergencyCallCallback,
boolean isSuplEsEnabled) {
mContext = context;
-
- if (netInitiatedListener == null) {
- throw new IllegalArgumentException("netInitiatedListener is null");
- } else {
- mNetInitiatedListener = netInitiatedListener;
- }
mEmergencyCallCallback = emergencyCallCallback;
- setSuplEsEnabled(isSuplEsEnabled);
mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
- updateLocationMode();
mTelephonyManager =
(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
mEmergencyCallListener);
- BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
- updateLocationMode();
- if (DEBUG) Log.d(TAG, "location enabled :" + getLocationEnabled());
- }
- }
- };
- mContext.registerReceiver(broadcastReceiver,
- new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
- }
-
- public void setSuplEsEnabled(boolean isEnabled) {
- mIsSuplEsEnabled = isEnabled;
- }
-
- public boolean getSuplEsEnabled() {
- return mIsSuplEsEnabled;
- }
-
- /**
- * Updates Location enabler based on location setting.
- */
- public void updateLocationMode() {
- mIsLocationEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
- }
-
- /**
- * Checks if user agreed to use location.
- */
- public boolean getLocationEnabled() {
- return mIsLocationEnabled;
}
/**
@@ -289,346 +148,4 @@ public class GpsNetInitiatedHandler {
public void setEmergencyExtensionSeconds(int emergencyExtensionSeconds) {
mEmergencyExtensionMillis = TimeUnit.SECONDS.toMillis(emergencyExtensionSeconds);
}
-
- // Handles NI events from HAL
- @UnsupportedAppUsage
- public void handleNiNotification(GpsNiNotification notif) {
- if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
- + " notificationId: " + notif.notificationId
- + " requestorId: " + notif.requestorId
- + " text: " + notif.text
- + " mIsSuplEsEnabled" + getSuplEsEnabled()
- + " mIsLocationEnabled" + getLocationEnabled());
-
- if (getSuplEsEnabled()) {
- handleNiInEs(notif);
- } else {
- handleNi(notif);
- }
-
- //////////////////////////////////////////////////////////////////////////
- // A note about timeout
- // According to the protocol, in the need_notify and need_verify case,
- // a default response should be sent when time out.
- //
- // In some GPS hardware, the GPS driver (under HAL) can handle the timeout case
- // and this class GpsNetInitiatedHandler does not need to do anything.
- //
- // However, the UI should at least close the dialog when timeout. Further,
- // for more general handling, timeout response should be added to the Handler here.
- //
- }
-
- // handle NI form HAL when SUPL_ES is disabled.
- private void handleNi(GpsNiNotification notif) {
- if (DEBUG) Log.d(TAG, "in handleNi () :"
- + " needNotify: " + notif.needNotify
- + " needVerify: " + notif.needVerify
- + " privacyOverride: " + notif.privacyOverride
- + " mPopupImmediately: " + mPopupImmediately
- + " mInEmergency: " + getInEmergency());
-
- if (!getLocationEnabled() && !getInEmergency()) {
- // Location is currently disabled, ignore all NI requests.
- try {
- mNetInitiatedListener.sendNiResponse(notif.notificationId,
- GPS_NI_RESPONSE_IGNORE);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in sendNiResponse");
- }
- }
- if (notif.needNotify) {
- // If NI does not need verify or the dialog is not requested
- // to pop up immediately, the dialog box will not pop up.
- if (notif.needVerify && mPopupImmediately) {
- // Popup the dialog box now
- openNiDialog(notif);
- } else {
- // Show the notification
- setNiNotification(notif);
- }
- }
- // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify;
- // 3. privacy override.
- if (!notif.needVerify || notif.privacyOverride) {
- try {
- mNetInitiatedListener.sendNiResponse(notif.notificationId,
- GPS_NI_RESPONSE_ACCEPT);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in sendNiResponse");
- }
- }
- }
-
- // handle NI from HAL when the SUPL_ES is enabled
- private void handleNiInEs(GpsNiNotification notif) {
-
- if (DEBUG) Log.d(TAG, "in handleNiInEs () :"
- + " niType: " + notif.niType
- + " notificationId: " + notif.notificationId);
-
- // UE is in emergency mode when in emergency call mode or in emergency call back mode
- /*
- 1. When SUPL ES bit is off and UE is not in emergency mode:
- Call handleNi() to do legacy behaviour.
- 2. When SUPL ES bit is on and UE is in emergency mode:
- Call handleNi() to do acceptance behaviour.
- 3. When SUPL ES bit is off but UE is in emergency mode:
- Ignore the emergency SUPL INIT.
- 4. When SUPL ES bit is on but UE is not in emergency mode:
- Ignore the emergency SUPL INIT.
- */
- boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
- if (isNiTypeES != getInEmergency()) {
- try {
- mNetInitiatedListener.sendNiResponse(notif.notificationId,
- GPS_NI_RESPONSE_IGNORE);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in sendNiResponse");
- }
- } else {
- handleNi(notif);
- }
- }
-
- /**
- * Posts a notification in the status bar using the contents in {@code notif} object.
- */
- private synchronized void setNiNotification(GpsNiNotification notif) {
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager == null) {
- return;
- }
-
- String title = getNotifTitle(notif, mContext);
- String message = getNotifMessage(notif, mContext);
-
- if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
- ", title: " + title +
- ", message: " + message);
-
- // Construct Notification
- if (mNiNotificationBuilder == null) {
- mNiNotificationBuilder = new Notification.Builder(mContext,
- SystemNotificationChannels.NETWORK_ALERTS)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
- .setWhen(0)
- .setOngoing(true)
- .setAutoCancel(true)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- }
-
- if (mPlaySounds) {
- mNiNotificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
- } else {
- mNiNotificationBuilder.setDefaults(0);
- }
-
- mNiNotificationBuilder.setTicker(getNotifTicker(notif, mContext))
- .setContentTitle(title)
- .setContentText(message);
-
- notificationManager.notifyAsUser(null, notif.notificationId, mNiNotificationBuilder.build(),
- UserHandle.ALL);
- }
-
- // Opens the notification dialog and waits for user input
- private void openNiDialog(GpsNiNotification notif)
- {
- Intent intent = getDlgIntent(notif);
-
- if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId +
- ", requestorId: " + notif.requestorId +
- ", text: " + notif.text);
-
- mContext.startActivity(intent);
- }
-
- // Construct the intent for bringing up the dialog activity, which shows the
- // notification and takes user input
- private Intent getDlgIntent(GpsNiNotification notif)
- {
- Intent intent = new Intent();
- String title = getDialogTitle(notif, mContext);
- String message = getDialogMessage(notif, mContext);
-
- // directly bring up the NI activity
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class);
-
- // put data in the intent
- intent.putExtra(NI_INTENT_KEY_NOTIF_ID, notif.notificationId);
- intent.putExtra(NI_INTENT_KEY_TITLE, title);
- intent.putExtra(NI_INTENT_KEY_MESSAGE, message);
- intent.putExtra(NI_INTENT_KEY_TIMEOUT, notif.timeout);
- intent.putExtra(NI_INTENT_KEY_DEFAULT_RESPONSE, notif.defaultResponse);
-
- if (DEBUG) Log.d(TAG, "generateIntent, title: " + title + ", message: " + message +
- ", timeout: " + notif.timeout);
-
- return intent;
- }
-
- // Converts a string (or Hex string) to a char array
- static byte[] stringToByteArray(String original, boolean isHex)
- {
- int length = isHex ? original.length() / 2 : original.length();
- byte[] output = new byte[length];
- int i;
-
- if (isHex)
- {
- for (i = 0; i < length; i++)
- {
- output[i] = (byte) Integer.parseInt(original.substring(i*2, i*2+2), 16);
- }
- }
- else {
- for (i = 0; i < length; i++)
- {
- output[i] = (byte) original.charAt(i);
- }
- }
-
- return output;
- }
-
- /**
- * Unpacks an byte array containing 7-bit packed characters into a String.
- *
- * @param input a 7-bit packed char array
- * @return the unpacked String
- */
- static String decodeGSMPackedString(byte[] input)
- {
- final char PADDING_CHAR = 0x00;
- int lengthBytes = input.length;
- int lengthSeptets = (lengthBytes * 8) / 7;
- String decoded;
-
- /* Special case where the last 7 bits in the last byte could hold a valid
- * 7-bit character or a padding character. Drop the last 7-bit character
- * if it is a padding character.
- */
- if (lengthBytes % 7 == 0) {
- if (lengthBytes > 0) {
- if ((input[lengthBytes - 1] >> 1) == PADDING_CHAR) {
- lengthSeptets = lengthSeptets - 1;
- }
- }
- }
-
- decoded = GsmAlphabet.gsm7BitPackedToString(input, 0, lengthSeptets);
-
- // Return "" if decoding of GSM packed string fails
- if (null == decoded) {
- Log.e(TAG, "Decoding of GSM packed string failed");
- decoded = "";
- }
-
- return decoded;
- }
-
- static String decodeUTF8String(byte[] input)
- {
- String decoded = "";
- try {
- decoded = new String(input, "UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- throw new AssertionError();
- }
- return decoded;
- }
-
- static String decodeUCS2String(byte[] input)
- {
- String decoded = "";
- try {
- decoded = new String(input, "UTF-16");
- }
- catch (UnsupportedEncodingException e)
- {
- throw new AssertionError();
- }
- return decoded;
- }
-
- /** Decode NI string
- *
- * @param original The text string to be decoded
- * @param isHex Specifies whether the content of the string has been encoded as a Hex string. Encoding
- * a string as Hex can allow zeros inside the coded text.
- * @param coding Specifies the coding scheme of the string, such as GSM, UTF8, UCS2, etc. This coding scheme
- * needs to match those used passed to HAL from the native GPS driver. Decoding is done according
- * to the <code> coding </code>, after a Hex string is decoded. Generally, if the
- * notification strings don't need further decoding, <code> coding </code> encoding can be
- * set to -1, and <code> isHex </code> can be false.
- * @return the decoded string
- */
- @UnsupportedAppUsage
- static private String decodeString(String original, boolean isHex, int coding)
- {
- if (coding == GPS_ENC_NONE || coding == GPS_ENC_UNKNOWN) {
- return original;
- }
-
- byte[] input = stringToByteArray(original, isHex);
-
- switch (coding) {
- case GPS_ENC_SUPL_GSM_DEFAULT:
- return decodeGSMPackedString(input);
-
- case GPS_ENC_SUPL_UTF8:
- return decodeUTF8String(input);
-
- case GPS_ENC_SUPL_UCS2:
- return decodeUCS2String(input);
-
- default:
- Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original);
- return original;
- }
- }
-
- // change this to configure notification display
- static private String getNotifTicker(GpsNiNotification notif, Context context)
- {
- String ticker = String.format(context.getString(R.string.gpsNotifTicker),
- decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
- decodeString(notif.text, mIsHexInput, notif.textEncoding));
- return ticker;
- }
-
- // change this to configure notification display
- static private String getNotifTitle(GpsNiNotification notif, Context context)
- {
- String title = String.format(context.getString(R.string.gpsNotifTitle));
- return title;
- }
-
- // change this to configure notification display
- static private String getNotifMessage(GpsNiNotification notif, Context context)
- {
- String message = String.format(context.getString(R.string.gpsNotifMessage),
- decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
- decodeString(notif.text, mIsHexInput, notif.textEncoding));
- return message;
- }
-
- // change this to configure dialog display (for verification)
- static public String getDialogTitle(GpsNiNotification notif, Context context)
- {
- return getNotifTitle(notif, context);
- }
-
- // change this to configure dialog display (for verification)
- static private String getDialogMessage(GpsNiNotification notif, Context context)
- {
- return getNotifMessage(notif, context);
- }
-
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 2d6cc699fc11..df91d98b8360 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -806,12 +806,12 @@ public class PackageInstallerActivity extends AlertActivity {
}
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (!isDestroyed()) {
+ startActivity(getIntent());
// The start flag (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP) doesn't
// work for the multiple user case, i.e. the caller task user and started
// Activity user are not the same. To avoid having multiple PIAs in the task,
// finish the current PackageInstallerActivity
finish();
- startActivity(getIntent());
}
}, 500);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 58c9f777de33..6778d5a08506 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -562,7 +562,7 @@
android:exported="true"
android:launchMode="singleTop"
android:permission="android.permission.MANAGE_SENSOR_PRIVACY"
- android:theme="@style/Theme.SystemUI.Dialog.Alert"
+ android:theme="@style/Theme.SystemUI.Dialog.Alert.SensorPrivacy"
android:finishOnCloseSystemDialogs="true"
android:showForAllUsers="true">
</activity>
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 3dfdbbaaee77..f91baf298347 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -77,7 +77,7 @@ fun SceneContainer(
SceneTransitionLayout(
currentScene = currentSceneKey.toTransitionSceneKey(),
- onChangeScene = { sceneKey -> viewModel.setCurrentScene(sceneKey.toModel()) },
+ onChangeScene = viewModel::onSceneChanged,
transitions = transitions {},
state = state,
modifier = modifier.fillMaxSize(),
@@ -154,3 +154,7 @@ private fun UserAction.toTransitionUserAction(): SceneTransitionUserAction {
is UserAction.Back -> Back
}
}
+
+private fun SceneContainerViewModel.onSceneChanged(sceneKey: SceneTransitionSceneKey) {
+ onSceneChanged(sceneKey.toModel())
+}
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 66c57fc2a9ac..36f7b96a267c 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -22,42 +22,6 @@
android:layout_width="match_parent"
android:outlineProvider="none" >
- <LinearLayout
- android:id="@id/keyguard_indication_area"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
- android:layout_gravity="bottom|center_horizontal"
- android:orientation="vertical">
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@id/keyguard_indication_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:accessibilityLiveRegion="polite"/>
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@id/keyguard_indication_text_bottom"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:minHeight="@dimen/keyguard_indication_text_min_height"
- android:layout_gravity="center_horizontal"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:maxLines="2"
- android:ellipsize="end"
- android:alpha=".8"
- android:accessibilityLiveRegion="polite"
- android:visibility="gone"/>
-
- </LinearLayout>
-
<com.android.systemui.animation.view.LaunchableImageView
android:id="@+id/start_button"
android:layout_height="@dimen/keyguard_affordance_fixed_height"
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 763930db1d55..c2dba6c41d12 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -38,4 +38,6 @@
protected. -->
<bool name="flag_battery_shield_icon">false</bool>
+ <!-- Whether face auth will immediately stop when the display state is OFF -->
+ <bool name="flag_stop_face_auth_on_display_off">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d520670ec012..10340c6847f7 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -451,6 +451,11 @@
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
+ <style name="Theme.SystemUI.Dialog.Alert.SensorPrivacy" parent="Theme.SystemUI.Dialog.Alert">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ </style>
+
<style name="Theme.SystemUI.Dialog.GlobalActions" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
<item name="android:colorError">@*android:color/error_color_material_dark</item>
<item name="android:windowIsFloating">true</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index 22cdb30376d0..2abb7a41ef08 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -33,6 +33,7 @@ import com.android.keyguard.InternalFaceAuthReasons.AUTH_REQUEST_DURING_CANCELLA
import com.android.keyguard.InternalFaceAuthReasons.BIOMETRIC_ENABLED
import com.android.keyguard.InternalFaceAuthReasons.CAMERA_LAUNCHED
import com.android.keyguard.InternalFaceAuthReasons.DEVICE_WOKEN_UP_ON_REACH_GESTURE
+import com.android.keyguard.InternalFaceAuthReasons.DISPLAY_OFF
import com.android.keyguard.InternalFaceAuthReasons.DREAM_STARTED
import com.android.keyguard.InternalFaceAuthReasons.DREAM_STOPPED
import com.android.keyguard.InternalFaceAuthReasons.ENROLLMENTS_CHANGED
@@ -131,6 +132,7 @@ private object InternalFaceAuthReasons {
const val NON_STRONG_BIOMETRIC_ALLOWED_CHANGED =
"Face auth stopped because non strong biometric allowed changed"
const val POSTURE_CHANGED = "Face auth started/stopped due to device posture changed."
+ const val DISPLAY_OFF = "Face auth stopped due to display state OFF."
}
/**
@@ -221,7 +223,8 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) :
FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED(1255, STRONG_AUTH_ALLOWED_CHANGED),
@UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED)
FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED),
- @UiEvent(doc = ACCESSIBILITY_ACTION) FACE_AUTH_ACCESSIBILITY_ACTION(1454, ACCESSIBILITY_ACTION);
+ @UiEvent(doc = ACCESSIBILITY_ACTION) FACE_AUTH_ACCESSIBILITY_ACTION(1454, ACCESSIBILITY_ACTION),
+ @UiEvent(doc = DISPLAY_OFF) FACE_AUTH_DISPLAY_OFF(1461, DISPLAY_OFF);
override fun getId(): Int = this.id
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index 461d390fd477..bb799fc55171 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -27,6 +27,7 @@ data class KeyguardFaceListenModel(
override var userId: Int = 0,
override var listening: Boolean = false,
// keep sorted
+ var allowedDisplayState: Boolean = false,
var alternateBouncerShowing: Boolean = false,
var authInterruptActive: Boolean = false,
var biometricSettingEnabledForUser: Boolean = false,
@@ -57,6 +58,8 @@ data class KeyguardFaceListenModel(
userId.toString(),
listening.toString(),
// keep sorted
+ allowedDisplayState.toString(),
+ alternateBouncerShowing.toString(),
authInterruptActive.toString(),
biometricSettingEnabledForUser.toString(),
bouncerFullyShown.toString(),
@@ -74,7 +77,6 @@ data class KeyguardFaceListenModel(
supportsDetect.toString(),
switchingUser.toString(),
systemUser.toString(),
- alternateBouncerShowing.toString(),
udfpsFingerDown.toString(),
userNotTrustedOrDetectionIsNeeded.toString(),
)
@@ -96,7 +98,9 @@ data class KeyguardFaceListenModel(
userId = model.userId
listening = model.listening
// keep sorted
+ allowedDisplayState = model.allowedDisplayState
alternateBouncerShowing = model.alternateBouncerShowing
+ authInterruptActive = model.authInterruptActive
biometricSettingEnabledForUser = model.biometricSettingEnabledForUser
bouncerFullyShown = model.bouncerFullyShown
faceAndFpNotAuthenticated = model.faceAndFpNotAuthenticated
@@ -105,7 +109,6 @@ data class KeyguardFaceListenModel(
faceLockedOut = model.faceLockedOut
goingToSleep = model.goingToSleep
keyguardAwake = model.keyguardAwake
- goingToSleep = model.goingToSleep
keyguardGoingAway = model.keyguardGoingAway
listeningForFaceAssistant = model.listeningForFaceAssistant
occludingAppRequestingFaceAuth = model.occludingAppRequestingFaceAuth
@@ -140,6 +143,8 @@ data class KeyguardFaceListenModel(
"userId",
"listening",
// keep sorted
+ "allowedDisplayState",
+ "alternateBouncerShowing",
"authInterruptActive",
"biometricSettingEnabledForUser",
"bouncerFullyShown",
@@ -157,7 +162,6 @@ data class KeyguardFaceListenModel(
"supportsDetect",
"switchingUser",
"systemUser",
- "udfpsBouncerShowing",
"udfpsFingerDown",
"userNotTrustedOrDetectionIsNeeded",
)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index aff25914ec36..57a859126db2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -476,18 +476,16 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
// When the scene framework transitions from bouncer to gone, we dismiss the keyguard.
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
- mSceneInteractor.get().getTransitions(),
- sceneTransitionModel -> {
- if (sceneTransitionModel != null
- && sceneTransitionModel.getFrom() == SceneKey.Bouncer.INSTANCE
- && sceneTransitionModel.getTo() == SceneKey.Gone.INSTANCE) {
- final int selectedUserId = mUserInteractor.getSelectedUserId();
- showNextSecurityScreenOrFinish(
- /* authenticated= */ true,
- selectedUserId,
- /* bypassSecondaryLockScreen= */ true,
- mSecurityModel.getSecurityMode(selectedUserId));
- }
+ mSceneInteractor.get().finishedSceneTransitions(
+ /* from= */ SceneKey.Bouncer.INSTANCE,
+ /* to= */ SceneKey.Gone.INSTANCE),
+ unused -> {
+ final int selectedUserId = mUserInteractor.getSelectedUserId();
+ showNextSecurityScreenOrFinish(
+ /* authenticated= */ true,
+ selectedUserId,
+ /* bypassSecondaryLockScreen= */ true,
+ mSecurityModel.getSecurityMode(selectedUserId));
});
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c03053d0a8a2..853a62a09f83 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -41,6 +41,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthReasonKt.apiRequestReasonToUiEvent;
+import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_DISPLAY_OFF;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_DREAM_STARTED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FACE_CANCEL_NOT_RECEIVED;
@@ -135,6 +136,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.view.Display;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -175,6 +177,7 @@ import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -335,6 +338,25 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
};
+ private final DisplayTracker.Callback mDisplayCallback = new DisplayTracker.Callback() {
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ return;
+ }
+
+ if (mDisplayTracker.getDisplay(mDisplayTracker.getDefaultDisplayId()).getState()
+ == Display.STATE_OFF) {
+ mAllowedDisplayStateForFaceAuth = false;
+ updateFaceListeningState(
+ BIOMETRIC_ACTION_STOP,
+ FACE_AUTH_DISPLAY_OFF
+ );
+ } else {
+ mAllowedDisplayStateForFaceAuth = true;
+ }
+ }
+ };
private final FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig;
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
@@ -355,6 +377,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private boolean mOccludingAppRequestingFp;
private boolean mOccludingAppRequestingFace;
private boolean mSecureCameraLaunched;
+ private boolean mAllowedDisplayStateForFaceAuth = true;
@VisibleForTesting
protected boolean mTelephonyCapable;
private boolean mAllowFingerprintOnCurrentOccludingActivity;
@@ -403,6 +426,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private KeyguardFaceAuthInteractor mFaceAuthInteractor;
private final TaskStackChangeListeners mTaskStackChangeListeners;
private final IActivityTaskManager mActivityTaskManager;
+ private final DisplayTracker mDisplayTracker;
private final LockPatternUtils mLockPatternUtils;
@VisibleForTesting
@DevicePostureInt
@@ -2187,6 +2211,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
Assert.isMainThread();
+ mAllowedDisplayStateForFaceAuth = true;
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
if (mFaceWakeUpTriggersConfig.shouldTriggerFaceAuthOnWakeUpFrom(pmWakeReason)) {
FACE_AUTH_UPDATED_STARTED_WAKING_UP.setExtraInfo(pmWakeReason);
@@ -2342,7 +2367,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Optional<FingerprintInteractiveToAuthProvider> interactiveToAuthProvider,
FeatureFlags featureFlags,
TaskStackChangeListeners taskStackChangeListeners,
- IActivityTaskManager activityTaskManagerService) {
+ IActivityTaskManager activityTaskManagerService,
+ DisplayTracker displayTracker) {
mContext = context;
mSubscriptionManager = subscriptionManager;
mUserTracker = userTracker;
@@ -2390,6 +2416,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
.collect(Collectors.toSet());
mTaskStackChangeListeners = taskStackChangeListeners;
mActivityTaskManager = activityTaskManagerService;
+ mDisplayTracker = displayTracker;
+ if (mFeatureFlags.isEnabled(Flags.STOP_FACE_AUTH_ON_DISPLAY_OFF)) {
+ mDisplayTracker.addDisplayChangeCallback(mDisplayCallback, mainExecutor);
+ }
mHandler = new Handler(mainLooper) {
@Override
@@ -3199,7 +3229,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& (!mSecureCameraLaunched || mAlternateBouncerShowing)
&& faceAndFpNotAuthenticated
&& !mGoingToSleep
- && isPostureAllowedForFaceAuth;
+ && isPostureAllowedForFaceAuth
+ && mAllowedDisplayStateForFaceAuth;
// Aggregate relevant fields for debug logging.
logListenerModelData(
@@ -3207,6 +3238,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
System.currentTimeMillis(),
user,
shouldListen,
+ mAllowedDisplayStateForFaceAuth,
mAlternateBouncerShowing,
mAuthInterruptActive,
biometricEnabledForUser,
@@ -4400,6 +4432,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLockPatternUtils.unregisterStrongAuthTracker(mStrongAuthTracker);
mTrustManager.unregisterTrustListener(this);
+ mDisplayTracker.removeCallback(mDisplayCallback);
mHandler.removeCallbacksAndMessages(null);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 4845a6173be9..951a6aeef11b 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -25,6 +25,7 @@ import static com.android.keyguard.LockIconView.ICON_UNLOCK;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
+import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.content.res.Configuration;
@@ -39,6 +40,7 @@ import android.os.VibrationAttributes;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.MathUtils;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -613,12 +615,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_HOVER_ENTER:
if (!mDownDetected && mAccessibilityManager.isTouchExplorationEnabled()) {
- mVibrator.vibrate(
- Process.myUid(),
- getContext().getOpPackageName(),
- UdfpsController.EFFECT_CLICK,
- "lock-icon-down",
- TOUCH_VIBRATION_ATTRIBUTES);
+ vibrateOnTouchExploration();
}
// The pointer that causes ACTION_DOWN is always at index 0.
@@ -699,13 +696,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
mOnGestureDetectedRunnable.run();
}
- // play device entry haptic (same as biometric success haptic)
- mVibrator.vibrate(
- Process.myUid(),
- getContext().getOpPackageName(),
- UdfpsController.EFFECT_CLICK,
- "lock-screen-lock-icon-longpress",
- TOUCH_VIBRATION_ATTRIBUTES);
+ // play device entry haptic (consistent with UDFPS controller longpress)
+ vibrateOnLongPress();
mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
}
@@ -753,6 +745,37 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
});
}
+ @VisibleForTesting
+ void vibrateOnTouchExploration() {
+ if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
+ mVibrator.performHapticFeedback(
+ mView,
+ HapticFeedbackConstants.CONTEXT_CLICK
+ );
+ } else {
+ mVibrator.vibrate(
+ Process.myUid(),
+ getContext().getOpPackageName(),
+ UdfpsController.EFFECT_CLICK,
+ "lock-icon-down",
+ TOUCH_VIBRATION_ATTRIBUTES);
+ }
+ }
+
+ @VisibleForTesting
+ void vibrateOnLongPress() {
+ if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
+ mVibrator.performHapticFeedback(mView, UdfpsController.LONG_PRESS);
+ } else {
+ mVibrator.vibrate(
+ Process.myUid(),
+ getContext().getOpPackageName(),
+ UdfpsController.EFFECT_CLICK,
+ "lock-screen-lock-icon-longpress",
+ TOUCH_VIBRATION_ATTRIBUTES);
+ }
+ }
+
private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
@Override
public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index ffcae1cacb00..1bf3a9ead08e 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -116,12 +116,12 @@ constructor(
repository.setMessage(
message ?: promptMessage(authenticationInteractor.getAuthenticationMethod())
)
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Bouncer),
loggingReason = "request to unlock device while authentication required",
)
} else {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Gone),
loggingReason = "request to unlock device while authentication isn't required",
)
@@ -169,7 +169,7 @@ constructor(
authenticationInteractor.authenticate(input, tryAutoConfirm) ?: return null
if (isAuthenticated) {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(SceneKey.Gone),
loggingReason = "successful authentication",
)
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index a30a3e1f855c..6037bbd837f0 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -244,10 +244,6 @@ object Flags {
/** Keyguard Migration */
- /** Migrate the indication area to the new keyguard root view. */
- // TODO(b/280067944): Tracking bug.
- @JvmField val MIGRATE_INDICATION_AREA = releasedFlag(236, "migrate_indication_area")
-
/**
* Migrate the bottom area to the new keyguard root view. Because there is no such thing as a
* "bottom area" after this, this also breaks it up into many smaller, modular pieces.
@@ -294,6 +290,11 @@ object Flags {
teamfood = true
)
+ /** Stop running face auth when the display state changes to OFF. */
+ // TODO(b/294221702): Tracking bug.
+ @JvmField val STOP_FACE_AUTH_ON_DISPLAY_OFF = resourceBooleanFlag(245,
+ R.bool.flag_stop_face_auth_on_display_off, "stop_face_auth_on_display_off")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -374,6 +375,9 @@ object Flags {
@JvmField val INCOMPATIBLE_CHARGING_BATTERY_ICON =
unreleasedFlag(614, "incompatible_charging_battery_icon")
+ // TODO(b/293585143): Tracking Bug
+ val INSTANT_TETHER = unreleasedFlag(615, "instant_tether")
+
// 700 - dialer/calls
// TODO(b/254512734): Tracking Bug
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index dffc19d566ff..2b6f77d280f8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -137,14 +137,6 @@ constructor(
fun bindIndicationArea() {
indicationAreaHandle?.dispose()
- // At startup, 2 views with the ID `R.id.keyguard_indication_area` will be available.
- // Disable one of them
- if (!featureFlags.isEnabled(Flags.MIGRATE_INDICATION_AREA)) {
- keyguardRootView.findViewById<View?>(R.id.keyguard_indication_area)?.let {
- keyguardRootView.removeView(it)
- }
- }
-
indicationAreaHandle =
KeyguardIndicationAreaBinder.bind(
notificationShadeWindowView,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index fee3960ff0e1..350fa38f2052 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -18,50 +18,49 @@
package com.android.systemui.scene.data.repository
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.stateIn
/** Source of truth for scene framework application state. */
class SceneContainerRepository
@Inject
constructor(
+ @Application applicationScope: CoroutineScope,
private val config: SceneContainerConfig,
) {
+ private val _desiredScene = MutableStateFlow(SceneModel(config.initialSceneKey))
+ val desiredScene: StateFlow<SceneModel> = _desiredScene.asStateFlow()
private val _isVisible = MutableStateFlow(true)
val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
- private val _currentScene = MutableStateFlow(SceneModel(config.initialSceneKey))
- val currentScene: StateFlow<SceneModel> = _currentScene.asStateFlow()
-
- private val transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
- val transitionProgress: Flow<Float> =
- transitionState.flatMapLatest { observableTransitionStateFlow ->
- observableTransitionStateFlow?.flatMapLatest { observableTransitionState ->
- when (observableTransitionState) {
- is ObservableTransitionState.Idle -> flowOf(1f)
- is ObservableTransitionState.Transition -> observableTransitionState.progress
- }
- }
- ?: flowOf(1f)
- }
-
- private val _transitions = MutableStateFlow<SceneTransitionModel?>(null)
- val transitions: StateFlow<SceneTransitionModel?> = _transitions.asStateFlow()
+ private val defaultTransitionState = ObservableTransitionState.Idle(config.initialSceneKey)
+ private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
+ val transitionState: StateFlow<ObservableTransitionState> =
+ _transitionState
+ .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = defaultTransitionState,
+ )
/**
- * Returns the keys to all scenes in the container with the given name.
+ * Returns the keys to all scenes in the container.
*
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
@@ -70,40 +69,19 @@ constructor(
return config.sceneKeys
}
- /** Sets the current scene in the container with the given name. */
- fun setCurrentScene(scene: SceneModel) {
+ fun setDesiredScene(scene: SceneModel) {
check(allSceneKeys().contains(scene.key)) {
"""
- Cannot set current scene key to "${scene.key}". The configuration does not contain a
- scene with that key.
- """
- .trimIndent()
- }
-
- _currentScene.value = scene
- }
-
- /** Sets the scene transition in the container with the given name. */
- fun setSceneTransition(from: SceneKey, to: SceneKey) {
- check(allSceneKeys().contains(from)) {
- """
- Cannot set current scene key to "$from". The configuration does not contain a scene
- with that key.
- """
- .trimIndent()
- }
- check(allSceneKeys().contains(to)) {
- """
- Cannot set current scene key to "$to". The configuration does not contain a scene
- with that key.
+ Cannot set the desired scene key to "${scene.key}". The configuration does not
+ contain a scene with that key.
"""
.trimIndent()
}
- _transitions.value = SceneTransitionModel(from = from, to = to)
+ _desiredScene.value = scene
}
- /** Sets whether the container with the given name is visible. */
+ /** Sets whether the container is visible. */
fun setVisible(isVisible: Boolean) {
_isVisible.value = isVisible
}
@@ -114,6 +92,6 @@ constructor(
* Note that you must call is with `null` when the UI is done or risk a memory leak.
*/
fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
- this.transitionState.value = transitionState
+ _transitionState.value = transitionState
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 64715bc26674..cf7abdd34b70 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -23,12 +23,15 @@ import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.RemoteUserInput
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
+import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
/**
* Generic business logic and app state accessors for the scene framework.
@@ -46,7 +49,54 @@ constructor(
) {
/**
- * Returns the keys of all scenes in the container with the given name.
+ * The currently *desired* scene.
+ *
+ * **Important:** this value will _commonly be different_ from what is being rendered in the UI,
+ * by design.
+ *
+ * There are two intended sources for this value:
+ * 1. Programmatic requests to transition to another scene (calls to [changeScene]).
+ * 2. Reports from the UI about completing a transition to another scene (calls to
+ * [onSceneChanged]).
+ *
+ * Both the sources above cause the value of this flow to change; however, they cause mismatches
+ * in different ways.
+ *
+ * **Updates from programmatic transitions**
+ *
+ * When an external bit of code asks the framework to switch to another scene, the value here
+ * will update immediately. Downstream, the UI will detect this change and initiate the
+ * transition animation. As the transition animation progresses, a threshold will be reached, at
+ * which point the UI and the state here will match each other.
+ *
+ * **Updates from the UI**
+ *
+ * When the user interacts with the UI, the UI runs a transition animation that tracks the user
+ * pointer (for example, the user's finger). During this time, the state value here and what the
+ * UI shows will likely not match. Once/if a threshold is met, the UI reports it and commits the
+ * change, making the value here match the UI again.
+ */
+ val desiredScene: StateFlow<SceneModel> = repository.desiredScene
+
+ /**
+ * The current state of the transition.
+ *
+ * Consumers should use this state to know:
+ * 1. Whether there is an ongoing transition or if the system is at rest.
+ * 2. When transitioning, which scenes are being transitioned between.
+ * 3. When transitioning, what the progress of the transition is.
+ */
+ val transitionState: StateFlow<ObservableTransitionState> = repository.transitionState
+
+ /** Whether the scene container is visible. */
+ val isVisible: StateFlow<Boolean> = repository.isVisible
+
+ private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)
+ /** A flow of motion events originating from outside of the scene framework. */
+ val remoteUserInput: StateFlow<RemoteUserInput?> = _remoteUserInput.asStateFlow()
+
+ /**
+ * Returns the keys of all scenes in the container.
*
* The scenes will be sorted in z-order such that the last one is the one that should be
* rendered on top of all previous ones.
@@ -55,26 +105,20 @@ constructor(
return repository.allSceneKeys()
}
- /** Sets the scene in the container with the given name. */
- fun setCurrentScene(scene: SceneModel, loggingReason: String) {
- val currentSceneKey = repository.currentScene.value.key
- if (currentSceneKey == scene.key) {
- return
- }
-
- logger.logSceneChange(
- from = currentSceneKey,
- to = scene.key,
- reason = loggingReason,
- )
- repository.setCurrentScene(scene)
- repository.setSceneTransition(from = currentSceneKey, to = scene.key)
+ /**
+ * Requests a scene change to the given scene.
+ *
+ * The change is animated. Therefore, while the value in [desiredScene] will update immediately,
+ * it will be some time before the UI will switch to the desired scene. The scene change
+ * requested is remembered here but served by the UI layer, which will start a transition
+ * animation. Once enough of the transition has occurred, the system will come into agreement
+ * between the [desiredScene] and the UI.
+ */
+ fun changeScene(scene: SceneModel, loggingReason: String) {
+ updateDesiredScene(scene, loggingReason, logger::logSceneChangeRequested)
}
- /** The current scene in the container with the given name. */
- val currentScene: StateFlow<SceneModel> = repository.currentScene
-
- /** Sets the visibility of the container with the given name. */
+ /** Sets the visibility of the container. */
fun setVisible(isVisible: Boolean, loggingReason: String) {
val wasVisible = repository.isVisible.value
if (wasVisible == isVisible) {
@@ -89,9 +133,6 @@ constructor(
return repository.setVisible(isVisible)
}
- /** Whether the container with the given name is visible. */
- val isVisible: StateFlow<Boolean> = repository.isVisible
-
/**
* Binds the given flow so the system remembers it.
*
@@ -101,23 +142,53 @@ constructor(
repository.setTransitionState(transitionState)
}
- /** Progress of the transition into the current scene in the container with the given name. */
- val transitionProgress: Flow<Float> = repository.transitionProgress
-
/**
- * Scene transitions as pairs of keys. A new value is emitted exactly once, each time a scene
- * transition occurs. The flow begins with a `null` value at first, because the initial scene is
- * not something that we transition to from another scene.
+ * Returns a stream of events that emits one [Unit] every time the framework transitions from
+ * [from] to [to].
*/
- val transitions: StateFlow<SceneTransitionModel?> = repository.transitions
-
- private val _remoteUserInput: MutableStateFlow<RemoteUserInput?> = MutableStateFlow(null)
-
- /** A flow of motion events originating from outside of the scene framework. */
- val remoteUserInput: StateFlow<RemoteUserInput?> = _remoteUserInput.asStateFlow()
+ fun finishedSceneTransitions(from: SceneKey, to: SceneKey): Flow<Unit> {
+ return transitionState
+ .mapNotNull { it as? ObservableTransitionState.Idle }
+ .map { idleState -> idleState.scene }
+ .distinctUntilChanged()
+ .pairwise()
+ .mapNotNull { (previousSceneKey, currentSceneKey) ->
+ Unit.takeIf { previousSceneKey == from && currentSceneKey == to }
+ }
+ }
/** Handles a remote user input. */
fun onRemoteUserInput(input: RemoteUserInput) {
_remoteUserInput.value = input
}
+
+ /**
+ * Notifies that the UI has transitioned sufficiently to the given scene.
+ *
+ * *Not intended for external use!*
+ *
+ * Once a transition between one scene and another passes a threshold, the UI invokes this
+ * method to report it, updating the value in [desiredScene] to match what the UI shows.
+ */
+ internal fun onSceneChanged(scene: SceneModel, loggingReason: String) {
+ updateDesiredScene(scene, loggingReason, logger::logSceneChangeCommitted)
+ }
+
+ private fun updateDesiredScene(
+ scene: SceneModel,
+ loggingReason: String,
+ log: (from: SceneKey, to: SceneKey, loggingReason: String) -> Unit,
+ ) {
+ val currentSceneKey = desiredScene.value.key
+ if (currentSceneKey == scene.key) {
+ return
+ }
+
+ log(
+ /* from= */ currentSceneKey,
+ /* to= */ scene.key,
+ /* loggingReason= */ loggingReason,
+ )
+ repository.setDesiredScene(scene)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index bd233f80b47b..afefccb27214 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -30,6 +30,7 @@ import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.logger.SceneLogger
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
@@ -40,8 +41,8 @@ import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_B
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.launch
/**
@@ -73,14 +74,31 @@ constructor(
}
}
- /** Updates the visibility of the scene container based on the current scene. */
+ /** Updates the visibility of the scene container. */
private fun hydrateVisibility() {
applicationScope.launch {
- sceneInteractor.currentScene
- .map { it.key }
+ sceneInteractor.transitionState
+ .mapNotNull { state ->
+ when (state) {
+ is ObservableTransitionState.Idle -> {
+ if (state.scene != SceneKey.Gone) {
+ true to "scene is not Gone"
+ } else {
+ false to "scene is Gone"
+ }
+ }
+ is ObservableTransitionState.Transition -> {
+ if (state.fromScene == SceneKey.Gone) {
+ true to "scene transitioning away from Gone"
+ } else {
+ null
+ }
+ }
+ }
+ }
.distinctUntilChanged()
- .collect { sceneKey ->
- sceneInteractor.setVisible(sceneKey != SceneKey.Gone, "scene is $sceneKey")
+ .collect { (isVisible, loggingReason) ->
+ sceneInteractor.setVisible(isVisible, loggingReason)
}
}
}
@@ -89,43 +107,55 @@ constructor(
private fun automaticallySwitchScenes() {
applicationScope.launch {
authenticationInteractor.isUnlocked
- .map { isUnlocked ->
- val currentSceneKey = sceneInteractor.currentScene.value.key
+ .mapNotNull { isUnlocked ->
+ val renderedScenes =
+ when (val transitionState = sceneInteractor.transitionState.value) {
+ is ObservableTransitionState.Idle -> setOf(transitionState.scene)
+ is ObservableTransitionState.Transition ->
+ setOf(
+ transitionState.progress,
+ transitionState.toScene,
+ )
+ }
val isBypassEnabled = authenticationInteractor.isBypassEnabled()
when {
isUnlocked ->
- when (currentSceneKey) {
+ when {
// When the device becomes unlocked in Bouncer, go to Gone.
- is SceneKey.Bouncer ->
+ renderedScenes.contains(SceneKey.Bouncer) ->
SceneKey.Gone to "device unlocked in Bouncer scene"
+
// When the device becomes unlocked in Lockscreen, go to Gone if
// bypass is enabled.
- is SceneKey.Lockscreen ->
+ renderedScenes.contains(SceneKey.Lockscreen) ->
if (isBypassEnabled) {
SceneKey.Gone to
"device unlocked in Lockscreen scene with bypass"
} else {
null
}
+
// We got unlocked while on a scene that's not Lockscreen or
// Bouncer, no need to change scenes.
else -> null
}
+
// When the device becomes locked, to Lockscreen.
!isUnlocked ->
- when (currentSceneKey) {
+ when {
// Already on lockscreen or bouncer, no need to change scenes.
- is SceneKey.Lockscreen,
- is SceneKey.Bouncer -> null
+ renderedScenes.contains(SceneKey.Lockscreen) ||
+ renderedScenes.contains(SceneKey.Bouncer) -> null
+
// We got locked while on a scene that's not Lockscreen or Bouncer,
// go to Lockscreen.
else ->
- SceneKey.Lockscreen to "device locked in $currentSceneKey scene"
+ SceneKey.Lockscreen to
+ "device locked in non-Lockscreen and non-Bouncer scene"
}
else -> null
}
}
- .filterNotNull()
.collect { (targetSceneKey, loggingReason) ->
switchToScene(
targetSceneKey = targetSceneKey,
@@ -143,7 +173,7 @@ constructor(
WakefulnessState.STARTING_TO_SLEEP -> {
switchToScene(
targetSceneKey = SceneKey.Lockscreen,
- loggingReason = "device is asleep",
+ loggingReason = "device is starting to sleep",
)
}
WakefulnessState.STARTING_TO_WAKE -> {
@@ -165,8 +195,9 @@ constructor(
/** Keeps [SysUiState] up-to-date */
private fun hydrateSystemUiState() {
applicationScope.launch {
- sceneInteractor.currentScene
- .map { it.key }
+ sceneInteractor.transitionState
+ .mapNotNull { it as? ObservableTransitionState.Idle }
+ .map { it.scene }
.distinctUntilChanged()
.collect { sceneKey ->
sysUiState.updateFlags(
@@ -183,7 +214,7 @@ constructor(
}
private fun switchToScene(targetSceneKey: SceneKey, loggingReason: String) {
- sceneInteractor.setCurrentScene(
+ sceneInteractor.changeScene(
scene = SceneModel(targetSceneKey),
loggingReason = loggingReason,
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 0adbd5ad19a7..62136dcd8e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -37,7 +37,7 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
)
}
- fun logSceneChange(
+ fun logSceneChangeRequested(
from: SceneKey,
to: SceneKey,
reason: String,
@@ -50,7 +50,24 @@ class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer:
str2 = to.toString()
str3 = reason
},
- messagePrinter = { "$str1 → $str2, reason: $str3" },
+ messagePrinter = { "Scene change requested: $str1 → $str2, reason: $str3" },
+ )
+ }
+
+ fun logSceneChangeCommitted(
+ from: SceneKey,
+ to: SceneKey,
+ reason: String,
+ ) {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = {
+ str1 = from.toString()
+ str2 = to.toString()
+ str3 = reason
+ },
+ messagePrinter = { "Scene change committed: $str1 → $str2, reason: $str3" },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index b4ebaece21f1..3e9bbe464e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -45,15 +45,15 @@ constructor(
*/
val allSceneKeys: List<SceneKey> = interactor.allSceneKeys()
- /** The current scene. */
- val currentScene: StateFlow<SceneModel> = interactor.currentScene
+ /** The scene that should be rendered. */
+ val currentScene: StateFlow<SceneModel> = interactor.desiredScene
/** Whether the container is visible. */
val isVisible: StateFlow<Boolean> = interactor.isVisible
- /** Requests a transition to the scene with the given key. */
- fun setCurrentScene(scene: SceneModel) {
- interactor.setCurrentScene(
+ /** Notifies that the UI has transitioned sufficiently to the given scene. */
+ fun onSceneChanged(scene: SceneModel) {
+ interactor.onSceneChanged(
scene = scene,
loggingReason = SCENE_TRANSITION_LOGGING_REASON,
)
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index d33d113f6cbd..2f0fc5127009 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -228,6 +228,8 @@ open class SensorUseStartedActivity @Inject constructor(
}
override fun onDismiss(dialog: DialogInterface?) {
- finish()
+ if (!isChangingConfigurations) {
+ finish()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/DisplayTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/DisplayTracker.kt
index 468a75d8276e..e7ee961e1888 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/DisplayTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/DisplayTracker.kt
@@ -48,6 +48,9 @@ interface DisplayTracker {
/** Remove a [Callback] previously added. */
fun removeCallback(callback: Callback)
+ /** Gets the Display with the given displayId */
+ fun getDisplay(displayId: Int): Display
+
/** Ćallback for notifying of changes. */
interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
index 5169f88c373c..68cc483fbe80 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
@@ -115,6 +115,10 @@ internal constructor(
}
}
+ override fun getDisplay(displayId: Int): Display {
+ return displayManager.getDisplay(displayId)
+ }
+
@WorkerThread
private fun onDisplayAdded(displayId: Int, list: List<DisplayTrackerDataItem>) {
Assert.isNotMainThread()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index b11b4727c3c3..b29d46174bd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -49,6 +49,9 @@ interface WifiRepository {
const val COL_NAME_IS_ENABLED = "isEnabled"
/** Column name to use for [isWifiDefault] for table logging. */
const val COL_NAME_IS_DEFAULT = "isDefault"
+
+ const val CARRIER_MERGED_INVALID_SUB_ID_REASON =
+ "Wifi network was carrier merged but had invalid sub ID"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
index 7d2501ca0e79..ab9b516b837f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt
@@ -24,6 +24,7 @@ import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
@@ -56,12 +57,14 @@ constructor(
val activity = getString("activity").toActivity()
val ssid = getString("ssid")
val validated = getString("fully").toBoolean()
+ val hotspotDeviceType = getString("hotspot").toHotspotDeviceType()
return FakeWifiEventModel.Wifi(
level = level,
activity = activity,
ssid = ssid,
validated = validated,
+ hotspotDeviceType,
)
}
@@ -82,6 +85,20 @@ constructor(
else -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE
}
+ private fun String?.toHotspotDeviceType(): WifiNetworkModel.HotspotDeviceType {
+ return when (this) {
+ null,
+ "none" -> WifiNetworkModel.HotspotDeviceType.NONE
+ "unknown" -> WifiNetworkModel.HotspotDeviceType.UNKNOWN
+ "phone" -> WifiNetworkModel.HotspotDeviceType.PHONE
+ "tablet" -> WifiNetworkModel.HotspotDeviceType.TABLET
+ "laptop" -> WifiNetworkModel.HotspotDeviceType.LAPTOP
+ "watch" -> WifiNetworkModel.HotspotDeviceType.WATCH
+ "auto" -> WifiNetworkModel.HotspotDeviceType.AUTO
+ else -> WifiNetworkModel.HotspotDeviceType.INVALID
+ }
+ }
+
companion object {
const val DEFAULT_CARRIER_MERGED_SUB_ID = 10
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
index a57be665f105..99b680056d7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
@@ -97,6 +97,7 @@ constructor(
isValidated = validated ?: true,
level = level ?: 0,
ssid = ssid ?: DEMO_NET_SSID,
+ hotspotDeviceType = hotspotDeviceType,
// These fields below aren't supported in demo mode, since they aren't needed to satisfy
// the interface.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
index f5035cbc0215..b2e843e283f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model
import android.telephony.Annotation
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
/**
* Model for demo wifi commands, ported from [NetworkControllerImpl]
@@ -29,6 +30,8 @@ sealed interface FakeWifiEventModel {
@Annotation.DataActivityType val activity: Int,
val ssid: String?,
val validated: Boolean?,
+ val hotspotDeviceType: WifiNetworkModel.HotspotDeviceType =
+ WifiNetworkModel.HotspotDeviceType.NONE,
) : FakeWifiEventModel
data class CarrierMerged(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt
new file mode 100644
index 000000000000..f1b98b3972e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryHelper.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.pipeline.wifi.data.repository.prod
+
+import android.net.wifi.WifiManager
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
+import java.util.concurrent.Executor
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Object to provide shared helper functions between [WifiRepositoryImpl] and
+ * [WifiRepositoryViaTrackerLib].
+ */
+object WifiRepositoryHelper {
+ /** Creates a flow that fetches the [DataActivityModel] from [WifiManager]. */
+ fun createActivityFlow(
+ wifiManager: WifiManager,
+ @Main mainExecutor: Executor,
+ scope: CoroutineScope,
+ tableLogBuffer: TableLogBuffer,
+ inputLogger: (String) -> Unit,
+ ): StateFlow<DataActivityModel> {
+ return conflatedCallbackFlow {
+ val callback =
+ WifiManager.TrafficStateCallback { state ->
+ inputLogger.invoke(prettyPrintActivity(state))
+ trySend(state.toWifiDataActivityModel())
+ }
+ wifiManager.registerTrafficStateCallback(mainExecutor, callback)
+ awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
+ }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = ACTIVITY_PREFIX,
+ initialValue = ACTIVITY_DEFAULT,
+ )
+ .stateIn(
+ scope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = ACTIVITY_DEFAULT,
+ )
+ }
+
+ // TODO(b/292534484): This print should only be done in [MessagePrinter] part of the log buffer.
+ private fun prettyPrintActivity(activity: Int): String {
+ return when (activity) {
+ WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE -> "NONE"
+ WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN -> "IN"
+ WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT -> "OUT"
+ WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT -> "INOUT"
+ else -> "INVALID"
+ }
+ }
+
+ private const val ACTIVITY_PREFIX = "wifiActivity"
+ val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 995de6d2fc61..afd15765d163 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -28,7 +28,6 @@ import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
-import android.net.wifi.WifiManager.TrafficStateCallback
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -40,10 +39,10 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.CARRIER_MERGED_INVALID_SUB_ID_REASON
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_ENABLED
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryDagger
@@ -218,29 +217,15 @@ constructor(
)
override val wifiActivity: StateFlow<DataActivityModel> =
- conflatedCallbackFlow {
- val callback = TrafficStateCallback { state ->
- logger.logActivity(prettyPrintActivity(state))
- trySend(state.toWifiDataActivityModel())
- }
- wifiManager.registerTrafficStateCallback(mainExecutor, callback)
- awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
- }
- .logDiffsForTable(
- wifiTableLogBuffer,
- columnPrefix = ACTIVITY_PREFIX,
- initialValue = ACTIVITY_DEFAULT,
- )
- .stateIn(
- scope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = ACTIVITY_DEFAULT,
- )
+ WifiRepositoryHelper.createActivityFlow(
+ wifiManager,
+ mainExecutor,
+ scope,
+ wifiTableLogBuffer,
+ logger::logActivity,
+ )
companion object {
- private const val ACTIVITY_PREFIX = "wifiActivity"
-
- val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
// Start out with no known wifi network.
// Note: [WifiStatusTracker] (the old implementation of connectivity logic) does do an
// initial fetch to get a starting wifi network. But, it uses a deprecated API
@@ -277,6 +262,8 @@ constructor(
isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED),
level = wifiManager.calculateSignalLevel(wifiInfo.rssi),
wifiInfo.ssid,
+ // This repository doesn't support any hotspot information.
+ WifiNetworkModel.HotspotDeviceType.NONE,
wifiInfo.isPasspointAp,
wifiInfo.isOsuAp,
wifiInfo.passpointProviderFriendlyName
@@ -284,16 +271,6 @@ constructor(
}
}
- private fun prettyPrintActivity(activity: Int): String {
- return when (activity) {
- TrafficStateCallback.DATA_ACTIVITY_NONE -> "NONE"
- TrafficStateCallback.DATA_ACTIVITY_IN -> "IN"
- TrafficStateCallback.DATA_ACTIVITY_OUT -> "OUT"
- TrafficStateCallback.DATA_ACTIVITY_INOUT -> "INOUT"
- else -> "INVALID"
- }
- }
-
private val WIFI_NETWORK_CALLBACK_REQUEST: NetworkRequest =
NetworkRequest.Builder()
.clearCapabilities()
@@ -301,9 +278,6 @@ constructor(
.addTransportType(TRANSPORT_WIFI)
.addTransportType(TRANSPORT_CELLULAR)
.build()
-
- private const val CARRIER_MERGED_INVALID_SUB_ID_REASON =
- "Wifi network was carrier merged but had invalid sub ID"
}
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
index 127136789ba6..175563bb0764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt
@@ -17,12 +17,15 @@
package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
import android.net.wifi.WifiManager
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.table.TableLogBuffer
@@ -31,20 +34,25 @@ import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
import com.android.systemui.statusbar.pipeline.dagger.WifiTrackerLibInputLog
import com.android.systemui.statusbar.pipeline.dagger.WifiTrackerLibTableLog
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.CARRIER_MERGED_INVALID_SUB_ID_REASON
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository.Companion.COL_NAME_IS_ENABLED
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryViaTrackerLibDagger
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_STATE_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Inactive.toHotspotDeviceType
+import com.android.wifitrackerlib.HotspotNetworkEntry
import com.android.wifitrackerlib.MergedCarrierEntry
import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
import com.android.wifitrackerlib.WifiPickerTracker
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
@@ -62,6 +70,7 @@ import kotlinx.coroutines.flow.stateIn
class WifiRepositoryViaTrackerLib
@Inject
constructor(
+ featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
@@ -75,6 +84,8 @@ constructor(
mainExecutor.execute { it.currentState = Lifecycle.State.CREATED }
}
+ private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER)
+
private var wifiPickerTracker: WifiPickerTracker? = null
private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run {
@@ -128,19 +139,21 @@ constructor(
}
}
- // TODO(b/292591403): [WifiPickerTrackerFactory] currently scans to see all
- // available wifi networks every 10s. Because SysUI only needs to display the
- // **connected** network, we don't need scans to be running. We should disable these
- // scans (ideal) or at least run them very infrequently.
- wifiPickerTracker = wifiPickerTrackerFactory.create(lifecycle, callback)
+ wifiPickerTracker =
+ wifiPickerTrackerFactory.create(lifecycle, callback).apply {
+ // By default, [WifiPickerTracker] will scan to see all available wifi
+ // networks in the area. Because SysUI only needs to display the
+ // **connected** network, we don't need scans to be running (and in fact,
+ // running scans is costly and should be avoided whenever possible).
+ this?.disableScanning()
+ }
// The lifecycle must be STARTED in order for the callback to receive events.
mainExecutor.execute { lifecycle.currentState = Lifecycle.State.STARTED }
awaitClose {
mainExecutor.execute { lifecycle.currentState = Lifecycle.State.CREATED }
}
}
- // TODO(b/292534484): Update to Eagerly once scans are disabled. (Here and other flows)
- .stateIn(scope, SharingStarted.WhileSubscribed(), current)
+ .stateIn(scope, SharingStarted.Eagerly, current)
}
override val isWifiEnabled: StateFlow<Boolean> =
@@ -153,7 +166,7 @@ constructor(
columnName = COL_NAME_IS_ENABLED,
initialValue = false,
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ .stateIn(scope, SharingStarted.Eagerly, false)
override val wifiNetwork: StateFlow<WifiNetworkModel> =
wifiPickerTrackerInfo
@@ -164,7 +177,7 @@ constructor(
columnPrefix = "",
initialValue = WIFI_NETWORK_DEFAULT,
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), WIFI_NETWORK_DEFAULT)
+ .stateIn(scope, SharingStarted.Eagerly, WIFI_NETWORK_DEFAULT)
/** Converts WifiTrackerLib's [WifiEntry] into our internal model. */
private fun WifiEntry.toWifiNetworkModel(): WifiNetworkModel {
@@ -172,30 +185,58 @@ constructor(
return WIFI_NETWORK_DEFAULT
}
return if (this is MergedCarrierEntry) {
+ this.convertCarrierMergedToModel()
+ } else {
+ this.convertNormalToModel()
+ }
+ }
+
+ private fun MergedCarrierEntry.convertCarrierMergedToModel(): WifiNetworkModel {
+ return if (this.subscriptionId == INVALID_SUBSCRIPTION_ID) {
+ WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
+ } else {
WifiNetworkModel.CarrierMerged(
networkId = NETWORK_ID,
- // TODO(b/292534484): Fetch the real subscription ID from [MergedCarrierEntry].
- subscriptionId = TEMP_SUB_ID,
+ subscriptionId = this.subscriptionId,
level = this.level,
// WifiManager APIs to calculate the signal level start from 0, so
// maxSignalLevel + 1 represents the total level buckets count.
numberOfLevels = wifiManager.maxSignalLevel + 1,
)
- } else {
- WifiNetworkModel.Active(
- networkId = NETWORK_ID,
- isValidated = this.hasInternetAccess(),
- level = this.level,
- ssid = this.ssid,
- // TODO(b/292534484): Fetch the real values from [WifiEntry] (#getTitle might be
- // appropriate).
- isPasspointAccessPoint = false,
- isOnlineSignUpForPasspointAccessPoint = false,
- passpointProviderFriendlyName = null,
- )
}
}
+ private fun WifiEntry.convertNormalToModel(): WifiNetworkModel {
+ if (this.level == WIFI_LEVEL_UNREACHABLE || this.level !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX) {
+ // If our level means the network is unreachable or the level is otherwise invalid, we
+ // don't have an active network.
+ return WifiNetworkModel.Inactive
+ }
+
+ val hotspotDeviceType =
+ if (isInstantTetherEnabled && this is HotspotNetworkEntry) {
+ this.deviceType.toHotspotDeviceType()
+ } else {
+ WifiNetworkModel.HotspotDeviceType.NONE
+ }
+
+ return WifiNetworkModel.Active(
+ networkId = NETWORK_ID,
+ isValidated = this.hasInternetAccess(),
+ level = this.level,
+ ssid = this.title,
+ hotspotDeviceType = hotspotDeviceType,
+ // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the SSID for
+ // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can
+ // always be false/null in this repository.
+ // TODO(b/292534484): Remove these fields from the wifi network model once this
+ // repository is fully enabled.
+ isPasspointAccessPoint = false,
+ isOnlineSignUpForPasspointAccessPoint = false,
+ passpointProviderFriendlyName = null,
+ )
+ }
+
override val isWifiDefault: StateFlow<Boolean> =
wifiPickerTrackerInfo
.map { it.isDefault }
@@ -206,12 +247,16 @@ constructor(
columnName = COL_NAME_IS_DEFAULT,
initialValue = false,
)
- .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+ .stateIn(scope, SharingStarted.Eagerly, false)
- // TODO(b/292534484): Re-use WifiRepositoryImpl code to implement wifi activity since
- // WifiTrackerLib doesn't expose activity details.
override val wifiActivity: StateFlow<DataActivityModel> =
- MutableStateFlow(DataActivityModel(false, false))
+ WifiRepositoryHelper.createActivityFlow(
+ wifiManager,
+ mainExecutor,
+ scope,
+ wifiTrackerLibTableLogBuffer,
+ this::logActivity,
+ )
private fun logOnWifiEntriesChanged(connectedEntry: WifiEntry?) {
inputLogger.log(
@@ -231,6 +276,10 @@ constructor(
)
}
+ private fun logActivity(activity: String) {
+ inputLogger.log(TAG, LogLevel.DEBUG, { str1 = activity }, { "onActivityChanged: $str1" })
+ }
+
/**
* Data class storing all the information fetched from [WifiPickerTracker].
*
@@ -249,6 +298,7 @@ constructor(
class Factory
@Inject
constructor(
+ private val featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
private val wifiPickerTrackerFactory: WifiPickerTrackerFactory,
@@ -257,6 +307,7 @@ constructor(
) {
fun create(wifiManager: WifiManager): WifiRepositoryViaTrackerLib {
return WifiRepositoryViaTrackerLib(
+ featureFlags,
scope,
mainExecutor,
wifiPickerTrackerFactory,
@@ -283,13 +334,5 @@ constructor(
* to [WifiRepositoryViaTrackerLib].
*/
private const val NETWORK_ID = -1
-
- /**
- * A temporary subscription ID until WifiTrackerLib exposes a method to fetch the
- * subscription ID.
- *
- * Use -2 because [SubscriptionManager.INVALID_SUBSCRIPTION_ID] is -1.
- */
- private const val TEMP_SUB_ID = -2
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
index 4b33c88cea30..7078a2e1728c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
@@ -17,11 +17,13 @@
package com.android.systemui.statusbar.pipeline.wifi.shared.model
import android.net.wifi.WifiManager.UNKNOWN_SSID
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo
import android.telephony.SubscriptionManager
import androidx.annotation.VisibleForTesting
import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
@@ -52,6 +54,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
+ row.logChange(COL_HOTSPOT, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
row.logChange(COL_PASSPOINT_NAME, null)
@@ -83,6 +86,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
+ row.logChange(COL_HOTSPOT, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
row.logChange(COL_PASSPOINT_NAME, null)
@@ -110,6 +114,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
+ row.logChange(COL_HOTSPOT, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
row.logChange(COL_PASSPOINT_NAME, null)
@@ -184,6 +189,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_LEVEL, level)
row.logChange(COL_NUM_LEVELS, numberOfLevels)
row.logChange(COL_SSID, null)
+ row.logChange(COL_HOTSPOT, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
row.logChange(COL_PASSPOINT_NAME, null)
@@ -209,6 +215,12 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
/** See [android.net.wifi.WifiInfo.ssid]. */
val ssid: String? = null,
+ /**
+ * The type of device providing a hotspot connection, or [HotspotDeviceType.NONE] if this
+ * isn't a hotspot connection.
+ */
+ val hotspotDeviceType: HotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
+
/** See [android.net.wifi.WifiInfo.isPasspointAp]. */
val isPasspointAccessPoint: Boolean = false,
@@ -247,6 +259,9 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
if (prevVal.ssid != ssid) {
row.logChange(COL_SSID, ssid)
}
+ if (prevVal.hotspotDeviceType != hotspotDeviceType) {
+ row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
+ }
// TODO(b/238425913): The passpoint-related values are frequently never used, so it
// would be great to not log them when they're not used.
@@ -272,6 +287,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_LEVEL, level)
row.logChange(COL_NUM_LEVELS, null)
row.logChange(COL_SSID, ssid)
+ row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
@@ -298,13 +314,51 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
}
companion object {
+ // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX] instead
+ // once the migration to WifiTrackerLib is complete.
@VisibleForTesting internal const val MAX_VALID_LEVEL = 4
}
}
companion object {
+ // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN] instead
+ // once the migration to WifiTrackerLib is complete.
@VisibleForTesting internal const val MIN_VALID_LEVEL = 0
}
+
+ /**
+ * Enum for the type of device providing the hotspot connection, or [NONE] if this connection
+ * isn't a hotspot.
+ */
+ enum class HotspotDeviceType {
+ /* This wifi connection isn't a hotspot. */
+ NONE,
+ /** The device type for this hotspot is unknown. */
+ UNKNOWN,
+ PHONE,
+ TABLET,
+ LAPTOP,
+ WATCH,
+ AUTO,
+ /** The device type sent for this hotspot is invalid to SysUI. */
+ INVALID,
+ }
+
+ /**
+ * Converts a device type from [com.android.wifitrackerlib.HotspotNetworkEntry.deviceType] to
+ * our internal representation.
+ */
+ fun @receiver:DeviceType Int.toHotspotDeviceType(): HotspotDeviceType {
+ return when (this) {
+ NetworkProviderInfo.DEVICE_TYPE_UNKNOWN -> HotspotDeviceType.UNKNOWN
+ NetworkProviderInfo.DEVICE_TYPE_PHONE -> HotspotDeviceType.PHONE
+ NetworkProviderInfo.DEVICE_TYPE_TABLET -> HotspotDeviceType.TABLET
+ NetworkProviderInfo.DEVICE_TYPE_LAPTOP -> HotspotDeviceType.LAPTOP
+ NetworkProviderInfo.DEVICE_TYPE_WATCH -> HotspotDeviceType.WATCH
+ NetworkProviderInfo.DEVICE_TYPE_AUTO -> HotspotDeviceType.AUTO
+ else -> HotspotDeviceType.INVALID
+ }
+ }
}
const val TYPE_CARRIER_MERGED = "CarrierMerged"
@@ -319,6 +373,7 @@ const val COL_VALIDATED = "isValidated"
const val COL_LEVEL = "level"
const val COL_NUM_LEVELS = "maxLevel"
const val COL_SSID = "ssid"
+const val COL_HOTSPOT = "hotspot"
const val COL_PASSPOINT_ACCESS_POINT = "isPasspointAccessPoint"
const val COL_ONLINE_SIGN_UP = "isOnlineSignUpForPasspointAccessPoint"
const val COL_PASSPOINT_NAME = "passpointProviderFriendlyName"
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index e7d420bcb32b..9016220b40cf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -419,7 +419,15 @@ public class CarrierTextManagerTest extends SysuiTestCase {
assertFalse(mWifiRepository.isWifiConnectedWithValidSsid());
mWifiRepository.setWifiNetwork(
- new WifiNetworkModel.Active(0, false, 0, "", false, false, null));
+ new WifiNetworkModel.Active(
+ /* networkId= */ 0,
+ /* isValidated= */ false,
+ /* level= */ 0,
+ /* ssid= */ "",
+ /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE,
+ /* isPasspointAccessPoint= */ false,
+ /* isOnlineSignUpForPasspointAccessPoint= */ false,
+ /* passpointProviderFriendlyName= */ null));
assertTrue(mWifiRepository.isWifiConnectedWithValidSsid());
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index efb981e5cebb..a6bd9363a08b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -50,6 +50,7 @@ import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -66,6 +67,8 @@ import com.google.common.truth.Truth
import java.util.Optional
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -139,6 +142,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
private lateinit var testableResources: TestableResources
private lateinit var sceneTestUtils: SceneTestUtils
private lateinit var sceneInteractor: SceneInteractor
+ private lateinit var sceneTransitionStateFlow: MutableStateFlow<ObservableTransitionState>
private lateinit var underTest: KeyguardSecurityContainerController
@@ -198,6 +202,9 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
whenever(userInteractor.getSelectedUserId()).thenReturn(TARGET_USER_ID)
sceneTestUtils = SceneTestUtils(this)
sceneInteractor = sceneTestUtils.sceneInteractor()
+ sceneTransitionStateFlow =
+ MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Lockscreen))
+ sceneInteractor.setTransitionState(sceneTransitionStateFlow)
underTest =
KeyguardSecurityContainerController(
@@ -733,20 +740,39 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// is
// not enough to trigger a dismissal of the keyguard.
underTest.onViewAttached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ SceneKey.Lockscreen,
+ SceneKey.Bouncer,
+ flowOf(.5f)
+ )
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While listening, going from the bouncer scene to the gone scene, does dismiss the
// keyguard.
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
// While listening, moving back to the bouncer scene does not dismiss the keyguard
// again.
clearInvocations(viewMediatorCallback)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Gone, SceneKey.Bouncer, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -754,12 +780,22 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// scene
// does not dismiss the keyguard while we're not listening.
underTest.onViewDetached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
// While not listening, moving back to the bouncer does not dismiss the keyguard.
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Gone, SceneKey.Bouncer, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Bouncer)
runCurrent()
verify(viewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt())
@@ -767,7 +803,12 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
// gone
// scene now does dismiss the keyguard again.
underTest.onViewAttached()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value =
+ ObservableTransitionState.Transition(SceneKey.Bouncer, SceneKey.Gone, flowOf(.5f))
+ runCurrent()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
+ sceneTransitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
runCurrent()
verify(viewMediatorCallback).keyguardDone(anyBoolean(), anyInt())
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 5abab6239b1e..6f3322ab1b85 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -40,6 +40,7 @@ import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_T
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.android.systemui.flags.Flags.FP_LISTEN_OCCLUDING_APPS;
+import static com.android.systemui.flags.Flags.STOP_FACE_AUTH_ON_DISPLAY_OFF;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
@@ -89,6 +90,7 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
+import android.hardware.display.DisplayManagerGlobal;
import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
@@ -121,6 +123,9 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
+import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayInfo;
import androidx.annotation.NonNull;
@@ -143,6 +148,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -304,10 +310,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mFingerprintAuthenticatorsRegisteredCallback;
private IFaceAuthenticatorsRegisteredCallback mFaceAuthenticatorsRegisteredCallback;
private final InstanceId mKeyguardInstanceId = InstanceId.fakeInstanceId(999);
+ private FakeDisplayTracker mDisplayTracker;
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
+ mDisplayTracker = new FakeDisplayTracker(mContext);
when(mSessionTracker.getSessionId(SESSION_KEYGUARD)).thenReturn(mKeyguardInstanceId);
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
@@ -348,6 +356,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
allowTestableLooperAsMainThread();
mFeatureFlags = new FakeFeatureFlags();
mFeatureFlags.set(FP_LISTEN_OCCLUDING_APPS, false);
+ mFeatureFlags.set(STOP_FACE_AUTH_ON_DISPLAY_OFF, false);
when(mSecureSettings.getUriFor(anyString())).thenReturn(mURI);
@@ -358,6 +367,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
anyInt());
mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mContext);
+ setupBiometrics(mKeyguardUpdateMonitor);
+ }
+
+ private void setupBiometrics(KeyguardUpdateMonitor keyguardUpdateMonitor)
+ throws RemoteException {
captureAuthenticatorsRegisteredCallbacks();
setupFaceAuth(/* isClass3 */ false);
setupFingerprintAuth(/* isClass3 */ true);
@@ -367,9 +381,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
biometricsEnabledForCurrentUser();
- mHandler = spy(mKeyguardUpdateMonitor.getHandler());
+ mHandler = spy(keyguardUpdateMonitor.getHandler());
try {
- FieldSetter.setField(mKeyguardUpdateMonitor,
+ FieldSetter.setField(keyguardUpdateMonitor,
KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
} catch (NoSuchFieldException e) {
@@ -3029,6 +3043,79 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(callback).onBiometricEnrollmentStateChanged(BiometricSourceType.FACE);
}
+ @Test
+ public void stopFaceAuthOnDisplayOffFlagNotEnabled_doNotRegisterForDisplayCallback() {
+ assertThat(mDisplayTracker.getDisplayCallbacks().size()).isEqualTo(0);
+ }
+
+ @Test
+ public void onDisplayOn_nothingHappens() throws RemoteException {
+ // GIVEN
+ keyguardIsVisible();
+ enableStopFaceAuthOnDisplayOff();
+
+ // WHEN the default display state changes to ON
+ triggerDefaultDisplayStateChangeToOn();
+
+ // THEN face auth is NOT started since we rely on STARTED_WAKING_UP to start face auth,
+ // NOT the display on event
+ verifyFaceAuthenticateNeverCalled();
+ verifyFaceDetectNeverCalled();
+ }
+
+ @Test
+ public void onDisplayOff_stopFaceAuth() throws RemoteException {
+ enableStopFaceAuthOnDisplayOff();
+
+ // GIVEN device is listening for face
+ mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ verifyFaceAuthenticateCall();
+
+ final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+ mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ // WHEN the default display state changes to OFF
+ triggerDefaultDisplayStateChangeToOff();
+
+ // THEN face listening is stopped.
+ verify(faceCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FACE)); // beverlyt
+
+ }
+
+ private void triggerDefaultDisplayStateChangeToOn() {
+ triggerDefaultDisplayStateChangeTo(true);
+ }
+
+ private void triggerDefaultDisplayStateChangeToOff() {
+ triggerDefaultDisplayStateChangeTo(false);
+ }
+
+ /**
+ * @param on true for Display.STATE_ON, else Display.STATE_OFF
+ */
+ private void triggerDefaultDisplayStateChangeTo(boolean on) {
+ DisplayManagerGlobal displayManagerGlobal = mock(DisplayManagerGlobal.class);
+ DisplayInfo displayInfoWithDisplayState = new DisplayInfo();
+ displayInfoWithDisplayState.state = on ? Display.STATE_ON : Display.STATE_OFF;
+ when(displayManagerGlobal.getDisplayInfo(mDisplayTracker.getDefaultDisplayId()))
+ .thenReturn(displayInfoWithDisplayState);
+ mDisplayTracker.setAllDisplays(new Display[]{
+ new Display(
+ displayManagerGlobal,
+ mDisplayTracker.getDefaultDisplayId(),
+ displayInfoWithDisplayState,
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
+ )
+ });
+ mDisplayTracker.triggerOnDisplayChanged(mDisplayTracker.getDefaultDisplayId());
+ }
+
private void verifyFingerprintAuthenticateNeverCalled() {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
@@ -3297,6 +3384,18 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ private void enableStopFaceAuthOnDisplayOff() throws RemoteException {
+ cleanupKeyguardUpdateMonitor();
+ clearInvocations(mFaceManager);
+ clearInvocations(mFingerprintManager);
+ clearInvocations(mBiometricManager);
+ clearInvocations(mStatusBarStateController);
+ mFeatureFlags.set(STOP_FACE_AUTH_ON_DISPLAY_OFF, true);
+ mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mContext);
+ setupBiometrics(mKeyguardUpdateMonitor);
+ assertThat(mDisplayTracker.getDisplayCallbacks().size()).isEqualTo(1);
+ }
+
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
@@ -3374,7 +3473,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mPackageManager, mFaceManager, mFingerprintManager, mBiometricManager,
mFaceWakeUpTriggersConfig, mDevicePostureController,
Optional.of(mInteractiveToAuthProvider), mFeatureFlags,
- mTaskStackChangeListeners, mActivityTaskManager);
+ mTaskStackChangeListeners, mActivityTaskManager, mDisplayTracker);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index ed6a891a6094..45021ba1b300 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -20,7 +20,9 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN
import static com.android.keyguard.LockIconView.ICON_LOCK;
import static com.android.keyguard.LockIconView.ICON_UNLOCK;
+import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
@@ -33,11 +35,13 @@ import android.hardware.biometrics.BiometricSourceType;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
+import android.view.HapticFeedbackConstants;
import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.settingslib.udfps.UdfpsOverlayParams;
+import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.doze.util.BurnInHelperKt;
import org.junit.Test;
@@ -339,4 +343,59 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest {
// THEN the lock icon is shown
verify(mLockIconView).setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
+
+ @Test
+ public void playHaptic_onTouchExploration_NoOneWayHaptics_usesVibrate() {
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false);
+
+ // WHEN request to vibrate on touch exploration
+ mUnderTest.vibrateOnTouchExploration();
+
+ // THEN vibrates
+ verify(mVibrator).vibrate(
+ anyInt(),
+ any(),
+ eq(UdfpsController.EFFECT_CLICK),
+ eq("lock-icon-down"),
+ any());
+ }
+
+ @Test
+ public void playHaptic_onTouchExploration_withOneWayHaptics_performHapticFeedback() {
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true);
+
+ // WHEN request to vibrate on touch exploration
+ mUnderTest.vibrateOnTouchExploration();
+
+ // THEN performHapticFeedback is used
+ verify(mVibrator).performHapticFeedback(any(), eq(HapticFeedbackConstants.CONTEXT_CLICK));
+ }
+
+ @Test
+ public void playHaptic_onLongPress_NoOneWayHaptics_usesVibrate() {
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false);
+
+ // WHEN request to vibrate on long press
+ mUnderTest.vibrateOnLongPress();
+
+ // THEN uses vibrate
+ verify(mVibrator).vibrate(
+ anyInt(),
+ any(),
+ eq(UdfpsController.EFFECT_CLICK),
+ eq("lock-screen-lock-icon-longpress"),
+ any());
+ }
+
+ @Test
+ public void playHaptic_onLongPress_withOneWayHaptics_performHapticFeedback() {
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true);
+
+ // WHEN request to vibrate on long press
+ mUnderTest.vibrateOnLongPress();
+
+ // THEN uses perform haptic feedback
+ verify(mVibrator).performHapticFeedback(any(), eq(UdfpsController.LONG_PRESS));
+
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index df4d2225f459..86e0c751085b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -70,7 +70,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -102,7 +102,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withAutoConfirmPin() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -139,7 +139,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun pinAuthMethod_tryAutoConfirm_withoutAutoConfirmPin() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
@@ -169,7 +169,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun passwordAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
@@ -202,7 +202,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun patternAuthMethod() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
@@ -236,7 +236,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -249,7 +249,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
utils.authenticationRepository.setLockscreenEnabled(true)
utils.authenticationRepository.setUnlocked(false)
@@ -262,7 +262,7 @@ class BouncerInteractorTest : SysuiTestCase() {
@Test
fun showOrUnlockDevice_customMessageShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(underTest.message)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
@@ -283,7 +283,7 @@ class BouncerInteractorTest : SysuiTestCase() {
val isThrottled by collectLastValue(underTest.isThrottled)
val throttling by collectLastValue(underTest.throttling)
val message by collectLastValue(underTest.message)
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
underTest.showOrUnlockDevice()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 4e9fe8d91da1..4380af80efbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -73,14 +73,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -93,14 +94,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPasswordInputChanged() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -115,12 +117,13 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("password")
@@ -133,14 +136,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")
@@ -155,14 +159,15 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateKeyPressed_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val password by collectLastValue(underTest.password)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPasswordInputChanged("wrong")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 000200c606b3..ea2cad2ab517 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -76,7 +76,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -84,7 +84,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -98,7 +99,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragStart() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -106,7 +107,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -122,14 +124,15 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -169,7 +172,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -177,7 +180,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
@@ -201,7 +205,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
@Test
fun onDragEnd_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val selectedDots by collectLastValue(underTest.selectedDots)
val currentDot by collectLastValue(underTest.currentDot)
@@ -209,7 +213,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onDragStart()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 4b667c393b62..531f86abdfbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -76,11 +76,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onShown() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -93,12 +95,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinButtonClicked() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -113,12 +117,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonClicked() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -135,11 +141,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onPinEdit() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
@@ -157,12 +165,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onBackspaceButtonLongPressed() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
runCurrent()
@@ -181,10 +191,12 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -199,12 +211,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -223,12 +237,14 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAuthenticateButtonClicked_correctAfterWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
underTest.onPinButtonClicked(1)
@@ -255,11 +271,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenCorrect() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -272,13 +290,15 @@ class PinBouncerViewModelTest : SysuiTestCase() {
@Test
fun onAutoConfirm_whenWrong() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
utils.authenticationRepository.setAutoConfirmEnabled(true)
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.onShown()
FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 834b9c526669..45d7a5ebb60a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -107,7 +107,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -120,7 +120,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -133,7 +133,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
@@ -146,7 +146,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
@Test
fun onLockButtonClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index bb365d05e9e2..2cb02058ab03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -56,7 +56,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -69,7 +69,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 56e3e9649fe7..181f8a7e3003 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -25,7 +25,6 @@ import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -39,6 +38,7 @@ import org.junit.runners.JUnit4
class SceneContainerRepositoryTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
+ private val testScope = utils.testScope
@Test
fun allSceneKeys() {
@@ -56,97 +56,82 @@ class SceneContainerRepositoryTest : SysuiTestCase() {
}
@Test
- fun currentScene() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val currentScene by collectLastValue(underTest.currentScene)
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+ fun desiredScene() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val currentScene by collectLastValue(underTest.desiredScene)
+ assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
- }
+ underTest.setDesiredScene(SceneModel(SceneKey.Shade))
+ assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
@Test(expected = IllegalStateException::class)
- fun setCurrentScene_noSuchSceneInContainer_throws() {
+ fun setDesiredScene_noSuchSceneInContainer_throws() {
val underTest =
utils.fakeSceneContainerRepository(
utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
)
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
+ underTest.setDesiredScene(SceneModel(SceneKey.Shade))
}
@Test
- fun isVisible() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val isVisible by collectLastValue(underTest.isVisible)
- assertThat(isVisible).isTrue()
+ fun isVisible() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val isVisible by collectLastValue(underTest.isVisible)
+ assertThat(isVisible).isTrue()
- underTest.setVisible(false)
- assertThat(isVisible).isFalse()
+ underTest.setVisible(false)
+ assertThat(isVisible).isFalse()
- underTest.setVisible(true)
- assertThat(isVisible).isTrue()
- }
+ underTest.setVisible(true)
+ assertThat(isVisible).isTrue()
+ }
@Test
- fun transitionProgress() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val sceneTransitionProgress by collectLastValue(underTest.transitionProgress)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- val transitionState =
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(SceneKey.Lockscreen)
- )
- underTest.setTransitionState(transitionState)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- val progress = MutableStateFlow(1f)
- transitionState.value =
- ObservableTransitionState.Transition(
- fromScene = SceneKey.Lockscreen,
- toScene = SceneKey.Shade,
- progress = progress,
- )
- assertThat(sceneTransitionProgress).isEqualTo(1f)
-
- progress.value = 0.1f
- assertThat(sceneTransitionProgress).isEqualTo(0.1f)
-
- progress.value = 0.9f
- assertThat(sceneTransitionProgress).isEqualTo(0.9f)
-
- underTest.setTransitionState(null)
- assertThat(sceneTransitionProgress).isEqualTo(1f)
- }
+ fun transitionState_defaultsToIdle() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState by collectLastValue(underTest.transitionState)
+
+ assertThat(transitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
@Test
- fun setSceneTransition() = runTest {
- val underTest = utils.fakeSceneContainerRepository()
- val sceneTransition by collectLastValue(underTest.transitions)
- assertThat(sceneTransition).isNull()
+ fun transitionState_reflectsUpdates() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ underTest.setTransitionState(transitionState)
+ val reflectedTransitionState by collectLastValue(underTest.transitionState)
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ val progress = MutableStateFlow(1f)
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Lockscreen,
+ toScene = SceneKey.Shade,
+ progress = progress,
+ )
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- underTest.setSceneTransition(SceneKey.Lockscreen, SceneKey.QuickSettings)
- assertThat(sceneTransition)
- .isEqualTo(
- SceneTransitionModel(from = SceneKey.Lockscreen, to = SceneKey.QuickSettings)
- )
- }
+ progress.value = 0.1f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- @Test(expected = IllegalStateException::class)
- fun setSceneTransition_noFromSceneInContainer_throws() {
- val underTest =
- utils.fakeSceneContainerRepository(
- utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
- )
- underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
- }
+ progress.value = 0.9f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- @Test(expected = IllegalStateException::class)
- fun setSceneTransition_noToSceneInContainer_throws() {
- val underTest =
- utils.fakeSceneContainerRepository(
- utils.fakeSceneContainerConfig(listOf(SceneKey.QuickSettings, SceneKey.Lockscreen)),
- )
- underTest.setSceneTransition(SceneKey.Shade, SceneKey.Lockscreen)
- }
+ underTest.setTransitionState(null)
+ assertThat(reflectedTransitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 4facc7a6a36d..0a93a7ca465f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -25,10 +25,12 @@ import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
-import com.android.systemui.scene.shared.model.SceneTransitionModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -39,6 +41,7 @@ import org.junit.runners.JUnit4
class SceneInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
+ private val testScope = utils.testScope
private val repository = utils.fakeSceneContainerRepository()
private val underTest = utils.sceneInteractor(repository = repository)
@@ -48,77 +51,156 @@ class SceneInteractorTest : SysuiTestCase() {
}
@Test
- fun currentScene() = runTest {
- val currentScene by collectLastValue(underTest.currentScene)
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+ fun changeScene() =
+ testScope.runTest {
+ val desiredScene by collectLastValue(underTest.desiredScene)
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
- }
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
+
+ @Test
+ fun onSceneChanged() =
+ testScope.runTest {
+ val desiredScene by collectLastValue(underTest.desiredScene)
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ assertThat(desiredScene).isEqualTo(SceneModel(SceneKey.Shade))
+ }
@Test
- fun sceneTransitionProgress() = runTest {
- val transitionProgress by collectLastValue(underTest.transitionProgress)
- assertThat(transitionProgress).isEqualTo(1f)
+ fun transitionState() =
+ testScope.runTest {
+ val underTest = utils.fakeSceneContainerRepository()
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ underTest.setTransitionState(transitionState)
+ val reflectedTransitionState by collectLastValue(underTest.transitionState)
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
- val progress = MutableStateFlow(0.55f)
- repository.setTransitionState(
- MutableStateFlow(
+ val progress = MutableStateFlow(1f)
+ transitionState.value =
ObservableTransitionState.Transition(
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.Shade,
progress = progress,
- ),
- )
- )
- assertThat(transitionProgress).isEqualTo(0.55f)
- }
+ )
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ progress.value = 0.1f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ progress.value = 0.9f
+ assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
+
+ underTest.setTransitionState(null)
+ assertThat(reflectedTransitionState)
+ .isEqualTo(
+ ObservableTransitionState.Idle(utils.fakeSceneContainerConfig().initialSceneKey)
+ )
+ }
@Test
- fun isVisible() = runTest {
- val isVisible by collectLastValue(underTest.isVisible)
- assertThat(isVisible).isTrue()
+ fun isVisible() =
+ testScope.runTest {
+ val isVisible by collectLastValue(underTest.isVisible)
+ assertThat(isVisible).isTrue()
- underTest.setVisible(false, "reason")
- assertThat(isVisible).isFalse()
+ underTest.setVisible(false, "reason")
+ assertThat(isVisible).isFalse()
- underTest.setVisible(true, "reason")
- assertThat(isVisible).isTrue()
- }
+ underTest.setVisible(true, "reason")
+ assertThat(isVisible).isTrue()
+ }
@Test
- fun sceneTransitions() = runTest {
- val transitions by collectLastValue(underTest.transitions)
- assertThat(transitions).isNull()
-
- val initialSceneKey = underTest.currentScene.value.key
- underTest.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
- assertThat(transitions)
- .isEqualTo(
- SceneTransitionModel(
- from = initialSceneKey,
- to = SceneKey.Shade,
+ fun finishedSceneTransitions() =
+ testScope.runTest {
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
)
- )
-
- underTest.setCurrentScene(SceneModel(SceneKey.QuickSettings), "reason")
- assertThat(transitions)
- .isEqualTo(
- SceneTransitionModel(
- from = SceneKey.Shade,
- to = SceneKey.QuickSettings,
+ underTest.setTransitionState(transitionState)
+ var transitionCount = 0
+ val job = launch {
+ underTest
+ .finishedSceneTransitions(
+ from = SceneKey.Shade,
+ to = SceneKey.QuickSettings,
+ )
+ .collect { transitionCount++ }
+ }
+
+ assertThat(transitionCount).isEqualTo(0)
+
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Lockscreen,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
)
- )
- }
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(0)
+
+ underTest.changeScene(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.QuickSettings,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.QuickSettings)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(1)
+
+ underTest.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.QuickSettings,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(1)
+
+ underTest.changeScene(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.QuickSettings,
+ progress = flowOf(0.5f),
+ )
+ runCurrent()
+ underTest.onSceneChanged(SceneModel(SceneKey.QuickSettings), "reason")
+ transitionState.value = ObservableTransitionState.Idle(SceneKey.QuickSettings)
+ runCurrent()
+ assertThat(transitionCount).isEqualTo(2)
- @Test
- fun remoteUserInput() = runTest {
- val remoteUserInput by collectLastValue(underTest.remoteUserInput)
- assertThat(remoteUserInput).isNull()
+ job.cancel()
+ }
- for (input in SceneTestUtils.REMOTE_INPUT_DOWN_GESTURE) {
- underTest.onRemoteUserInput(input)
- assertThat(remoteUserInput).isEqualTo(input)
+ @Test
+ fun remoteUserInput() =
+ testScope.runTest {
+ val remoteUserInput by collectLastValue(underTest.remoteUserInput)
+ assertThat(remoteUserInput).isNull()
+
+ for (input in SceneTestUtils.REMOTE_INPUT_DOWN_GESTURE) {
+ underTest.onRemoteUserInput(input)
+ assertThat(remoteUserInput).isEqualTo(input)
+ }
}
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index bec0b77e6480..45db7a0b17f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -29,15 +29,17 @@ import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -77,59 +79,86 @@ class SceneContainerStartableTest : SysuiTestCase() {
sceneLogger = mock(),
)
- @Before
- fun setUp() {
- prepareState()
- }
-
@Test
fun hydrateVisibility_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentDesiredSceneKey by
+ collectLastValue(sceneInteractor.desiredScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isFeatureEnabled = true,
- isDeviceUnlocked = true,
- initialSceneKey = SceneKey.Gone,
- )
- assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ val transitionStateFlow =
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentDesiredSceneKey).isEqualTo(SceneKey.Gone)
assertThat(isVisible).isTrue()
underTest.start()
-
assertThat(isVisible).isFalse()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
+ assertThat(isVisible).isTrue()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Shade)
+ assertThat(isVisible).isTrue()
+
+ sceneInteractor.changeScene(SceneModel(SceneKey.Gone), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Shade,
+ toScene = SceneKey.Gone,
+ progress = flowOf(0.5f),
+ )
assertThat(isVisible).isTrue()
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Gone)
+ assertThat(isVisible).isFalse()
}
@Test
fun hydrateVisibility_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentDesiredSceneKey by
+ collectLastValue(sceneInteractor.desiredScene.map { it.key })
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isFeatureEnabled = false,
- isDeviceUnlocked = true,
- initialSceneKey = SceneKey.Lockscreen,
- )
- assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ val transitionStateFlow =
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentDesiredSceneKey).isEqualTo(SceneKey.Gone)
assertThat(isVisible).isTrue()
underTest.start()
+
assertThat(isVisible).isTrue()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Gone), "reason")
+ sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value =
+ ObservableTransitionState.Transition(
+ fromScene = SceneKey.Gone,
+ toScene = SceneKey.Shade,
+ progress = flowOf(0.5f),
+ )
assertThat(isVisible).isTrue()
- sceneInteractor.setCurrentScene(SceneModel(SceneKey.Shade), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(SceneKey.Shade)
assertThat(isVisible).isTrue()
}
@Test
fun switchToLockscreenWhenDeviceLocks_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = true,
@@ -146,7 +175,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceLocks_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -163,7 +192,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -180,7 +209,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromBouncerToGoneWhenDeviceUnlocked_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -197,7 +226,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOn() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = true,
@@ -214,7 +243,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOff() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isBypassEnabled = false,
@@ -231,7 +260,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOff_bypassOn() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isBypassEnabled = true,
@@ -248,7 +277,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
isDeviceUnlocked = false,
@@ -265,7 +294,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToLockscreenWhenDeviceSleepsLocked_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
isDeviceUnlocked = false,
@@ -282,6 +311,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateSystemUiState() =
testScope.runTest {
+ val transitionStateFlow = prepareState()
underTest.start()
runCurrent()
clearInvocations(sysUiState)
@@ -294,9 +324,16 @@ class SceneContainerStartableTest : SysuiTestCase() {
SceneKey.QuickSettings,
)
.forEachIndexed { index, sceneKey ->
- sceneInteractor.setCurrentScene(SceneModel(sceneKey), "reason")
+ sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
+ runCurrent()
+ verify(sysUiState, times(index)).commitUpdate(Display.DEFAULT_DISPLAY)
+
+ sceneInteractor.onSceneChanged(SceneModel(sceneKey), "reason")
runCurrent()
+ verify(sysUiState, times(index)).commitUpdate(Display.DEFAULT_DISPLAY)
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
+ runCurrent()
verify(sysUiState, times(index + 1)).commitUpdate(Display.DEFAULT_DISPLAY)
}
}
@@ -304,7 +341,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNone_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
initialSceneKey = SceneKey.Lockscreen,
@@ -321,7 +358,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNotNone_featureEnabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = true,
initialSceneKey = SceneKey.Lockscreen,
@@ -338,7 +375,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun switchToGoneWhenDeviceStartsToWakeUp_authMethodNone_featureDisabled() =
testScope.runTest {
- val currentSceneKey by collectLastValue(sceneInteractor.currentScene.map { it.key })
+ val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
prepareState(
isFeatureEnabled = false,
initialSceneKey = SceneKey.Lockscreen,
@@ -358,17 +395,27 @@ class SceneContainerStartableTest : SysuiTestCase() {
isBypassEnabled: Boolean = false,
initialSceneKey: SceneKey? = null,
authenticationMethod: AuthenticationMethodModel? = null,
- ) {
+ ): MutableStateFlow<ObservableTransitionState> {
featureFlags.set(Flags.SCENE_CONTAINER, isFeatureEnabled)
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
- initialSceneKey?.let { sceneInteractor.setCurrentScene(SceneModel(it), "reason") }
+ val transitionStateFlow =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(SceneKey.Lockscreen)
+ )
+ sceneInteractor.setTransitionState(transitionStateFlow)
+ initialSceneKey?.let {
+ transitionStateFlow.value = ObservableTransitionState.Idle(it)
+ sceneInteractor.changeScene(SceneModel(it), "reason")
+ sceneInteractor.onSceneChanged(SceneModel(it), "reason")
+ }
authenticationMethod?.let {
authenticationRepository.setAuthenticationMethod(authenticationMethod)
authenticationRepository.setLockscreenEnabled(
authenticationMethod != AuthenticationMethodModel.None
)
}
+ return transitionStateFlow
}
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 9f3b12bd2042..da6c42694666 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -69,7 +69,8 @@ class SceneContainerViewModelTest : SysuiTestCase() {
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- underTest.setCurrentScene(SceneModel(SceneKey.Shade))
+ underTest.onSceneChanged(SceneModel(SceneKey.Shade))
+
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Shade))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index d9301604c67f..7443097a2628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -78,7 +78,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -91,7 +91,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene)
+ val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
index 1bf431b4ea13..1c8dac14b089 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.pipeline.wifi.data.repository
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.ACTIVITY_DEFAULT
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryHelper.ACTIVITY_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index fef042be65a8..2dbeb7aa7e90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -489,6 +489,26 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
+ fun wifiNetwork_neverHasHotspot() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiInfo =
+ mock<WifiInfo>().apply {
+ whenever(this.ssid).thenReturn(SSID)
+ whenever(this.isPrimary).thenReturn(true)
+ }
+ val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
+
+ getNetworkCallback()
+ .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo))
+
+ assertThat(latest is WifiNetworkModel.Active).isTrue()
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
+ }
+
+ @Test
fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiNetwork)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
index 7002cbb6ab21..9959e00fd3f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt
@@ -18,13 +18,18 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod
import android.net.wifi.WifiManager
import android.net.wifi.WifiManager.UNKNOWN_SSID
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.util.concurrency.FakeExecutor
@@ -34,8 +39,13 @@ import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
+import com.android.wifitrackerlib.HotspotNetworkEntry
+import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
import com.android.wifitrackerlib.MergedCarrierEntry
import com.android.wifitrackerlib.WifiEntry
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN
+import com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE
import com.android.wifitrackerlib.WifiPickerTracker
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -45,6 +55,7 @@ import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
+import org.mockito.Mockito.verify
/**
* Note: Most of these tests are duplicates of [WifiRepositoryImplTest] tests.
@@ -57,10 +68,25 @@ import org.junit.Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
- private lateinit var underTest: WifiRepositoryViaTrackerLib
+ // Using lazy means that the class will only be constructed once it's fetched. Because the
+ // repository internally sets some values on construction, we need to set up some test
+ // parameters (like feature flags) *before* construction. Using lazy allows us to do that setup
+ // inside each test case without needing to manually recreate the repository.
+ private val underTest: WifiRepositoryViaTrackerLib by lazy {
+ WifiRepositoryViaTrackerLib(
+ featureFlags,
+ testScope.backgroundScope,
+ executor,
+ wifiPickerTrackerFactory,
+ wifiManager,
+ logger,
+ tableLogger,
+ )
+ }
private val executor = FakeExecutor(FakeSystemClock())
private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock())
+ private val featureFlags = FakeFeatureFlags()
private val tableLogger = mock<TableLogBuffer>()
private val wifiManager =
mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) }
@@ -74,12 +100,21 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
@Before
fun setUp() {
+ featureFlags.set(Flags.INSTANT_TETHER, false)
whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor)))
.thenReturn(wifiPickerTracker)
- underTest = createRepo()
}
@Test
+ fun wifiPickerTrackerCreation_scansDisabled() =
+ testScope.runTest {
+ collectLastValue(underTest.wifiNetwork)
+ testScope.runCurrent()
+
+ verify(wifiPickerTracker).disableScanning()
+ }
+
+ @Test
fun isWifiEnabled_enabled_true() =
testScope.runTest {
val latest by collectLastValue(underTest.isWifiEnabled)
@@ -238,7 +273,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.level).thenReturn(3)
- whenever(this.ssid).thenReturn(SSID)
+ whenever(this.title).thenReturn(TITLE)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -246,7 +281,240 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(latest is WifiNetworkModel.Active).isTrue()
val latestActive = latest as WifiNetworkModel.Active
assertThat(latestActive.level).isEqualTo(3)
- assertThat(latestActive.ssid).isEqualTo(SSID)
+ assertThat(latestActive.ssid).isEqualTo(TITLE)
+ }
+
+ @Test
+ fun accessPointInfo_alwaysFalse() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(3)
+ whenever(this.title).thenReturn(TITLE)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest is WifiNetworkModel.Active).isTrue()
+ val latestActive = latest as WifiNetworkModel.Active
+ assertThat(latestActive.isPasspointAccessPoint).isFalse()
+ assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse()
+ assertThat(latestActive.passpointProviderFriendlyName).isNull()
+ }
+
+ @Test
+ fun wifiNetwork_unreachableLevel_inactiveNetwork() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(WIFI_LEVEL_UNREACHABLE)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+ }
+
+ @Test
+ fun wifiNetwork_levelTooHigh_inactiveNetwork() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(WIFI_LEVEL_MAX + 1)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+ }
+
+ @Test
+ fun wifiNetwork_levelTooLow_inactiveNetwork() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(WIFI_LEVEL_MIN - 1)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest).isEqualTo(WifiNetworkModel.Inactive)
+ }
+
+ @Test
+ fun wifiNetwork_levelIsMax_activeNetworkWithMaxLevel() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(WIFI_LEVEL_MAX)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
+ assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MAX)
+ }
+
+ @Test
+ fun wifiNetwork_levelIsMin_activeNetworkWithMinLevel() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.level).thenReturn(WIFI_LEVEL_MIN)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat(latest).isInstanceOf(WifiNetworkModel.Active::class.java)
+ assertThat((latest as WifiNetworkModel.Active).level).isEqualTo(WIFI_LEVEL_MIN)
+ }
+
+ @Test
+ fun wifiNetwork_notHotspot_none() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry =
+ mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(true) }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_unknown() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.UNKNOWN)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_phone() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.PHONE)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_tablet() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.TABLET)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_laptop() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.LAPTOP)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_watch() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.WATCH)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_auto() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.AUTO)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_invalid() =
+ testScope.runTest {
+ featureFlags.set(Flags.INSTANT_TETHER, true)
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(1234)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.INVALID)
+ }
+
+ @Test
+ fun wifiNetwork_hotspot_flagOff_valueNotUsed() =
+ testScope.runTest {
+ // WHEN the flag is off
+ featureFlags.set(Flags.INSTANT_TETHER, false)
+
+ val latest by collectLastValue(underTest.wifiNetwork)
+
+ val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+
+ // THEN NONE is always used, even if the wifi entry does have a hotspot device type
+ assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
+ .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
}
@Test
@@ -258,6 +526,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
mock<MergedCarrierEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.level).thenReturn(3)
+ whenever(this.subscriptionId).thenReturn(567)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -265,7 +534,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
val latestMerged = latest as WifiNetworkModel.CarrierMerged
assertThat(latestMerged.level).isEqualTo(3)
- // numberOfLevels = maxSignalLevel + 1
+ assertThat(latestMerged.subscriptionId).isEqualTo(567)
}
@Test
@@ -288,30 +557,23 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(latestMerged.numberOfLevels).isEqualTo(6)
}
- /* TODO(b/292534484): Re-enable this test once WifiTrackerLib gives us the subscription ID.
@Test
fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiNetwork)
- val wifiInfo =
- mock<WifiInfo>().apply {
- whenever(this.isPrimary).thenReturn(true)
- whenever(this.isCarrierMerged).thenReturn(true)
+ val wifiEntry =
+ mock<MergedCarrierEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
}
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
- getNetworkCallback()
- .onCapabilitiesChanged(
- NETWORK,
- createWifiNetworkCapabilities(wifiInfo),
- )
+ getCallback().onWifiEntriesChanged()
assertThat(latest).isInstanceOf(WifiNetworkModel.Invalid::class.java)
}
- */
-
@Test
fun wifiNetwork_notValidated_networkNotValidated() =
testScope.runTest {
@@ -382,7 +644,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.level).thenReturn(3)
- whenever(this.ssid).thenReturn("AB")
+ whenever(this.title).thenReturn("AB")
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -397,7 +659,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.level).thenReturn(4)
- whenever(this.ssid).thenReturn("CD")
+ whenever(this.title).thenReturn("CD")
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(newWifiEntry)
getCallback().onWifiEntriesChanged()
@@ -430,12 +692,12 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
val wifiEntry =
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.ssid).thenReturn(SSID)
+ whenever(this.title).thenReturn(TITLE)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
- assertThat((latest as WifiNetworkModel.Active).ssid).isEqualTo(SSID)
+ assertThat((latest as WifiNetworkModel.Active).ssid).isEqualTo(TITLE)
// WHEN we lose our current network
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(null)
@@ -480,7 +742,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
whenever(this.level).thenReturn(1)
- whenever(this.ssid).thenReturn(SSID)
+ whenever(this.title).thenReturn(TITLE)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -488,7 +750,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(latest1 is WifiNetworkModel.Active).isTrue()
val latest1Active = latest1 as WifiNetworkModel.Active
assertThat(latest1Active.level).isEqualTo(1)
- assertThat(latest1Active.ssid).isEqualTo(SSID)
+ assertThat(latest1Active.ssid).isEqualTo(TITLE)
// WHEN we add a second subscriber after having already emitted a value
val latest2 by collectLastValue(underTest.wifiNetwork)
@@ -497,7 +759,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(latest2 is WifiNetworkModel.Active).isTrue()
val latest2Active = latest2 as WifiNetworkModel.Active
assertThat(latest2Active.level).isEqualTo(1)
- assertThat(latest2Active.ssid).isEqualTo(SSID)
+ assertThat(latest2Active.ssid).isEqualTo(TITLE)
}
@Test
@@ -541,40 +803,32 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
}
- /* TODO(b/292534484): Re-enable this test once WifiTrackerLib gives us the subscription ID.
- @Test
- fun isWifiConnectedWithValidSsid_invalidNetwork_false() =
- testScope.runTest {
- collectLastValue(underTest.wifiNetwork)
-
- val wifiInfo =
- mock<WifiInfo>().apply {
- whenever(this.isPrimary).thenReturn(true)
- whenever(this.isCarrierMerged).thenReturn(true)
- whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
- }
-
- getNetworkCallback()
- .onCapabilitiesChanged(
- NETWORK,
- createWifiNetworkCapabilities(wifiInfo),
- )
- testScope.runCurrent()
+ @Test
+ fun isWifiConnectedWithValidSsid_invalidNetwork_false() =
+ testScope.runTest {
+ collectLastValue(underTest.wifiNetwork)
- assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
- }
+ val wifiEntry =
+ mock<MergedCarrierEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.subscriptionId).thenReturn(INVALID_SUBSCRIPTION_ID)
+ }
+ whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
+ getCallback().onWifiEntriesChanged()
+ testScope.runCurrent()
- */
+ assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
+ }
@Test
- fun isWifiConnectedWithValidSsid_activeNetwork_nullSsid_false() =
+ fun isWifiConnectedWithValidSsid_activeNetwork_nullTitle_false() =
testScope.runTest {
collectLastValue(underTest.wifiNetwork)
val wifiEntry =
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.ssid).thenReturn(null)
+ whenever(this.title).thenReturn(null)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -584,14 +838,14 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
}
@Test
- fun isWifiConnectedWithValidSsid_activeNetwork_unknownSsid_false() =
+ fun isWifiConnectedWithValidSsid_activeNetwork_unknownTitle_false() =
testScope.runTest {
collectLastValue(underTest.wifiNetwork)
val wifiEntry =
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.ssid).thenReturn(UNKNOWN_SSID)
+ whenever(this.title).thenReturn(UNKNOWN_SSID)
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -601,14 +855,14 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
}
@Test
- fun isWifiConnectedWithValidSsid_activeNetwork_validSsid_true() =
+ fun isWifiConnectedWithValidSsid_activeNetwork_validTitle_true() =
testScope.runTest {
collectLastValue(underTest.wifiNetwork)
val wifiEntry =
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.ssid).thenReturn("fakeSsid")
+ whenever(this.title).thenReturn("fakeSsid")
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -626,7 +880,7 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
val wifiEntry =
mock<WifiEntry>().apply {
whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.ssid).thenReturn("fakeSsid")
+ whenever(this.title).thenReturn("fakeSsid")
}
whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
getCallback().onWifiEntriesChanged()
@@ -643,23 +897,74 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() {
assertThat(underTest.isWifiConnectedWithValidSsid()).isFalse()
}
+ @Test
+ fun wifiActivity_callbackGivesNone_activityFlowHasNone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiActivity)
+
+ getTrafficStateCallback()
+ .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE)
+
+ assertThat(latest)
+ .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
+ }
+
+ @Test
+ fun wifiActivity_callbackGivesIn_activityFlowHasIn() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiActivity)
+
+ getTrafficStateCallback()
+ .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN)
+
+ assertThat(latest)
+ .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
+ }
+
+ @Test
+ fun wifiActivity_callbackGivesOut_activityFlowHasOut() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiActivity)
+
+ getTrafficStateCallback()
+ .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT)
+
+ assertThat(latest)
+ .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
+ }
+
+ @Test
+ fun wifiActivity_callbackGivesInout_activityFlowHasInAndOut() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.wifiActivity)
+
+ getTrafficStateCallback()
+ .onStateChanged(WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT)
+
+ assertThat(latest)
+ .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
+ }
+
private fun getCallback(): WifiPickerTracker.WifiPickerTrackerCallback {
testScope.runCurrent()
return callbackCaptor.value
}
- private fun createRepo(): WifiRepositoryViaTrackerLib {
- return WifiRepositoryViaTrackerLib(
- testScope.backgroundScope,
- executor,
- wifiPickerTrackerFactory,
- wifiManager,
- logger,
- tableLogger,
- )
+ private fun getTrafficStateCallback(): WifiManager.TrafficStateCallback {
+ testScope.runCurrent()
+ val callbackCaptor = argumentCaptor<WifiManager.TrafficStateCallback>()
+ verify(wifiManager).registerTrafficStateCallback(any(), callbackCaptor.capture())
+ return callbackCaptor.value!!
+ }
+
+ private fun createHotspotWithType(@DeviceType type: Int): HotspotNetworkEntry {
+ return mock<HotspotNetworkEntry>().apply {
+ whenever(this.isPrimaryNetwork).thenReturn(true)
+ whenever(this.deviceType).thenReturn(type)
+ }
}
private companion object {
- const val SSID = "AB"
+ const val TITLE = "AB"
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
index 4e0c309512e8..ba035bec340c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
@@ -136,7 +136,8 @@ class WifiNetworkModelTest : SysuiTestCase() {
networkId = 5,
isValidated = true,
level = 3,
- ssid = "Test SSID"
+ ssid = "Test SSID",
+ hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.LAPTOP,
)
activeNetwork.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
@@ -146,6 +147,7 @@ class WifiNetworkModelTest : SysuiTestCase() {
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
+ assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "LAPTOP"))
}
@Test
fun logDiffs_activeToInactive_resetsAllActiveFields() {
@@ -165,6 +167,7 @@ class WifiNetworkModelTest : SysuiTestCase() {
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
+ assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "null"))
}
@Test
@@ -175,7 +178,8 @@ class WifiNetworkModelTest : SysuiTestCase() {
networkId = 5,
isValidated = true,
level = 3,
- ssid = "Test SSID"
+ ssid = "Test SSID",
+ hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.AUTO,
)
val prevVal =
WifiNetworkModel.CarrierMerged(
@@ -191,6 +195,7 @@ class WifiNetworkModelTest : SysuiTestCase() {
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
+ assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "AUTO"))
}
@Test
fun logDiffs_activeToCarrierMerged_logsAllFields() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 62087df8c238..507267e2d185 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -97,7 +97,7 @@ class SceneTestUtils(
fun fakeSceneContainerRepository(
containerConfig: SceneContainerConfig = fakeSceneContainerConfig(),
): SceneContainerRepository {
- return SceneContainerRepository(containerConfig)
+ return SceneContainerRepository(applicationScope(), containerConfig)
}
fun fakeSceneKeys(): List<SceneKey> {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
index 1403cea1c625..3fd11a1db96f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeDisplayTracker.kt
@@ -26,7 +26,7 @@ class FakeDisplayTracker constructor(val context: Context) : DisplayTracker {
override var defaultDisplayId: Int = Display.DEFAULT_DISPLAY
override var allDisplays: Array<Display> = displayManager.displays
- private val displayCallbacks: MutableList<DisplayTracker.Callback> = ArrayList()
+ val displayCallbacks: MutableList<DisplayTracker.Callback> = ArrayList()
private val brightnessCallbacks: MutableList<DisplayTracker.Callback> = ArrayList()
override fun addDisplayChangeCallback(callback: DisplayTracker.Callback, executor: Executor) {
displayCallbacks.add(callback)
@@ -43,12 +43,12 @@ class FakeDisplayTracker constructor(val context: Context) : DisplayTracker {
brightnessCallbacks.remove(callback)
}
- fun setDefaultDisplay(displayId: Int) {
- defaultDisplayId = displayId
+ override fun getDisplay(displayId: Int): Display {
+ return allDisplays.filter { display -> display.displayId == displayId }[0]
}
- fun setDisplays(displays: Array<Display>) {
- allDisplays = displays
+ fun setDefaultDisplay(displayId: Int) {
+ defaultDisplayId = displayId
}
fun triggerOnDisplayAdded(displayId: Int) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 37abe1b1aee3..061b4221ecf7 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -4204,7 +4204,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// We don't send an empty response to IME so that it doesn't cause UI flicker
// on the IME side if it arrives before the input view is finished on the IME.
mInlineSessionController.resetInlineFillUiLocked();
- mCurrentViewId = null;
+
+ if ((viewState.getState() &
+ ViewState.STATE_PENDING_CREATE_INLINE_REQUEST) != 0) {
+ // View was exited before Inline Request sent back, do not set it to
+ // null yet to let onHandleAssistData finish processing
+ } else {
+ mCurrentViewId = null;
+ }
+
mPresentationStatsEventLogger.maybeSetNoPresentationEventReason(
NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED);
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 846283c38327..fc51e2ec0954 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1369,6 +1369,13 @@ public abstract class PackageManagerInternal {
public abstract void setPackageStoppedState(@NonNull String packageName, boolean stopped,
@UserIdInt int userId);
+ /**
+ * Tells PackageManager when a component (except BroadcastReceivers) of the package is used
+ * and the package should get out of stopped state and be enabled.
+ */
+ public abstract void notifyComponentUsed(@NonNull String packageName,
+ @UserIdInt int userId, @NonNull String recentCallingPackage);
+
/** @deprecated For legacy shell command only. */
@Deprecated
public abstract void legacyDumpProfiles(@NonNull String packageName,
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index da2588b12054..4b589885473b 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5116,10 +5116,9 @@ public final class ActiveServices {
r.packageName, r.userId, UsageEvents.Event.APP_COMPONENT_USED);
}
- // Service is now being launched, its package can't be stopped.
try {
- mAm.mPackageManagerInt.setPackageStoppedState(
- r.packageName, false, r.userId);
+ mAm.mPackageManagerInt.notifyComponentUsed(
+ r.packageName, r.userId, r.mRecentCallingPackage);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c1f2f6731e43..a53c2fb44873 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3095,6 +3095,22 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /**
+ * Enforces that the uid of the caller matches the uid of the package.
+ *
+ * @param packageName the name of the package to match uid against.
+ * @param callingUid the uid of the caller.
+ * @throws SecurityException if the calling uid doesn't match uid of the package.
+ */
+ private void enforceCallingPackage(String packageName, int callingUid) {
+ final int userId = UserHandle.getUserId(callingUid);
+ final int packageUid = getPackageManagerInternal().getPackageUid(packageName,
+ /*flags=*/ 0, userId);
+ if (packageUid != callingUid) {
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
+ }
+ }
+
@Override
public void setPackageScreenCompatMode(String packageName, int mode) {
mActivityTaskManager.setPackageScreenCompatMode(packageName, mode);
@@ -13704,13 +13720,16 @@ public class ActivityManagerService extends IActivityManager.Stub
// A backup agent has just come up
@Override
public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ enforceCallingPackage(agentPackageName, callingUid);
+
// Resolve the target user id and enforce permissions.
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null);
if (DEBUG_BACKUP) {
Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
+ " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId
- + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid());
+ + " callingUid = " + callingUid + " uid = " + Process.myUid());
}
synchronized(this) {
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index e26ee9c9d747..65fd54afbbfb 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -505,12 +505,11 @@ public class ContentProviderHelper {
cpr.appInfo.packageName, userId, Event.APP_COMPONENT_USED);
}
- // Content provider is now in use, its package can't be stopped.
try {
checkTime(startTime,
"getContentProviderImpl: before set stopped state");
- mService.mPackageManagerInt.setPackageStoppedState(
- cpr.appInfo.packageName, false, userId);
+ mService.mPackageManagerInt.notifyComponentUsed(
+ cpr.appInfo.packageName, userId, callingPackage);
checkTime(startTime, "getContentProviderImpl: after set stopped state");
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index 0af9b2b4c26a..575db01931e6 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -88,11 +88,14 @@
"file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
"name": "FrameworksServicesTests",
"options": [
- { "include-filter": "com.android.server.am.BatteryStatsServiceTest" },
- { "include-filter": "com.android.server.power.stats.BatteryStatsTests" }
+ { "include-filter": "com.android.server.am.BatteryStatsServiceTest" }
]
},
{
+ "file_patterns": ["Battery[^/]*\\.java", "MeasuredEnergy[^/]*\\.java"],
+ "name": "PowerStatsTests"
+ },
+ {
"file_patterns": ["Broadcast.*"],
"name": "FrameworksMockingServicesTests",
"options": [
@@ -111,27 +114,14 @@
]
},
{
- "name": "CtsUsageStatsTestCases",
+ "name": "CtsBRSTestCases",
"file_patterns": [
"ActivityManagerService\\.java",
"BroadcastQueue\\.java"
],
"options": [
- {
- "include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
- },
- {
- "exclude-annotation": "androidx.test.filters.MediumTest"
- },
- {
- "exclude-annotation": "androidx.test.filters.LargeTest"
- }
+ { "exclude-annotation": "androidx.test.filters.FlakyTest" },
+ { "exclude-annotation": "org.junit.Ignore" }
]
}
],
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 279aaf9d3253..1898b8015462 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -1308,10 +1308,13 @@ public class BiometricService extends SystemService {
.getString(R.string.biometric_dialog_default_subtitle));
} else if (hasEligibleFingerprintSensor) {
promptInfo.setSubtitle(getContext()
- .getString(R.string.biometric_dialog_fingerprint_subtitle));
+ .getString(R.string.fingerprint_dialog_default_subtitle));
} else if (hasEligibleFaceSensor) {
promptInfo.setSubtitle(getContext()
- .getString(R.string.biometric_dialog_face_subtitle));
+ .getString(R.string.face_dialog_default_subtitle));
+ } else {
+ promptInfo.setSubtitle(getContext()
+ .getString(R.string.screen_lock_dialog_default_subtitle));
}
}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 595b2e4113b2..74b7f0866b54 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -1750,13 +1750,6 @@ public class LocationManagerService extends ILocationManager.Stub implements
}
@Override
- public void sendNiResponse(int notifId, int userResponse) {
- if (mGnssManagerService != null) {
- mGnssManagerService.sendNiResponse(notifId, userResponse);
- }
- }
-
- @Override
public @Nullable LocationTime getGnssTimeMillis() {
LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
if (gpsManager == null) {
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index ed5c1306733e..e97a12a83b1f 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -62,7 +62,6 @@ import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.location.GnssCapabilities;
import android.location.GnssStatus;
-import android.location.INetInitiatedListener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
@@ -109,7 +108,6 @@ import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.HexDump;
import com.android.server.FgThread;
@@ -396,7 +394,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT);
mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec());
mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1;
- mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
if (mGnssVisibilityControl != null) {
mGnssVisibilityControl.onConfigurationUpdated(mGnssConfiguration);
}
@@ -465,7 +462,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
};
mNIHandler = new GpsNetInitiatedHandler(context,
- mNetInitiatedListener,
emergencyCallCallback,
mSuplEsEnabled);
// Trigger PSDS data download when the network comes up after booting.
@@ -1435,96 +1431,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
updateRequirements();
}
- //=============================================================
- // NI Client support
- //=============================================================
- private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
- // Sends a response for an NI request to HAL.
- @Override
- public boolean sendNiResponse(int notificationId, int userResponse) {
- // TODO Add Permission check
-
- if (DEBUG) {
- Log.d(TAG, "sendNiResponse, notifId: " + notificationId
- + ", response: " + userResponse);
- }
- mGnssNative.sendNiResponse(notificationId, userResponse);
-
- FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED,
- FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_RESPONSE,
- notificationId,
- /* niType= */ 0,
- /* needNotify= */ false,
- /* needVerify= */ false,
- /* privacyOverride= */ false,
- /* timeout= */ 0,
- /* defaultResponse= */ 0,
- /* requestorId= */ null,
- /* text= */ null,
- /* requestorIdEncoding= */ 0,
- /* textEncoding= */ 0,
- mSuplEsEnabled,
- isGpsEnabled(),
- userResponse);
-
- return true;
- }
- };
-
- public INetInitiatedListener getNetInitiatedListener() {
- return mNetInitiatedListener;
- }
-
- /** Reports a NI notification. */
- private void reportNiNotification(int notificationId, int niType, int notifyFlags, int timeout,
- int defaultResponse, String requestorId, String text, int requestorIdEncoding,
- int textEncoding) {
- Log.i(TAG, "reportNiNotification: entered");
- Log.i(TAG, "notificationId: " + notificationId
- + ", niType: " + niType
- + ", notifyFlags: " + notifyFlags
- + ", timeout: " + timeout
- + ", defaultResponse: " + defaultResponse);
-
- Log.i(TAG, "requestorId: " + requestorId
- + ", text: " + text
- + ", requestorIdEncoding: " + requestorIdEncoding
- + ", textEncoding: " + textEncoding);
-
- GpsNiNotification notification = new GpsNiNotification();
-
- notification.notificationId = notificationId;
- notification.niType = niType;
- notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
- notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
- notification.privacyOverride =
- (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
- notification.timeout = timeout;
- notification.defaultResponse = defaultResponse;
- notification.requestorId = requestorId;
- notification.text = text;
- notification.requestorIdEncoding = requestorIdEncoding;
- notification.textEncoding = textEncoding;
-
- mNIHandler.handleNiNotification(notification);
- FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED,
- FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_REQUEST,
- notification.notificationId,
- notification.niType,
- notification.needNotify,
- notification.needVerify,
- notification.privacyOverride,
- notification.timeout,
- notification.defaultResponse,
- notification.requestorId,
- notification.text,
- notification.requestorIdEncoding,
- notification.textEncoding,
- mSuplEsEnabled,
- isGpsEnabled(),
- /* userResponse= */ 0);
- }
-
private void demandUtcTimeInjection() {
if (DEBUG) Log.d(TAG, "demandUtcTimeInjection");
postWithWakeLockHeld(mNetworkTimeHelper::demandUtcTimeInjection);
@@ -1829,14 +1735,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
@Override
- public void onReportNiNotification(int notificationId, int niType, int notifyFlags,
- int timeout, int defaultResponse, String requestorId, String text,
- int requestorIdEncoding, int textEncoding) {
- reportNiNotification(notificationId, niType, notifyFlags, timeout,
- defaultResponse, requestorId, text, requestorIdEncoding, textEncoding);
- }
-
- @Override
public void onRequestSetID(@GnssNative.AGpsCallbacks.AgpsSetIdFlags int flags) {
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index c962bc4c20d8..133704d11b08 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -38,7 +38,6 @@ import android.location.LocationManager;
import android.location.util.identity.CallerIdentity;
import android.os.BatteryStats;
import android.os.Binder;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
@@ -275,17 +274,6 @@ public class GnssManagerService {
}
/**
- * Send Ni Response, indicating a location request initiated by a network carrier.
- */
- public void sendNiResponse(int notifId, int userResponse) {
- try {
- mGnssLocationProvider.getNetInitiatedListener().sendNiResponse(notifId, userResponse);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Dump info for debugging.
*/
public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
index 7618419ab0e4..bdd488581817 100644
--- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
+++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
@@ -284,9 +284,6 @@ public class GnssNative {
/** Callbacks for notifications. */
public interface NotificationCallbacks {
- void onReportNiNotification(int notificationId, int niType, int notifyFlags,
- int timeout, int defaultResponse, String requestorId, String text,
- int requestorIdEncoding, int textEncoding);
void onReportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId,
byte responseType, boolean inEmergencyMode, boolean isCachedLocation);
@@ -933,14 +930,6 @@ public class GnssNative {
}
/**
- * Send a network initiated respnse.
- */
- public void sendNiResponse(int notificationId, int userResponse) {
- Preconditions.checkState(mRegistered);
- mGnssHal.sendNiResponse(notificationId, userResponse);
- }
-
- /**
* Request an eventual update of GNSS power statistics.
*/
public void requestPowerStats() {
@@ -1244,16 +1233,6 @@ public class GnssNative {
}
@NativeEntryPoint
- void reportNiNotification(int notificationId, int niType, int notifyFlags,
- int timeout, int defaultResponse, String requestorId, String text,
- int requestorIdEncoding, int textEncoding) {
- Binder.withCleanCallingIdentity(
- () -> mNotificationCallbacks.onReportNiNotification(notificationId, niType,
- notifyFlags, timeout, defaultResponse, requestorId, text,
- requestorIdEncoding, textEncoding));
- }
-
- @NativeEntryPoint
void requestSetID(int flags) {
Binder.withCleanCallingIdentity(() -> mAGpsCallbacks.onRequestSetID(flags));
}
@@ -1488,10 +1467,6 @@ public class GnssNative {
return native_is_gnss_visibility_control_supported();
}
- protected void sendNiResponse(int notificationId, int userResponse) {
- native_send_ni_response(notificationId, userResponse);
- }
-
protected void requestPowerStats() {
native_request_power_stats();
}
@@ -1648,8 +1623,6 @@ public class GnssNative {
private static native boolean native_is_gnss_visibility_control_supported();
- private static native void native_send_ni_response(int notificationId, int userResponse);
-
// power stats APIs
private static native void native_request_power_stats();
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index 4e7521070132..82587c529e29 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -745,6 +745,13 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
mService.setPackageStoppedState(snapshot(), packageName, stopped, userId);
}
+ @Override
+ public void notifyComponentUsed(@NonNull String packageName,
+ @UserIdInt int userId, @NonNull String recentCallingPackage) {
+ mService.notifyComponentUsed(snapshot(), packageName, userId,
+ recentCallingPackage);
+ }
+
@NonNull
@Override
@Deprecated
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 770ed8b40d2e..dc42644b04c0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4582,6 +4582,13 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
}
+ void notifyComponentUsed(@NonNull Computer snapshot, @NonNull String packageName,
+ @UserIdInt int userId, @NonNull String recentCallingPackage) {
+ PackageManagerService.this
+ .setPackageStoppedState(snapshot, packageName, false /* stopped */,
+ userId);
+ }
+
public class IPackageManagerImpl extends IPackageManagerBase {
public IPackageManagerImpl() {
diff --git a/services/core/java/com/android/server/power/TEST_MAPPING b/services/core/java/com/android/server/power/TEST_MAPPING
index 8374997e3fa2..19086a184068 100644
--- a/services/core/java/com/android/server/power/TEST_MAPPING
+++ b/services/core/java/com/android/server/power/TEST_MAPPING
@@ -17,15 +17,6 @@
]
},
{
- "name": "FrameworksServicesTests",
- "options": [
- {"include-filter": "com.android.server.power"},
- {"exclude-filter": "com.android.server.power.BatteryStatsTests"},
- {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"}
- ]
- },
- {
"name": "PowerServiceTests",
"options": [
{"include-filter": "com.android.server.power"},
@@ -48,15 +39,13 @@
{
"name": "FrameworksServicesTests",
"options": [
- {"include-filter": "com.android.server.power"},
- {"exclude-filter": "com.android.server.power.BatteryStatsTests"}
+ {"include-filter": "com.android.server.power"}
]
},
{
"name": "PowerServiceTests",
"options": [
{"include-filter": "com.android.server.power"},
- {"exclude-filter": "com.android.server.power.BatteryStatsTests"},
{"exclude-annotation": "org.junit.Ignore"}
]
}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 1a91d252c431..8dcf3e06330f 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -304,7 +304,8 @@ public final class HintManagerService extends SystemService {
return mService;
}
- private boolean checkTidValid(int uid, int tgid, int [] tids) {
+ // returns the first invalid tid or null if not found
+ private Integer checkTidValid(int uid, int tgid, int [] tids) {
// Make sure all tids belongs to the same UID (including isolated UID),
// tids can belong to different application processes.
List<Integer> isolatedPids = null;
@@ -326,19 +327,24 @@ public final class HintManagerService extends SystemService {
if (isolatedPids == null) {
// To avoid deadlock, do not call into AMS if the call is from system.
if (uid == Process.SYSTEM_UID) {
- return false;
+ return threadId;
}
isolatedPids = mAmInternal.getIsolatedProcesses(uid);
if (isolatedPids == null) {
- return false;
+ return threadId;
}
}
if (isolatedPids.contains(pidOfThreadId)) {
continue;
}
- return false;
+ return threadId;
}
- return true;
+ return null;
+ }
+
+ private String formatTidCheckErrMsg(int callingUid, int[] tids, Integer invalidTid) {
+ return "Tid" + invalidTid + " from list " + Arrays.toString(tids)
+ + " doesn't belong to the calling application" + callingUid;
}
@VisibleForTesting
@@ -356,8 +362,11 @@ public final class HintManagerService extends SystemService {
final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
final long identity = Binder.clearCallingIdentity();
try {
- if (!checkTidValid(callingUid, callingTgid, tids)) {
- throw new SecurityException("Some tid doesn't belong to the application");
+ final Integer invalidTid = checkTidValid(callingUid, callingTgid, tids);
+ if (invalidTid != null) {
+ final String errMsg = formatTidCheckErrMsg(callingUid, tids, invalidTid);
+ Slogf.w(TAG, errMsg);
+ throw new SecurityException(errMsg);
}
long halSessionPtr = mNativeWrapper.halCreateHintSession(callingTgid, callingUid,
@@ -561,8 +570,11 @@ public final class HintManagerService extends SystemService {
final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
final long identity = Binder.clearCallingIdentity();
try {
- if (!checkTidValid(callingUid, callingTgid, tids)) {
- throw new SecurityException("Some tid doesn't belong to the application.");
+ final Integer invalidTid = checkTidValid(callingUid, callingTgid, tids);
+ if (invalidTid != null) {
+ final String errMsg = formatTidCheckErrMsg(callingUid, tids, invalidTid);
+ Slogf.w(TAG, errMsg);
+ throw new SecurityException(errMsg);
}
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 83949ccae366..d8cc8d386424 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -86,7 +86,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.Slog;
@@ -1325,14 +1324,12 @@ class TaskFragment extends WindowContainer<WindowContainer> {
}
}
- // Launching this app's activity, make sure the app is no longer
- // considered stopped.
try {
mTaskSupervisor.getActivityMetricsLogger()
.notifyBeforePackageUnstopped(next.packageName);
- mAtmService.getPackageManager().setPackageStoppedState(
- next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
- } catch (RemoteException e1) {
+ mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(
+ next.packageName, next.mUserId,
+ next.packageName); /* TODO: Verify if correct userid */
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ next.packageName + ": " + e);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e1de05cf6c7c..11c40d7bcd9b 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -69,7 +69,6 @@
static jclass class_gnssPowerStats;
-static jmethodID method_reportNiNotification;
static jmethodID method_reportGnssPowerStats;
static jmethodID method_reportNfwNotification;
static jmethodID method_isInEmergencySession;
@@ -92,8 +91,6 @@ using android::hardware::hidl_death_recipient;
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V1_0::IGnssNavigationMessage;
using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
-using android::hardware::gnss::V1_0::IGnssNi;
-using android::hardware::gnss::V1_0::IGnssNiCallback;
using android::hardware::gnss::V1_0::IGnssXtra;
using android::hardware::gnss::V1_0::IGnssXtraCallback;
using android::hardware::gnss::V2_0::ElapsedRealtimeFlags;
@@ -127,7 +124,6 @@ using IGnssConfigurationAidl = android::hardware::gnss::IGnssConfiguration;
using GnssLocationAidl = android::hardware::gnss::GnssLocation;
using IGnssAntennaInfoAidl = android::hardware::gnss::IGnssAntennaInfo;
-sp<IGnssNi> gnssNiIface = nullptr;
sp<IGnssPowerIndication> gnssPowerIndicationIface = nullptr;
std::unique_ptr<android::gnss::GnssHal> gnssHal = nullptr;
@@ -195,42 +191,6 @@ Status GnssPowerIndicationCallback::gnssPowerStatsCb(const GnssPowerStats& data)
return Status::ok();
}
-/*
- * GnssNiCallback implements callback methods required by the IGnssNi interface.
- */
-struct GnssNiCallback : public IGnssNiCallback {
- Return<void> niNotifyCb(const IGnssNiCallback::GnssNiNotification& notification)
- override;
-};
-
-Return<void> GnssNiCallback::niNotifyCb(
- const IGnssNiCallback::GnssNiNotification& notification) {
- JNIEnv* env = getJniEnv();
- jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
- jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
-
- if (requestorId && text) {
- env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
- notification.notificationId, notification.niType,
- notification.notifyFlags, notification.timeoutSec,
- notification.defaultResponse, requestorId, text,
- notification.requestorIdEncoding,
- notification.notificationIdEncoding);
- } else {
- ALOGE("%s: OOM Error\n", __func__);
- }
-
- if (requestorId) {
- env->DeleteLocalRef(requestorId);
- }
-
- if (text) {
- env->DeleteLocalRef(text);
- }
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- return Void();
-}
-
/* Initializes the GNSS service handle. */
static void android_location_gnss_hal_GnssNative_set_gps_service_handle() {
gnssHal = std::make_unique<gnss::GnssHal>();
@@ -242,10 +202,6 @@ static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jc
android_location_gnss_hal_GnssNative_set_gps_service_handle();
// Cache methodIDs and class IDs.
-
- method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
- "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
-
method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
"(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
method_reportGnssPowerStats =
@@ -305,7 +261,6 @@ static void android_location_gnss_hal_GnssNative_init_once(JNIEnv* env, jobject
gnssAntennaInfoIface = gnssHal->getGnssAntennaInfoInterface();
gnssMeasurementCorrectionsIface = gnssHal->getMeasurementCorrectionsInterface();
gnssDebugIface = gnssHal->getGnssDebugInterface();
- gnssNiIface = gnssHal->getGnssNiInterface();
gnssConfigurationIface = gnssHal->getGnssConfigurationInterface();
gnssGeofencingIface = gnssHal->getGnssGeofenceInterface();
gnssBatchingIface = gnssHal->getGnssBatchingInterface();
@@ -376,15 +331,6 @@ static jboolean android_location_gnss_hal_GnssNative_init(JNIEnv* /* env */, jcl
ALOGI("Unable to initialize IGnssGeofencing interface.");
}
- // Set IGnssNi.hal callback.
- sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
- if (gnssNiIface != nullptr) {
- auto status = gnssNiIface->setCallback(gnssNiCbIface);
- checkHidlReturn(status, "IGnssNi setCallback() failed.");
- } else {
- ALOGI("Unable to initialize IGnssNi interface.");
- }
-
// Set IAGnssRil callback.
if (agnssRilIface == nullptr ||
!agnssRilIface->setCallback(std::make_unique<gnss::AGnssRilCallback>())) {
@@ -592,18 +538,6 @@ static void android_location_gnss_hal_GnssNative_set_agps_server(JNIEnv* env, jc
}
}
-static void android_location_gnss_hal_GnssNative_send_ni_response(JNIEnv* /* env */, jclass,
- jint notifId, jint response) {
- if (gnssNiIface == nullptr) {
- ALOGE("%s: IGnssNi interface not available.", __func__);
- return;
- }
-
- auto result = gnssNiIface->respond(notifId,
- static_cast<IGnssNiCallback::GnssUserResponseType>(response));
- checkHidlReturn(result, "IGnssNi respond() failed.");
-}
-
static jstring android_location_gnss_hal_GnssNative_get_internal_state(JNIEnv* env, jclass) {
/*
* TODO: Create a jobject to represent GnssDebug.
@@ -987,8 +921,6 @@ static const JNINativeMethod sLocationProviderMethods[] = {
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_agps_server)},
{"native_inject_ni_supl_message_data", "([BII)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_ni_supl_message_data)},
- {"native_send_ni_response", "(II)V",
- reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_send_ni_response)},
{"native_get_internal_state", "()Ljava/lang/String;",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_get_internal_state)},
{"native_is_gnss_visibility_control_supported", "()Z",
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
index 2d962acfe665..1a8b12a00714 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
@@ -686,9 +686,6 @@ public final class FakeGnssHal extends GnssNative.GnssHal {
}
@Override
- protected void sendNiResponse(int notificationId, int userResponse) {}
-
- @Override
protected void requestPowerStats() {
Objects.requireNonNull(mGnssNative).reportGnssPowerStats(mState.mPowerStats);
}
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
new file mode 100644
index 000000000000..05acd9b8eeb1
--- /dev/null
+++ b/services/tests/powerstatstests/Android.bp
@@ -0,0 +1,52 @@
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "PowerStatsTests",
+
+ // Include all test java files.
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ "services.core",
+ "coretests-aidl",
+ "platformprotosnano",
+ "junit",
+ "truth-prebuilt",
+ "androidx.test.runner",
+ "androidx.test.ext.junit",
+ "androidx.test.ext.truth",
+ "androidx.test.uiautomator_uiautomator",
+ "mockito-target-minus-junit4",
+ "servicestests-utils",
+ ],
+
+ libs: [
+ "android.test.base",
+ ],
+
+ resource_dirs: ["res/"],
+
+ data: [
+ ":BstatsTestApp",
+ ],
+
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+
+ platform_apis: true,
+
+ certificate: "platform",
+
+ dxflags: ["--multi-dex"],
+
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/services/tests/powerstatstests/AndroidManifest.xml b/services/tests/powerstatstests/AndroidManifest.xml
new file mode 100644
index 000000000000..d3a88d2bc38c
--- /dev/null
+++ b/services/tests/powerstatstests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.powerstatstests">
+
+ <uses-permission android:name="android.permission.BATTERY_STATS" />
+ <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
+
+ <queries>
+ <package android:name="com.android.coretests.apps.bstatstestapp" />
+ </queries>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.powerstatstests"
+ android:label="BatteryStats and PowerStats Services Tests"/>
+</manifest>
diff --git a/services/tests/powerstatstests/AndroidTest.xml b/services/tests/powerstatstests/AndroidTest.xml
new file mode 100644
index 000000000000..79b07e812b28
--- /dev/null
+++ b/services/tests/powerstatstests/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs Power Stats Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="PowerStatsTests.apk" />
+ <option name="test-file-name" value="BstatsTestApp.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="PowerStatsTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.powerstatstests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
+ </test>
+</configuration>
diff --git a/core/tests/coretests/BstatsTestApp/Android.bp b/services/tests/powerstatstests/BstatsTestApp/Android.bp
index c82da9e7b449..c82da9e7b449 100644
--- a/core/tests/coretests/BstatsTestApp/Android.bp
+++ b/services/tests/powerstatstests/BstatsTestApp/Android.bp
diff --git a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml b/services/tests/powerstatstests/BstatsTestApp/AndroidManifest.xml
index fcb1e71cc3f5..fcb1e71cc3f5 100644
--- a/core/tests/coretests/BstatsTestApp/AndroidManifest.xml
+++ b/services/tests/powerstatstests/BstatsTestApp/AndroidManifest.xml
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java
index 2601f3571b98..2601f3571b98 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java
+++ b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/BaseCmdReceiver.java
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java
index d192fbd66c89..c731e536d032 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java
+++ b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/Common.java
@@ -15,8 +15,6 @@
*/
package com.android.coretests.apps.bstatstestapp;
-import com.android.frameworks.coretests.aidl.ICmdCallback;
-
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
@@ -24,6 +22,8 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
+import com.android.frameworks.coretests.aidl.ICmdCallback;
+
public class Common {
private static final String EXTRA_KEY_CMD_RECEIVER = "cmd_receiver";
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java
index 892f60e8530f..892f60e8530f 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java
+++ b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/IsolatedTestService.java
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java
index 5c551d54b4d5..5c551d54b4d5 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java
+++ b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestActivity.java
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
index 0cd0643ee8c0..0cd0643ee8c0 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
+++ b/services/tests/powerstatstests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS b/services/tests/powerstatstests/OWNERS
index 12f13ea63db0..9ed0e051738d 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/OWNERS
+++ b/services/tests/powerstatstests/OWNERS
@@ -1 +1,4 @@
+# Bug component: 987260
+
+include /BATTERY_STATS_OWNERS
include /services/core/java/com/android/server/powerstats/OWNERS
diff --git a/services/tests/powerstatstests/TEST_MAPPING b/services/tests/powerstatstests/TEST_MAPPING
new file mode 100644
index 000000000000..e1eb1e4fc0db
--- /dev/null
+++ b/services/tests/powerstatstests/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit": [
+ {
+ "name": "PowerStatsTests",
+ "options": [
+ {"include-filter": "com.android.server.power.stats"},
+ {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {"exclude-annotation": "org.junit.Ignore"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "PowerStatsTests",
+ "options": [
+ {"include-filter": "com.android.server.power.stats"},
+ {"exclude-annotation": "org.junit.Ignore"}
+ ]
+ }
+ ]
+}
diff --git a/services/tests/servicestests/res/xml/irq_device_map_1.xml b/services/tests/powerstatstests/res/xml/irq_device_map_1.xml
index 1f1a77b437ab..1f1a77b437ab 100644
--- a/services/tests/servicestests/res/xml/irq_device_map_1.xml
+++ b/services/tests/powerstatstests/res/xml/irq_device_map_1.xml
diff --git a/services/tests/servicestests/res/xml/irq_device_map_2.xml b/services/tests/powerstatstests/res/xml/irq_device_map_2.xml
index 508c98d871da..508c98d871da 100644
--- a/services/tests/servicestests/res/xml/irq_device_map_2.xml
+++ b/services/tests/powerstatstests/res/xml/irq_device_map_2.xml
diff --git a/services/tests/servicestests/res/xml/irq_device_map_3.xml b/services/tests/powerstatstests/res/xml/irq_device_map_3.xml
index fd55428c48df..fd55428c48df 100644
--- a/services/tests/servicestests/res/xml/irq_device_map_3.xml
+++ b/services/tests/powerstatstests/res/xml/irq_device_map_3.xml
diff --git a/services/tests/servicestests/res/xml/power_profile_test_legacy_modem.xml b/services/tests/powerstatstests/res/xml/power_profile_test_legacy_modem.xml
index 5335f9640738..5335f9640738 100644
--- a/services/tests/servicestests/res/xml/power_profile_test_legacy_modem.xml
+++ b/services/tests/powerstatstests/res/xml/power_profile_test_legacy_modem.xml
diff --git a/services/tests/servicestests/res/xml/power_profile_test_modem_calculator.xml b/services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator.xml
index f57bc0f70b5d..f57bc0f70b5d 100644
--- a/services/tests/servicestests/res/xml/power_profile_test_modem_calculator.xml
+++ b/services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator.xml
diff --git a/services/tests/servicestests/res/xml/power_profile_test_modem_calculator_multiactive.xml b/services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator_multiactive.xml
index 4f5e674c60f5..4f5e674c60f5 100644
--- a/services/tests/servicestests/res/xml/power_profile_test_modem_calculator_multiactive.xml
+++ b/services/tests/powerstatstests/res/xml/power_profile_test_modem_calculator_multiactive.xml
diff --git a/services/tests/servicestests/res/xml/power_profile_test_modem_default.xml b/services/tests/powerstatstests/res/xml/power_profile_test_modem_default.xml
index ab016fbb1f5d..ab016fbb1f5d 100644
--- a/services/tests/servicestests/res/xml/power_profile_test_modem_default.xml
+++ b/services/tests/powerstatstests/res/xml/power_profile_test_modem_default.xml
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java
index 319a280d10cc..319a280d10cc 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java
index fb367b24168e..fb367b24168e 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/AudioPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
index 4ea0805ffaa7..4ea0805ffaa7 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryChargeCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
index 5a2d2e3d33fd..5a2d2e3d33fd 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryExternalStatsWorkerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
index 4d3fcb611f24..4d3fcb611f24 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBackgroundStatsTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
index 3f101a96d36c..3f101a96d36c 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsBinderCallStatsTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCounterTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCounterTest.java
index 326639c54495..326639c54495 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCounterTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCounterTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
index 55ffa1a15a6b..55ffa1a15a6b 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsCpuTimesTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java
index d6acf8da7431..d6acf8da7431 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDualTimerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java
index 99520cd6fbad..99520cd6fbad 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsDurationTimerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
index 4fde73bd8408..4fde73bd8408 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 48ba765c3968..48ba765c3968 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index f20f061230e2..5ebc6ca3f558 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -267,7 +267,7 @@ public class BatteryStatsImplTest {
final long[][] delta3 = {
{98545, 95768795, 76586, 548945, 57846},
{788876, 586, 578459, 8776984, 9578923},
- {3049509483598l, 4597834, 377654, 94589035, 7854},
+ {3049509483598L, 4597834, 377654, 94589035, 7854},
{9493, 784, 99895, 8974893, 9879843}
};
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsManagerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
index 7ae111711b6b..7ae111711b6b 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
index 88b9522d4cb1..88b9522d4cb1 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java
index a0fb631812f4..a0fb631812f4 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsResetTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java
index 784d673ed3f0..ee68bf8ae53c 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSamplingTimerTest.java
@@ -1,17 +1,17 @@
/*
* Copyright (C) 2016 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
+ * 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
+ * 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.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.server.power.stats;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSensorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSensorTest.java
index b8f0ce3456f8..9c70f376ca14 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsSensorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsSensorTest.java
@@ -1,17 +1,17 @@
/*
* Copyright (C) 2016 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
+ * 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
+ * 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.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.server.power.stats;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsServTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsServTest.java
index 200eb1d0ad15..200eb1d0ad15 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsServTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsServTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java
index fcae42a76f1b..18a366c178fd 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsStopwatchTimerTest.java
@@ -1,17 +1,17 @@
/*
* Copyright (C) 2017 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
+ * 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
+ * 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.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.server.power.stats;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java
index 5b47423f0d59..5b47423f0d59 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimeBaseTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimerTest.java
index 14c5c5db5c1c..14c5c5db5c1c 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTimerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsTimerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
index face849620d7..face849620d7 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsUserLifecycleTests.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index 5df0acb65249..5df0acb65249 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index 534aa89e1699..534aa89e1699 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
index b846e3a36656..b846e3a36656 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
index 266a22632a6d..266a22632a6d 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java
index 4d4337c16757..4d4337c16757 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
index ccace40bb056..ccace40bb056 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BstatsCpuTimesValidationTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
index 5fce32f0598a..5fce32f0598a 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java
index 888bc623f669..888bc623f669 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java
index 245faaf15cc8..245faaf15cc8 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
index 28f4799656b7..28f4799656b7 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/EnergyConsumerSnapshotTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java
index 0f85fdc375fb..0f85fdc375fb 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/FlashlightPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java
index 3f2a6d04c1e6..3f2a6d04c1e6 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java
index 3d150af711f1..3d150af711f1 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/IdlePowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
index c0f3c775ffe5..2edfc8e1e408 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/KernelWakelockReaderTest.java
@@ -1,17 +1,17 @@
/*
* Copyright (C) 2016 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
+ * 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
+ * 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.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.server.power.stats;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java
index 2e962c364ed2..2e962c364ed2 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterArrayTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterTest.java
index 0eac625051fc..0eac625051fc 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/LongSamplingCounterTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/LongSamplingCounterTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java
index 2cce449c6c05..2cce449c6c05 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MemoryPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
index d3ec0d7e3f6e..888a1688c2a1 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
@@ -46,7 +46,7 @@ import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.frameworks.servicestests.R;
+import com.android.frameworks.powerstatstests.R;
import com.google.common.collect.Range;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 6d3f1f27b572..6d3f1f27b572 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockClock.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MockClock.java
index 5e57cc36797b..5e57cc36797b 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockClock.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MockClock.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/OWNERS b/services/tests/powerstatstests/src/com/android/server/power/stats/OWNERS
index 9a7db1cb4fe4..9a7db1cb4fe4 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/OWNERS
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java
index 372307985f04..372307985f04 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java
index 474527040839..474527040839 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
index 80cbe0da402e..80cbe0da402e 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServerCpuThreadReaderTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
index 4dae2d548057..4dae2d548057 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/SystemServicePowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/UserPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/UserPowerCalculatorTest.java
index f14745ef2daa..f14745ef2daa 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/UserPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/UserPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java
index f578aa3b46be..f578aa3b46be 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/VideoPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java
index f1961855f12f..f1961855f12f 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WakelockPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java
index 113be8b19518..113be8b19518 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerCalculatorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java
index b81b776019f9..0dc836ba0400 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java
@@ -34,7 +34,7 @@ import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.frameworks.servicestests.R;
+import com.android.frameworks.powerstatstests.R;
import com.android.server.power.stats.wakeups.CpuWakeupStats.Wakeup;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java
index 47a8f49e7025..9af288496bb9 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/IrqDeviceMapTest.java
@@ -23,7 +23,7 @@ import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.frameworks.servicestests.R;
+import com.android.frameworks.powerstatstests.R;
import com.android.internal.util.CollectionUtils;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java
index 99bc25abc4a1..99bc25abc4a1 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/wakeups/WakingActivityHistoryTest.java
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java b/services/tests/powerstatstests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java
index 99621460f360..99621460f360 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/powerstats/IntervalRandomNoiseGeneratorTest.java
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 2ffe4aacda73..2ffe4aacda73 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 3272ce6a5865..92ff7ab86247 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -112,7 +112,6 @@ android_test {
},
data: [
- ":BstatsTestApp",
":JobTestApp",
":SimpleServiceTestApp1",
":SimpleServiceTestApp2",
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index fbb0ca108ecd..b1d50399416a 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -28,7 +28,6 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="install-arg" value="-t" />
- <option name="test-file-name" value="BstatsTestApp.apk" />
<option name="test-file-name" value="FrameworksServicesTests.apk" />
<option name="test-file-name" value="JobTestApp.apk" />
<option name="test-file-name" value="SuspendTestApp.apk" />
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index fc62e75b7d59..e79ac0986dc8 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -16,6 +16,7 @@
package com.android.server.biometrics;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_CREDENTIAL;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricManager.Authenticators;
@@ -116,9 +117,9 @@ public class BiometricServiceTest {
private static final String ERROR_LOCKOUT = "error_lockout";
private static final String FACE_SUBTITLE = "face_subtitle";
private static final String FINGERPRINT_SUBTITLE = "fingerprint_subtitle";
+ private static final String CREDENTIAL_SUBTITLE = "credential_subtitle";
private static final String DEFAULT_SUBTITLE = "default_subtitle";
-
private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty";
private static final int SENSOR_ID_FINGERPRINT = 0;
@@ -143,6 +144,8 @@ public class BiometricServiceTest {
@Mock
IBiometricAuthenticator mFaceAuthenticator;
@Mock
+ IBiometricAuthenticator mCredentialAuthenticator;
+ @Mock
ITrustManager mTrustManager;
@Mock
DevicePolicyManager mDevicePolicyManager;
@@ -196,10 +199,12 @@ public class BiometricServiceTest {
.thenReturn(ERROR_NOT_RECOGNIZED);
when(mResources.getString(R.string.biometric_error_user_canceled))
.thenReturn(ERROR_USER_CANCELED);
- when(mContext.getString(R.string.biometric_dialog_face_subtitle))
+ when(mContext.getString(R.string.face_dialog_default_subtitle))
.thenReturn(FACE_SUBTITLE);
- when(mContext.getString(R.string.biometric_dialog_fingerprint_subtitle))
+ when(mContext.getString(R.string.fingerprint_dialog_default_subtitle))
.thenReturn(FINGERPRINT_SUBTITLE);
+ when(mContext.getString(R.string.screen_lock_dialog_default_subtitle))
+ .thenReturn(CREDENTIAL_SUBTITLE);
when(mContext.getString(R.string.biometric_dialog_default_subtitle))
.thenReturn(DEFAULT_SUBTITLE);
@@ -292,7 +297,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL);
+ Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_CREDENTIAL),
@@ -312,7 +318,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL);
+ Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertNotNull(mBiometricService.mAuthSession);
@@ -338,7 +345,8 @@ public class BiometricServiceTest {
mBiometricService.onStart();
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -357,7 +365,8 @@ public class BiometricServiceTest {
mFingerprintAuthenticator);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -370,7 +379,8 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- Authenticators.BIOMETRIC_STRONG);
+ Authenticators.BIOMETRIC_STRONG, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -429,7 +439,8 @@ public class BiometricServiceTest {
mFingerprintAuthenticator);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -441,9 +452,9 @@ public class BiometricServiceTest {
public void testAuthenticateFace_shouldShowSubtitleForFace() throws Exception {
setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(FACE_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
@@ -453,9 +464,9 @@ public class BiometricServiceTest {
public void testAuthenticateFingerprint_shouldShowSubtitleForFingerprint() throws Exception {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(FINGERPRINT_SUBTITLE,
@@ -463,6 +474,19 @@ public class BiometricServiceTest {
}
@Test
+ public void testAuthenticateFingerprint_shouldShowSubtitleForCredential() throws Exception {
+ setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL);
+
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ true /* deviceCredentialAllowed */);
+ waitForIdle();
+
+ assertEquals(CREDENTIAL_SUBTITLE,
+ mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
+ }
+
+ @Test
public void testAuthenticateBothFpAndFace_shouldShowDefaultSubtitle() throws Exception {
final int[] modalities = new int[] {
TYPE_FINGERPRINT,
@@ -476,9 +500,9 @@ public class BiometricServiceTest {
setupAuthForMultiple(modalities, strengths);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */,
- null);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, true /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(DEFAULT_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
@@ -492,7 +516,8 @@ public class BiometricServiceTest {
// Disabled in user settings receives onError
when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_NONE),
@@ -506,7 +531,8 @@ public class BiometricServiceTest {
anyInt() /* modality */, anyInt() /* userId */))
.thenReturn(true);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
final byte[] HAT = generateRandomHAT();
@@ -524,7 +550,8 @@ public class BiometricServiceTest {
anyInt() /* modality */, anyInt() /* userId */))
.thenReturn(false);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
SENSOR_ID_FACE,
@@ -552,7 +579,8 @@ public class BiometricServiceTest {
throws Exception {
// Start testing the happy path
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// Creates a pending auth session with the correct initial states
@@ -632,7 +660,8 @@ public class BiometricServiceTest {
.thenReturn(true);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
true /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
+ false /* useDefaultSubtitle*/, false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
@@ -702,7 +731,8 @@ public class BiometricServiceTest {
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
true /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(anyInt() /* modality */,
@@ -754,7 +784,8 @@ public class BiometricServiceTest {
false /* requireConfirmation */, null /* authenticators */);
invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */,
- null /* authenticators */);
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
@@ -887,7 +918,8 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
@@ -920,8 +952,9 @@ public class BiometricServiceTest {
public void testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()
throws Exception {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
mBiometricService.mAuthSession.mSensorReceiver.onError(
@@ -957,8 +990,9 @@ public class BiometricServiceTest {
setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
.thenReturn(lockoutMode);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// Modality and error are sent
@@ -996,8 +1030,9 @@ public class BiometricServiceTest {
when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
.thenReturn(lockoutMode);
when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
- invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, null /* authenticators */);
+ invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
+ null /* authenticators */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
// The lockout error should be sent, instead of ERROR_NONE_ENROLLED. See b/286923477.
@@ -1014,7 +1049,8 @@ public class BiometricServiceTest {
.thenReturn(LockoutTracker.LOCKOUT_PERMANENT);
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG);
+ Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
@@ -1503,7 +1539,8 @@ public class BiometricServiceTest {
assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
invokeCanAuthenticate(mBiometricService, authenticators));
long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
- false /* requireConfirmation */, authenticators);
+ false /* requireConfirmation */, authenticators, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
verify(mReceiver1).onError(
eq(TYPE_FINGERPRINT),
@@ -1539,7 +1576,8 @@ public class BiometricServiceTest {
invokeCanAuthenticate(mBiometricService, authenticators));
requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
- authenticators);
+ authenticators, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */);
waitForIdle();
assertTrue(Utils.isCredentialRequested(mBiometricService.mAuthSession.mPromptInfo));
verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
@@ -1749,6 +1787,11 @@ public class BiometricServiceTest {
mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, strength,
mFaceAuthenticator);
}
+
+ if ((modality & TYPE_CREDENTIAL) != 0) {
+ when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
+ .thenReturn(true);
+ }
}
// TODO: Reduce duplicated code, currently we cannot start the BiometricService in setUp() for
@@ -1799,7 +1842,8 @@ public class BiometricServiceTest {
Integer authenticators) throws Exception {
// Request auth, creates a pending session
final long requestId = invokeAuthenticate(
- service, receiver, requireConfirmation, authenticators);
+ service, receiver, requireConfirmation, authenticators,
+ false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
waitForIdle();
startPendingAuthSession(mBiometricService);
@@ -1827,7 +1871,8 @@ public class BiometricServiceTest {
private static long invokeAuthenticate(IBiometricService.Stub service,
IBiometricServiceReceiver receiver, boolean requireConfirmation,
- Integer authenticators) throws Exception {
+ Integer authenticators, boolean useDefaultSubtitle,
+ boolean deviceCredentialAllowed) throws Exception {
return service.authenticate(
new Binder() /* token */,
0 /* operationId */,
@@ -1835,7 +1880,8 @@ public class BiometricServiceTest {
receiver,
TEST_PACKAGE_NAME /* packageName */,
createTestPromptInfo(requireConfirmation, authenticators,
- false /* checkDevicePolicy */));
+ false /* checkDevicePolicy */, useDefaultSubtitle,
+ deviceCredentialAllowed));
}
private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service,
@@ -1847,16 +1893,19 @@ public class BiometricServiceTest {
receiver,
TEST_PACKAGE_NAME /* packageName */,
createTestPromptInfo(false /* requireConfirmation */, authenticators,
- true /* checkDevicePolicy */));
+ true /* checkDevicePolicy */, false /* useDefaultSubtitle */,
+ false /* deviceCredentialAllowed */));
}
private static PromptInfo createTestPromptInfo(
boolean requireConfirmation,
Integer authenticators,
- boolean checkDevicePolicy) {
+ boolean checkDevicePolicy,
+ boolean useDefaultSubtitle,
+ boolean deviceCredentialAllowed) {
final PromptInfo promptInfo = new PromptInfo();
promptInfo.setConfirmationRequested(requireConfirmation);
- promptInfo.setUseDefaultSubtitle(true);
+ promptInfo.setUseDefaultSubtitle(useDefaultSubtitle);
if (authenticators != null) {
promptInfo.setAuthenticators(authenticators);
@@ -1864,6 +1913,7 @@ public class BiometricServiceTest {
if (checkDevicePolicy) {
promptInfo.setDisallowBiometricsIfPolicyExists(checkDevicePolicy);
}
+ promptInfo.setDeviceCredentialAllowed(deviceCredentialAllowed);
return promptInfo;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
index f834cb24f245..b65a53af56a0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
@@ -138,6 +138,17 @@ class AndroidPackageParsingValidationTest {
R.styleable.AndroidManifestApplication_taskAffinity,
1024
)
+ validateTagAttr(
+ tag,
+ "zygotePreloadName",
+ R.styleable.AndroidManifestApplication_zygotePreloadName,
+ 1024
+ )
+ validateTagAttrComponentName(
+ tag,
+ "zygotePreloadName",
+ R.styleable.AndroidManifestApplication_zygotePreloadName
+ )
validateTagCount("profileable", 100, tag)
validateTagCount("uses-native-library", 100, tag)
validateTagCount("receiver", 1000, tag)
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTests.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTests.java
deleted file mode 100644
index 48290e5ca1ef..000000000000
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsTests.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.power.stats;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
- AmbientDisplayPowerCalculatorTest.class,
- AudioPowerCalculatorTest.class,
- BatteryChargeCalculatorTest.class,
- BatteryExternalStatsWorkerTest.class,
- BatteryStatsCpuTimesTest.class,
- BatteryStatsBackgroundStatsTest.class,
- BatteryStatsBinderCallStatsTest.class,
- BatteryStatsCounterTest.class,
- BatteryStatsDualTimerTest.class,
- BatteryStatsDurationTimerTest.class,
- BatteryStatsHistoryIteratorTest.class,
- BatteryStatsHistoryTest.class,
- BatteryStatsImplTest.class,
- BatteryStatsManagerTest.class,
- BatteryStatsNoteTest.class,
- BatteryStatsSamplingTimerTest.class,
- BatteryStatsSensorTest.class,
- BatteryStatsServTest.class,
- BatteryStatsStopwatchTimerTest.class,
- BatteryStatsTimeBaseTest.class,
- BatteryStatsTimerTest.class,
- BatteryUsageStatsProviderTest.class,
- BatteryUsageStatsTest.class,
- BatteryUsageStatsStoreTest.class,
- BatteryStatsUserLifecycleTests.class,
- BluetoothPowerCalculatorTest.class,
- BstatsCpuTimesValidationTest.class,
- CameraPowerCalculatorTest.class,
- CpuPowerCalculatorTest.class,
- CustomEnergyConsumerPowerCalculatorTest.class,
- FlashlightPowerCalculatorTest.class,
- GnssPowerCalculatorTest.class,
- IdlePowerCalculatorTest.class,
- KernelWakelockReaderTest.class,
- LongSamplingCounterTest.class,
- LongSamplingCounterArrayTest.class,
- EnergyConsumerSnapshotTest.class,
- MobileRadioPowerCalculatorTest.class,
- ScreenPowerCalculatorTest.class,
- SensorPowerCalculatorTest.class,
- SystemServerCpuThreadReaderTest.class,
- SystemServicePowerCalculatorTest.class,
- UserPowerCalculatorTest.class,
- VideoPowerCalculatorTest.class,
- WakelockPowerCalculatorTest.class,
- WifiPowerCalculatorTest.class,
-})
-public class BatteryStatsTests {
-}
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index a3fe6f2876d7..6e845433492b 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -20,22 +20,13 @@
]
},
{
- "name": "CtsUsageStatsTestCases",
+ "name": "CtsBRSTestCases",
"options": [
{
- "include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"
- },
- {
"exclude-annotation": "androidx.test.filters.FlakyTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
- },
- {
- "exclude-annotation": "androidx.test.filters.MediumTest"
- },
- {
- "exclude-annotation": "androidx.test.filters.LargeTest"
+ "exclude-annotation": "org.junit.Ignore"
}
]
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 78b86d398718..5bdcdf4d63ef 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -2661,7 +2661,9 @@ public final class Call {
// remove ourselves from the Phone. Note that we do this after completing all state updates
// so a client can cleanly transition all their UI to the state appropriate for a
// DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
- if (mState == STATE_DISCONNECTED) {
+ // Check if the original state is already disconnected, otherwise onCallRemoved will be
+ // triggered before onCallAdded.
+ if (mState == STATE_DISCONNECTED && stateChanged) {
fireCallDestroyed();
}
}
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 95a8e16ace3d..61e829e75930 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -174,6 +174,9 @@ public final class Phone {
checkCallTree(parcelableCall);
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
fireCallAdded(call);
+ if (call.getState() == Call.STATE_DISCONNECTED) {
+ internalRemoveCall(call);
+ }
} else {
Log.w(this, "Call %s added, but it was already present", call.internalGetCallId());
checkCallTree(parcelableCall);
diff --git a/tests/testables/src/android/testing/TestableResources.java b/tests/testables/src/android/testing/TestableResources.java
index 27d5b66b355e..0ec106e329f6 100644
--- a/tests/testables/src/android/testing/TestableResources.java
+++ b/tests/testables/src/android/testing/TestableResources.java
@@ -15,9 +15,11 @@
package android.testing;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import android.util.SparseArray;
@@ -54,6 +56,16 @@ public class TestableResources {
}
/**
+ * Sets a configuration for {@link #getResources()} to return to allow custom configs to
+ * be set and tested.
+ *
+ * @param configuration the configuration to return from resources.
+ */
+ public void overrideConfiguration(Configuration configuration) {
+ when(mResources.getConfiguration()).thenReturn(configuration);
+ }
+
+ /**
* Sets the return value for the specified resource id.
* <p>
* Since resource ids are unique there is a single addOverride that will override the value