summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java424
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java71
-rw-r--r--apex/statsd/Android.bp4
-rw-r--r--api/current.txt7
-rw-r--r--api/module-lib-current.txt8
-rwxr-xr-xapi/system-current.txt34
-rw-r--r--api/test-current.txt8
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp5
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp7
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h9
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp5
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp9
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h13
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp3
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h21
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp8
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h6
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp11
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h10
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp138
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h9
-rw-r--r--cmds/statsd/tests/metrics/CountMetricProducer_test.cpp19
-rw-r--r--cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp61
-rw-r--r--cmds/statsd/tests/metrics/EventMetricProducer_test.cpp12
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp52
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp117
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp13
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp90
-rw-r--r--core/java/android/app/Notification.java6
-rw-r--r--core/java/android/app/PictureInPictureParams.java49
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java3
-rw-r--r--core/java/android/content/pm/PackageManager.java3
-rw-r--r--core/java/android/os/image/DynamicSystemManager.java13
-rw-r--r--core/java/android/os/image/IDynamicSystemService.aidl7
-rw-r--r--core/java/android/provider/DeviceConfig.java9
-rw-r--r--core/java/android/provider/DocumentsProvider.java25
-rw-r--r--core/java/android/provider/Settings.java32
-rw-r--r--core/java/android/telephony/PhoneStateListener.java31
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java17
-rw-r--r--core/java/android/view/ViewRootImpl.java35
-rw-r--r--core/java/android/view/WindowManager.java6
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java77
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java22
-rw-r--r--core/java/com/android/internal/policy/DecorContext.java16
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl3
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl6
-rw-r--r--core/java/com/android/internal/util/LatencyTracker.java50
-rw-r--r--core/jni/android_media_AudioSystem.cpp83
-rw-r--r--core/jni/android_view_KeyEvent.cpp1
-rw-r--r--core/jni/android_view_MotionEvent.cpp5
-rw-r--r--core/proto/android/providers/settings/config.proto8
-rw-r--r--core/proto/android/providers/settings/global.proto2
-rw-r--r--core/proto/android/server/windowmanagerservice.proto1
-rw-r--r--core/res/res/values/attrs.xml12
-rw-r--r--core/tests/coretests/src/android/view/ViewRootImplTest.java11
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java122
-rw-r--r--core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java11
-rw-r--r--data/keyboards/Generic.kcm26
-rw-r--r--libs/WindowManager/Shell/res/anim/forced_resizable_enter.xml (renamed from packages/SystemUI/res/anim/forced_resizable_enter.xml)0
-rw-r--r--libs/WindowManager/Shell/res/anim/forced_resizable_exit.xml (renamed from packages/SystemUI/res/anim/forced_resizable_exit.xml)0
-rw-r--r--libs/WindowManager/Shell/res/layout/divider.xml (renamed from packages/SystemUI/res/layout/divider.xml)0
-rw-r--r--libs/WindowManager/Shell/res/layout/docked_stack_divider.xml (renamed from packages/SystemUI/res/layout/docked_stack_divider.xml)8
-rw-r--r--libs/WindowManager/Shell/res/layout/forced_resizable_activity.xml (renamed from packages/SystemUI/res/layout/forced_resizable_activity.xml)0
-rw-r--r--libs/WindowManager/Shell/res/values-land/dimens.xml21
-rw-r--r--libs/WindowManager/Shell/res/values-land/styles.xml35
-rw-r--r--libs/WindowManager/Shell/res/values-sw600dp/config.xml25
-rw-r--r--libs/WindowManager/Shell/res/values/colors.xml25
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml3
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml6
-rw-r--r--libs/WindowManager/Shell/res/values/ids.xml7
-rw-r--r--libs/WindowManager/Shell/res/values/strings.xml35
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml49
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java)134
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java)25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java)68
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java)5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java)6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java)35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java)16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java)6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java)24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java)8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java)2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreen.java)2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java)4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java)2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java)3
-rw-r--r--media/java/android/media/AudioDeviceAttributes.java19
-rw-r--r--media/java/android/media/AudioDeviceInfo.java37
-rw-r--r--[-rwxr-xr-x]media/java/android/media/AudioManager.java343
-rw-r--r--media/java/android/media/AudioSystem.java146
-rwxr-xr-xmedia/java/android/media/IAudioService.aidl13
-rw-r--r--media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl31
-rw-r--r--media/java/android/media/MediaRecorder.java26
-rw-r--r--media/java/android/media/MediaTranscodeManager.java37
-rw-r--r--media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh5
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java255
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java294
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java503
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java2
-rw-r--r--non-updatable-api/current.txt6
-rw-r--r--non-updatable-api/module-lib-current.txt8
-rw-r--r--non-updatable-api/system-current.txt34
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java2
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java2
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java2
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java26
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java18
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java7
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/README.md4
-rw-r--r--packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml36
-rw-r--r--packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml36
-rw-r--r--packages/SystemUI/res/layout-land-television/volume_dialog_row.xml1
-rw-r--r--packages/SystemUI/res/layout/media_view.xml3
-rw-r--r--packages/SystemUI/res/values-mcc310-mnc004/strings.xml22
-rw-r--r--packages/SystemUI/res/values-mcc311-mnc480/strings.xml22
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml3
-rw-r--r--packages/SystemUI/res/values-television/config.xml1
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml8
-rw-r--r--packages/SystemUI/res/values/ids.xml7
-rw-r--r--packages/SystemUI/res/values/strings.xml35
-rw-r--r--packages/SystemUI/res/values/styles.xml32
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java437
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java340
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java146
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java62
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java136
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java76
-rw-r--r--services/core/java/com/android/server/DynamicSystemService.java10
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java87
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java43
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java45
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java77
-rw-r--r--[-rwxr-xr-x]services/core/java/com/android/server/audio/AudioService.java89
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java34
-rw-r--r--[-rwxr-xr-x]services/core/java/com/android/server/audio/MediaFocusControl.java0
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/Face10.java30
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java5
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java24
-rw-r--r--services/core/java/com/android/server/hdmi/ActiveSourceAction.java2
-rw-r--r--services/core/java/com/android/server/hdmi/ActiveSourceHandler.java8
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java12
-rwxr-xr-xservices/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java59
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java3
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java12
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java16
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java17
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java28
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java13
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java113
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java39
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java63
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java107
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java606
-rw-r--r--services/core/java/com/android/server/wm/OWNERS1
-rw-r--r--services/core/java/com/android/server/wm/Task.java47
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java20
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java51
-rw-r--r--services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java106
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java79
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java36
-rw-r--r--telephony/api/system-current.txt16
-rw-r--r--telephony/java/android/telephony/PhysicalChannelConfig.java61
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java43
-rw-r--r--tests/SilkFX/Android.bp6
-rw-r--r--tests/SilkFX/AndroidManifest.xml3
-rw-r--r--tests/SilkFX/res/drawable-hdpi/background1.jpegbin0 -> 200459 bytes
-rw-r--r--tests/SilkFX/res/drawable-hdpi/background2.jpegbin0 -> 110703 bytes
-rw-r--r--tests/SilkFX/res/drawable-hdpi/background3.jpegbin0 -> 318853 bytes
-rw-r--r--tests/SilkFX/res/drawable-hdpi/noise.pngbin0 -> 494875 bytes
-rw-r--r--tests/SilkFX/res/layout/activity_glass.xml281
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/Main.kt4
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt134
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt128
-rw-r--r--wifi/api/current.txt1
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java49
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSpecifier.java31
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java31
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java12
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl1
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java13
-rw-r--r--wifi/tests/src/android/net/wifi/FakeKeys.java413
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java105
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java78
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java20
251 files changed, 6411 insertions, 3226 deletions
diff --git a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
index b1dbb28c9501..d07ed375b2ab 100644
--- a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
+++ b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
@@ -51,13 +51,14 @@ public class MyContentCaptureService extends ContentCaptureService {
sServiceWatcher = null;
}
- public static void clearServiceWatcher() {
- if (sServiceWatcher != null) {
- if (sServiceWatcher.mReadyToClear) {
- sServiceWatcher.mService = null;
+ private static void clearServiceWatcher() {
+ final ServiceWatcher sw = sServiceWatcher;
+ if (sw != null) {
+ if (sw.mReadyToClear) {
+ sw.mService = null;
sServiceWatcher = null;
} else {
- sServiceWatcher.mReadyToClear = true;
+ sw.mReadyToClear = true;
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 6c3398f91db1..d8386b5f1153 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -21,14 +21,12 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -63,11 +61,10 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
-import android.util.KeyValueListParser;
import android.util.MutableLong;
import android.util.Pair;
import android.util.Slog;
@@ -856,7 +853,7 @@ public class DeviceIdleController extends SystemService
* global Settings. Any access to this class or its fields should be done while
* holding the DeviceIdleController lock.
*/
- public final class Constants extends ContentObserver {
+ public final class Constants implements DeviceConfig.OnPropertiesChangedListener {
// Key names stored in the settings value.
private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
= "light_after_inactive_to";
@@ -884,15 +881,15 @@ public class DeviceIdleController extends SystemService
private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
private static final String KEY_IDLE_FACTOR = "idle_factor";
private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
+ // TODO(166121524): update flag names
private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
"max_temp_app_whitelist_duration";
private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
"mms_temp_app_whitelist_duration";
private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
"sms_temp_app_whitelist_duration";
- // TODO(b/124466289): update value to match the name
- private static final String KEY_NOTIFICATION_ALLOWLIST_DURATION =
- "notification_whitelist_duration";
+ private static final String KEY_NOTIFICATION_ALLOWLIST_DURATION_MS =
+ "notification_allowlist_duration_ms";
/**
* Whether to wait for the user to unlock the device before causing screen-on to
* exit doze. Default = true
@@ -903,52 +900,106 @@ public class DeviceIdleController extends SystemService
private static final String KEY_PRE_IDLE_FACTOR_SHORT =
"pre_idle_factor_short";
+ private static final long DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT =
+ !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L;
+ private static final long DEFAULT_LIGHT_PRE_IDLE_TIMEOUT =
+ !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L;
+ private static final long DEFAULT_LIGHT_IDLE_TIMEOUT =
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L;
+ private static final float DEFAULT_LIGHT_IDLE_FACTOR = 2f;
+ private static final long DEFAULT_LIGHT_MAX_IDLE_TIMEOUT =
+ !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
+ private static final long DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET =
+ !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L;
+ private static final long DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET =
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L;
+ private static final long DEFAULT_MIN_LIGHT_MAINTENANCE_TIME =
+ !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L;
+ private static final long DEFAULT_MIN_DEEP_MAINTENANCE_TIME =
+ !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L;
+ private static final long DEFAULT_INACTIVE_TIMEOUT =
+ (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10);
+ private static final long DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY =
+ (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10);
+ private static final long DEFAULT_SENSING_TIMEOUT =
+ !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L;
+ private static final long DEFAULT_LOCATING_TIMEOUT =
+ !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L;
+ private static final float DEFAULT_LOCATION_ACCURACY = 20f;
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT =
+ !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L;
+ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT =
+ (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10);
+ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY =
+ (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10);
+ private static final long DEFAULT_IDLE_PENDING_TIMEOUT =
+ !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L;
+ private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT =
+ !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L;
+ private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f;
+ private static final long DEFAULT_QUICK_DOZE_DELAY_TIMEOUT =
+ !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L;
+ private static final long DEFAULT_IDLE_TIMEOUT =
+ !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L;
+ private static final long DEFAULT_MAX_IDLE_TIMEOUT =
+ !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L;
+ private static final float DEFAULT_IDLE_FACTOR = 2f;
+ private static final long DEFAULT_MIN_TIME_TO_ALARM =
+ !COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L;
+ private static final long DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L;
+ private static final long DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION = 60 * 1000L;
+ private static final long DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION = 20 * 1000L;
+ private static final long DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS = 30 * 1000L;
+ private static final boolean DEFAULT_WAIT_FOR_UNLOCK = true;
+ private static final float DEFAULT_PRE_IDLE_FACTOR_LONG = 1.67f;
+ private static final float DEFAULT_PRE_IDLE_FACTOR_SHORT = .33f;
+
/**
* This is the time, after becoming inactive, that we go in to the first
* light-weight idle mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
*/
- public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
+ public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
/**
* This is amount of time we will wait from the point where we decide we would
* like to go idle until we actually do, while waiting for jobs and other current
* activity to finish.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
*/
- public long LIGHT_PRE_IDLE_TIMEOUT;
+ public long LIGHT_PRE_IDLE_TIMEOUT = DEFAULT_LIGHT_PRE_IDLE_TIMEOUT;
/**
* This is the initial time that we will run in idle maintenance mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_IDLE_TIMEOUT
*/
- public long LIGHT_IDLE_TIMEOUT;
+ public long LIGHT_IDLE_TIMEOUT = DEFAULT_LIGHT_IDLE_TIMEOUT;
/**
* Scaling factor to apply to the light idle mode time each time we complete a cycle.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_IDLE_FACTOR
*/
- public float LIGHT_IDLE_FACTOR;
+ public float LIGHT_IDLE_FACTOR = DEFAULT_LIGHT_IDLE_FACTOR;
/**
* This is the maximum time we will run in idle maintenance mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
*/
- public long LIGHT_MAX_IDLE_TIMEOUT;
+ public long LIGHT_MAX_IDLE_TIMEOUT = DEFAULT_LIGHT_MAX_IDLE_TIMEOUT;
/**
* This is the minimum amount of time we want to make available for maintenance mode
* when lightly idling. That is, we will always have at least this amount of time
* available maintenance before timing out and cutting off maintenance mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
*/
- public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
+ public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
/**
* This is the maximum amount of time we want to make available for maintenance mode
@@ -956,10 +1007,10 @@ public class DeviceIdleController extends SystemService
* budget and this time is being added to the budget reserve, this is the maximum
* reserve size we will allow to grow and thus the maximum amount of time we will
* allow for the maintenance window.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
*/
- public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
+ public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
/**
* This is the minimum amount of time that we will stay in maintenance mode after
@@ -967,10 +1018,10 @@ public class DeviceIdleController extends SystemService
* in to maintenance mode and scheduling their work -- otherwise we may
* see there is nothing to do (no jobs pending) and go out of maintenance
* mode immediately.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
*/
- public long MIN_LIGHT_MAINTENANCE_TIME;
+ public long MIN_LIGHT_MAINTENANCE_TIME = DEFAULT_MIN_LIGHT_MAINTENANCE_TIME;
/**
* This is the minimum amount of time that we will stay in maintenance mode after
@@ -978,271 +1029,323 @@ public class DeviceIdleController extends SystemService
* in to maintenance mode and scheduling their work -- otherwise we may
* see there is nothing to do (no jobs pending) and go out of maintenance
* mode immediately.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MIN_DEEP_MAINTENANCE_TIME
*/
- public long MIN_DEEP_MAINTENANCE_TIME;
+ public long MIN_DEEP_MAINTENANCE_TIME = DEFAULT_MIN_DEEP_MAINTENANCE_TIME;
/**
* This is the time, after becoming inactive, at which we start looking at the
* motion sensor to determine if the device is being left alone. We don't do this
* immediately after going inactive just because we don't want to be continually running
* the motion sensor whenever the screen is off.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_INACTIVE_TIMEOUT
*/
- public long INACTIVE_TIMEOUT;
+ public long INACTIVE_TIMEOUT = DEFAULT_INACTIVE_TIMEOUT;
/**
* If we don't receive a callback from AnyMotion in this amount of time +
* {@link #LOCATING_TIMEOUT}, we will change from
* STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
* will be ignored.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_SENSING_TIMEOUT
*/
- public long SENSING_TIMEOUT;
+ public long SENSING_TIMEOUT = DEFAULT_SENSING_TIMEOUT;
/**
* This is how long we will wait to try to get a good location fix before going in to
* idle mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_LOCATING_TIMEOUT
*/
- public long LOCATING_TIMEOUT;
+ public long LOCATING_TIMEOUT = DEFAULT_LOCATING_TIMEOUT;
/**
* The desired maximum accuracy (in meters) we consider the location to be good enough to go
* on to idle. We will be trying to get an accuracy fix at least this good or until
* {@link #LOCATING_TIMEOUT} expires.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_LOCATION_ACCURACY
*/
- public float LOCATION_ACCURACY;
+ public float LOCATION_ACCURACY = DEFAULT_LOCATION_ACCURACY;
/**
* This is the time, after seeing motion, that we wait after becoming inactive from
* that until we start looking for motion again.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MOTION_INACTIVE_TIMEOUT
*/
- public long MOTION_INACTIVE_TIMEOUT;
+ public long MOTION_INACTIVE_TIMEOUT = DEFAULT_MOTION_INACTIVE_TIMEOUT;
/**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for motion until we truly consider the device to be idle.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
*/
- public long IDLE_AFTER_INACTIVE_TIMEOUT;
+ public long IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT;
/**
* This is the initial time, after being idle, that we will allow ourself to be back
* in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
* idle.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_PENDING_TIMEOUT
*/
- public long IDLE_PENDING_TIMEOUT;
+ public long IDLE_PENDING_TIMEOUT = DEFAULT_IDLE_PENDING_TIMEOUT;
/**
* Maximum pending idle timeout (time spent running) we will be allowed to use.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MAX_IDLE_PENDING_TIMEOUT
*/
- public long MAX_IDLE_PENDING_TIMEOUT;
+ public long MAX_IDLE_PENDING_TIMEOUT = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
/**
* Scaling factor to apply to current pending idle timeout each time we cycle through
* that state.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_PENDING_FACTOR
*/
- public float IDLE_PENDING_FACTOR;
+ public float IDLE_PENDING_FACTOR = DEFAULT_IDLE_PENDING_FACTOR;
/**
* This is amount of time we will wait from the point where we go into
* STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs
* and other current activity to finish.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_QUICK_DOZE_DELAY_TIMEOUT
*/
- public long QUICK_DOZE_DELAY_TIMEOUT;
+ public long QUICK_DOZE_DELAY_TIMEOUT = DEFAULT_QUICK_DOZE_DELAY_TIMEOUT;
/**
* This is the initial time that we want to sit in the idle state before waking up
* again to return to pending idle and allowing normal work to run.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_TIMEOUT
*/
- public long IDLE_TIMEOUT;
+ public long IDLE_TIMEOUT = DEFAULT_IDLE_TIMEOUT;
/**
* Maximum idle duration we will be allowed to use.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MAX_IDLE_TIMEOUT
*/
- public long MAX_IDLE_TIMEOUT;
+ public long MAX_IDLE_TIMEOUT = DEFAULT_MAX_IDLE_TIMEOUT;
/**
* Scaling factor to apply to current idle timeout each time we cycle through that state.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_FACTOR
*/
- public float IDLE_FACTOR;
+ public float IDLE_FACTOR = DEFAULT_IDLE_FACTOR;
/**
* This is the minimum time we will allow until the next upcoming alarm for us to
* actually go in to idle mode.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MIN_TIME_TO_ALARM
*/
- public long MIN_TIME_TO_ALARM;
+ public long MIN_TIME_TO_ALARM = DEFAULT_MIN_TIME_TO_ALARM;
/**
* Max amount of time to temporarily whitelist an app when it receives a high priority
* tickle.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ *
* @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
*/
- public long MAX_TEMP_APP_WHITELIST_DURATION;
+ public long MAX_TEMP_APP_WHITELIST_DURATION = DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION;
/**
* Amount of time we would like to whitelist an app that is receiving an MMS.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
*/
- public long MMS_TEMP_APP_WHITELIST_DURATION;
+ public long MMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION;
/**
* Amount of time we would like to whitelist an app that is receiving an SMS.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
*/
- public long SMS_TEMP_APP_WHITELIST_DURATION;
+ public long SMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION;
/**
* Amount of time we would like to whitelist an app that is handling a
* {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}.
- * @see Settings.Global#DEVICE_IDLE_CONSTANTS
- * @see #KEY_NOTIFICATION_ALLOWLIST_DURATION
+ * @see #KEY_NOTIFICATION_ALLOWLIST_DURATION_MS
*/
- public long NOTIFICATION_ALLOWLIST_DURATION;
+ public long NOTIFICATION_ALLOWLIST_DURATION_MS = DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS;
/**
* Pre idle time factor use to make idle delay longer
*/
- public float PRE_IDLE_FACTOR_LONG;
+ public float PRE_IDLE_FACTOR_LONG = DEFAULT_PRE_IDLE_FACTOR_LONG;
/**
* Pre idle time factor use to make idle delay shorter
*/
- public float PRE_IDLE_FACTOR_SHORT;
+ public float PRE_IDLE_FACTOR_SHORT = DEFAULT_PRE_IDLE_FACTOR_SHORT;
- public boolean WAIT_FOR_UNLOCK;
+ public boolean WAIT_FOR_UNLOCK = DEFAULT_WAIT_FOR_UNLOCK;
- private final ContentResolver mResolver;
private final boolean mSmallBatteryDevice;
- private final KeyValueListParser mParser = new KeyValueListParser(',');
- public Constants(Handler handler, ContentResolver resolver) {
- super(handler);
- mResolver = resolver;
+ public Constants() {
mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice();
- mResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS),
- false, this);
- updateConstants();
+ if (mSmallBatteryDevice) {
+ INACTIVE_TIMEOUT = DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY;
+ IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY;
+ }
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DEVICE_IDLE,
+ JobSchedulerBackgroundThread.getExecutor(), this);
+ // Load all the constants.
+ onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_DEVICE_IDLE));
}
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- updateConstants();
- }
- private void updateConstants() {
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
synchronized (DeviceIdleController.this) {
- try {
- mParser.setString(Settings.Global.getString(mResolver,
- Settings.Global.DEVICE_IDLE_CONSTANTS));
- } catch (IllegalArgumentException e) {
- // Failed to parse the settings string, log this and move on
- // with defaults.
- Slog.e(TAG, "Bad device idle settings", e);
+ for (String name : properties.getKeyset()) {
+ if (name == null) {
+ continue;
+ }
+ switch (name) {
+ case KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT:
+ LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong(
+ KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
+ DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
+ break;
+ case KEY_LIGHT_PRE_IDLE_TIMEOUT:
+ LIGHT_PRE_IDLE_TIMEOUT = properties.getLong(
+ KEY_LIGHT_PRE_IDLE_TIMEOUT, DEFAULT_LIGHT_PRE_IDLE_TIMEOUT);
+ break;
+ case KEY_LIGHT_IDLE_TIMEOUT:
+ LIGHT_IDLE_TIMEOUT = properties.getLong(
+ KEY_LIGHT_IDLE_TIMEOUT, DEFAULT_LIGHT_IDLE_TIMEOUT);
+ break;
+ case KEY_LIGHT_IDLE_FACTOR:
+ LIGHT_IDLE_FACTOR = properties.getFloat(
+ KEY_LIGHT_IDLE_FACTOR, DEFAULT_LIGHT_IDLE_FACTOR);
+ break;
+ case KEY_LIGHT_MAX_IDLE_TIMEOUT:
+ LIGHT_MAX_IDLE_TIMEOUT = properties.getLong(
+ KEY_LIGHT_MAX_IDLE_TIMEOUT, DEFAULT_LIGHT_MAX_IDLE_TIMEOUT);
+ break;
+ case KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET:
+ LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = properties.getLong(
+ KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
+ DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
+ break;
+ case KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET:
+ LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = properties.getLong(
+ KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
+ DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET);
+ break;
+ case KEY_MIN_LIGHT_MAINTENANCE_TIME:
+ MIN_LIGHT_MAINTENANCE_TIME = properties.getLong(
+ KEY_MIN_LIGHT_MAINTENANCE_TIME,
+ DEFAULT_MIN_LIGHT_MAINTENANCE_TIME);
+ break;
+ case KEY_MIN_DEEP_MAINTENANCE_TIME:
+ MIN_DEEP_MAINTENANCE_TIME = properties.getLong(
+ KEY_MIN_DEEP_MAINTENANCE_TIME,
+ DEFAULT_MIN_DEEP_MAINTENANCE_TIME);
+ break;
+ case KEY_INACTIVE_TIMEOUT:
+ final long defaultInactiveTimeout = mSmallBatteryDevice
+ ? DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY
+ : DEFAULT_INACTIVE_TIMEOUT;
+ INACTIVE_TIMEOUT = properties.getLong(
+ KEY_INACTIVE_TIMEOUT, defaultInactiveTimeout);
+ break;
+ case KEY_SENSING_TIMEOUT:
+ SENSING_TIMEOUT = properties.getLong(
+ KEY_SENSING_TIMEOUT, DEFAULT_SENSING_TIMEOUT);
+ break;
+ case KEY_LOCATING_TIMEOUT:
+ LOCATING_TIMEOUT = properties.getLong(
+ KEY_LOCATING_TIMEOUT, DEFAULT_LOCATING_TIMEOUT);
+ break;
+ case KEY_LOCATION_ACCURACY:
+ LOCATION_ACCURACY = properties.getFloat(
+ KEY_LOCATION_ACCURACY, DEFAULT_LOCATION_ACCURACY);
+ break;
+ case KEY_MOTION_INACTIVE_TIMEOUT:
+ MOTION_INACTIVE_TIMEOUT = properties.getLong(
+ KEY_MOTION_INACTIVE_TIMEOUT, DEFAULT_MOTION_INACTIVE_TIMEOUT);
+ break;
+ case KEY_IDLE_AFTER_INACTIVE_TIMEOUT:
+ final long defaultIdleAfterInactiveTimeout = mSmallBatteryDevice
+ ? DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY
+ : DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT;
+ IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong(
+ KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
+ defaultIdleAfterInactiveTimeout);
+ break;
+ case KEY_IDLE_PENDING_TIMEOUT:
+ IDLE_PENDING_TIMEOUT = properties.getLong(
+ KEY_IDLE_PENDING_TIMEOUT, DEFAULT_IDLE_PENDING_TIMEOUT);
+ break;
+ case KEY_MAX_IDLE_PENDING_TIMEOUT:
+ MAX_IDLE_PENDING_TIMEOUT = properties.getLong(
+ KEY_MAX_IDLE_PENDING_TIMEOUT, DEFAULT_MAX_IDLE_PENDING_TIMEOUT);
+ break;
+ case KEY_IDLE_PENDING_FACTOR:
+ IDLE_PENDING_FACTOR = properties.getFloat(
+ KEY_IDLE_PENDING_FACTOR, DEFAULT_IDLE_PENDING_FACTOR);
+ break;
+ case KEY_QUICK_DOZE_DELAY_TIMEOUT:
+ QUICK_DOZE_DELAY_TIMEOUT = properties.getLong(
+ KEY_QUICK_DOZE_DELAY_TIMEOUT, DEFAULT_QUICK_DOZE_DELAY_TIMEOUT);
+ break;
+ case KEY_IDLE_TIMEOUT:
+ IDLE_TIMEOUT = properties.getLong(
+ KEY_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT);
+ break;
+ case KEY_MAX_IDLE_TIMEOUT:
+ MAX_IDLE_TIMEOUT = properties.getLong(
+ KEY_MAX_IDLE_TIMEOUT, DEFAULT_MAX_IDLE_TIMEOUT);
+ break;
+ case KEY_IDLE_FACTOR:
+ IDLE_FACTOR = properties.getFloat(KEY_IDLE_FACTOR, DEFAULT_IDLE_FACTOR);
+ break;
+ case KEY_MIN_TIME_TO_ALARM:
+ MIN_TIME_TO_ALARM = properties.getLong(
+ KEY_MIN_TIME_TO_ALARM, DEFAULT_MIN_TIME_TO_ALARM);
+ break;
+ case KEY_MAX_TEMP_APP_WHITELIST_DURATION:
+ MAX_TEMP_APP_WHITELIST_DURATION = properties.getLong(
+ KEY_MAX_TEMP_APP_WHITELIST_DURATION,
+ DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION);
+ break;
+ case KEY_MMS_TEMP_APP_WHITELIST_DURATION:
+ MMS_TEMP_APP_WHITELIST_DURATION = properties.getLong(
+ KEY_MMS_TEMP_APP_WHITELIST_DURATION,
+ DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION);
+ break;
+ case KEY_SMS_TEMP_APP_WHITELIST_DURATION:
+ SMS_TEMP_APP_WHITELIST_DURATION = properties.getLong(
+ KEY_SMS_TEMP_APP_WHITELIST_DURATION,
+ DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION);
+ break;
+ case KEY_NOTIFICATION_ALLOWLIST_DURATION_MS:
+ NOTIFICATION_ALLOWLIST_DURATION_MS = properties.getLong(
+ KEY_NOTIFICATION_ALLOWLIST_DURATION_MS,
+ DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS);
+ break;
+ case KEY_WAIT_FOR_UNLOCK:
+ WAIT_FOR_UNLOCK = properties.getBoolean(
+ KEY_WAIT_FOR_UNLOCK, DEFAULT_WAIT_FOR_UNLOCK);
+ break;
+ case KEY_PRE_IDLE_FACTOR_LONG:
+ PRE_IDLE_FACTOR_LONG = properties.getFloat(
+ KEY_PRE_IDLE_FACTOR_LONG, DEFAULT_PRE_IDLE_FACTOR_LONG);
+ break;
+ case KEY_PRE_IDLE_FACTOR_SHORT:
+ PRE_IDLE_FACTOR_SHORT = properties.getFloat(
+ KEY_PRE_IDLE_FACTOR_SHORT, DEFAULT_PRE_IDLE_FACTOR_SHORT);
+ break;
+ default:
+ Slog.e(TAG, "Unknown configuration key: " + name);
+ break;
+ }
}
-
- LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
- KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
- !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L);
- LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT,
- !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L);
- LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT,
- !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
- LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
- 2f);
- LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT,
- !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
- LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis(
- KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
- !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
- LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis(
- KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
- !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
- MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis(
- KEY_MIN_LIGHT_MAINTENANCE_TIME,
- !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
- MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis(
- KEY_MIN_DEEP_MAINTENANCE_TIME,
- !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
- long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
- INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
- !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
- SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
- !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L);
- LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
- !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L);
- LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
- MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
- !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
- long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L;
- IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis(
- KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
- !COMPRESS_TIME ? idleAfterInactiveTimeout
- : (idleAfterInactiveTimeout / 10));
- IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT,
- !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
- MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT,
- !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
- IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
- 2f);
- QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis(
- KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L);
- IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT,
- !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
- MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
- !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
- IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
- 2f);
- MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM,
- !COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L);
- MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
- KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
- MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
- KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
- SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis(
- KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
- NOTIFICATION_ALLOWLIST_DURATION = mParser.getDurationMillis(
- KEY_NOTIFICATION_ALLOWLIST_DURATION, 30 * 1000L);
- WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true);
- PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f);
- PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f);
}
}
void dump(PrintWriter pw) {
pw.println(" Settings:");
- pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
+ pw.print(" ");
+ pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
+ pw.print("=");
TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
pw.println();
@@ -1344,8 +1447,8 @@ public class DeviceIdleController extends SystemService
TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
pw.println();
- pw.print(" "); pw.print(KEY_NOTIFICATION_ALLOWLIST_DURATION); pw.print("=");
- TimeUtils.formatDuration(NOTIFICATION_ALLOWLIST_DURATION, pw);
+ pw.print(" "); pw.print(KEY_NOTIFICATION_ALLOWLIST_DURATION_MS); pw.print("=");
+ TimeUtils.formatDuration(NOTIFICATION_ALLOWLIST_DURATION_MS, pw);
pw.println();
pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("=");
@@ -1794,7 +1897,7 @@ public class DeviceIdleController extends SystemService
// duration in milliseconds
@Override
public long getNotificationAllowlistDuration() {
- return mConstants.NOTIFICATION_ALLOWLIST_DURATION;
+ return mConstants.NOTIFICATION_ALLOWLIST_DURATION_MS;
}
@Override
@@ -1871,10 +1974,9 @@ public class DeviceIdleController extends SystemService
return mConnectivityManager;
}
- Constants getConstants(DeviceIdleController controller, Handler handler,
- ContentResolver resolver) {
+ Constants getConstants(DeviceIdleController controller) {
if (mConstants == null) {
- mConstants = controller.new Constants(handler, resolver);
+ mConstants = controller.new Constants();
}
return mConstants;
}
@@ -2023,7 +2125,7 @@ public class DeviceIdleController extends SystemService
}
}
- mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver());
+ mConstants = mInjector.getConstants(this);
readConfigFileLocked();
updateWhitelistAppIdsLocked();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index f1c624d1d9f5..67997cf31501 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -22,6 +22,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
+import android.annotation.Nullable;
import android.app.job.JobInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -86,9 +87,12 @@ public final class ConnectivityController extends RestrictingController implemen
@GuardedBy("mLock")
private final SparseArray<ArraySet<JobStatus>> mRequestedWhitelistJobs = new SparseArray<>();
- /** List of currently available networks. */
+ /**
+ * Set of currently available networks mapped to their latest network capabilities. Cache the
+ * latest capabilities to avoid unnecessary calls into ConnectivityManager.
+ */
@GuardedBy("mLock")
- private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
+ private final ArrayMap<Network, NetworkCapabilities> mAvailableNetworks = new ArrayMap<>();
private static final int MSG_DATA_SAVER_TOGGLED = 0;
private static final int MSG_UID_RULES_CHANGES = 1;
@@ -165,9 +169,8 @@ public final class ConnectivityController extends RestrictingController implemen
public boolean isNetworkAvailable(JobStatus job) {
synchronized (mLock) {
for (int i = 0; i < mAvailableNetworks.size(); ++i) {
- final Network network = mAvailableNetworks.valueAt(i);
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(
- network);
+ final Network network = mAvailableNetworks.keyAt(i);
+ final NetworkCapabilities capabilities = mAvailableNetworks.valueAt(i);
final boolean satisfied = isSatisfied(job, network, capabilities, mConstants);
if (DEBUG) {
Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network
@@ -427,9 +430,33 @@ public final class ConnectivityController extends RestrictingController implemen
return false;
}
+ @Nullable
+ private NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
+ if (network == null) {
+ return null;
+ }
+ synchronized (mLock) {
+ // There is technically a race here if the Network object is reused. This can happen
+ // only if that Network disconnects and the auto-incrementing network ID in
+ // ConnectivityService wraps. This should no longer be a concern if/when we only make
+ // use of asynchronous calls.
+ if (mAvailableNetworks.get(network) != null) {
+ return mAvailableNetworks.get(network);
+ }
+
+ // This should almost never happen because any time a new network connects, the
+ // NetworkCallback would populate mAvailableNetworks. However, it's currently necessary
+ // because we also call synchronous methods such as getActiveNetworkForUid.
+ // TODO(134978280): remove after switching to callback-based APIs
+ final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ mAvailableNetworks.put(network, capabilities);
+ return capabilities;
+ }
+ }
+
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
- final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
+ final NetworkCapabilities capabilities = getNetworkCapabilities(network);
return updateConstraintsSatisfied(jobStatus, network, capabilities);
}
@@ -470,19 +497,13 @@ public final class ConnectivityController extends RestrictingController implemen
*/
private void updateTrackedJobs(int filterUid, Network filterNetwork) {
synchronized (mLock) {
- // Since this is a really hot codepath, temporarily cache any
- // answers that we get from ConnectivityManager.
- final ArrayMap<Network, NetworkCapabilities> networkToCapabilities = new ArrayMap<>();
-
boolean changed = false;
if (filterUid == -1) {
for (int i = mTrackedJobs.size() - 1; i >= 0; i--) {
- changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i),
- filterNetwork, networkToCapabilities);
+ changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork);
}
} else {
- changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid),
- filterNetwork, networkToCapabilities);
+ changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork);
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
@@ -490,18 +511,13 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
- private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork,
- ArrayMap<Network, NetworkCapabilities> networkToCapabilities) {
+ private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork) {
if (jobs == null || jobs.size() == 0) {
return false;
}
final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
- NetworkCapabilities capabilities = networkToCapabilities.get(network);
- if (capabilities == null) {
- capabilities = mConnManager.getNetworkCapabilities(network);
- networkToCapabilities.put(network, capabilities);
- }
+ final NetworkCapabilities capabilities = getNetworkCapabilities(network);
final boolean networkMatch = (filterNetwork == null
|| Objects.equals(filterNetwork, network));
@@ -544,9 +560,9 @@ public final class ConnectivityController extends RestrictingController implemen
@Override
public void onAvailable(Network network) {
if (DEBUG) Slog.v(TAG, "onAvailable: " + network);
- synchronized (mLock) {
- mAvailableNetworks.add(network);
- }
+ // Documentation says not to call getNetworkCapabilities here but wait for
+ // onCapabilitiesChanged instead. onCapabilitiesChanged should be called immediately
+ // after this, so no need to update mAvailableNetworks here.
}
@Override
@@ -554,6 +570,9 @@ public final class ConnectivityController extends RestrictingController implemen
if (DEBUG) {
Slog.v(TAG, "onCapabilitiesChanged: " + network);
}
+ synchronized (mLock) {
+ mAvailableNetworks.put(network, capabilities);
+ }
updateTrackedJobs(-1, network);
}
@@ -630,6 +649,8 @@ public final class ConnectivityController extends RestrictingController implemen
pw.println("Available networks:");
pw.increaseIndent();
for (int i = 0; i < mAvailableNetworks.size(); i++) {
+ pw.print(mAvailableNetworks.keyAt(i));
+ pw.print(": ");
pw.println(mAvailableNetworks.valueAt(i));
}
pw.decreaseIndent();
@@ -667,7 +688,7 @@ public final class ConnectivityController extends RestrictingController implemen
mRequestedWhitelistJobs.keyAt(i));
}
for (int i = 0; i < mAvailableNetworks.size(); i++) {
- Network network = mAvailableNetworks.valueAt(i);
+ Network network = mAvailableNetworks.keyAt(i);
if (network != null) {
network.dumpDebug(proto,
StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS);
diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp
index e75fa88c54fe..ede8852c5905 100644
--- a/apex/statsd/Android.bp
+++ b/apex/statsd/Android.bp
@@ -19,8 +19,10 @@ apex {
}
apex_defaults {
- native_shared_libs: [
+ jni_libs: [
"libstats_jni",
+ ],
+ native_shared_libs: [
"libstatspull",
"libstatssocket",
],
diff --git a/api/current.txt b/api/current.txt
index a1629f1a937e..e83450136aa4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1005,7 +1005,7 @@ package android {
field public static final int numericModifiers = 16844111; // 0x101054f
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int offset = 16844052; // 0x1010514
- field public static final int onClick = 16843375; // 0x101026f
+ field @Deprecated public static final int onClick = 16843375; // 0x101026f
field public static final int oneshot = 16843159; // 0x1010197
field public static final int opacity = 16843550; // 0x101031e
field public static final int opticalInsetBottom = 16844171; // 0x101058b
@@ -6188,6 +6188,7 @@ package android.app {
method public android.app.PictureInPictureParams build();
method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>);
method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational);
+ method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterAllowed(boolean);
method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect);
}
@@ -31737,6 +31738,7 @@ package android.net.wifi.aware {
method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession);
method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int);
+ method public void onServiceLost(@NonNull android.net.wifi.aware.PeerHandle);
method public void onSessionConfigFailed();
method public void onSessionConfigUpdated();
method public void onSessionTerminated();
@@ -48399,7 +48401,8 @@ package android.telephony {
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
- method public void listen(android.telephony.PhoneStateListener, int);
+ method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
+ method public void listen(long, @NonNull android.telephony.PhoneStateListener);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 17545a469cb8..8186c9c69991 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -129,6 +129,14 @@ package android.os {
}
+package android.provider {
+
+ public final class DeviceConfig {
+ field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
+ }
+
+}
+
package android.util {
public class AtomicFile {
diff --git a/api/system-current.txt b/api/system-current.txt
index dbe2e318a7ba..8009d0370dd8 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4199,8 +4199,10 @@ package android.media {
public class AudioManager {
method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForCapturePresetChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener) throws java.lang.SecurityException;
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener) throws java.lang.SecurityException;
method public void clearAudioServerStateCallback();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean clearPreferredDevicesForCapturePreset(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
@@ -4211,6 +4213,7 @@ package android.media {
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
@@ -4219,6 +4222,7 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDeviceForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForCapturePresetChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean removePreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
@@ -4228,6 +4232,7 @@ package android.media {
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForCapturePreset(int, @NonNull android.media.AudioDeviceAttributes);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
@@ -4257,6 +4262,10 @@ package android.media {
method @Deprecated public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes);
}
+ public static interface AudioManager.OnPreferredDevicesForCapturePresetChangedListener {
+ method public void onPreferredDevicesForCapturePresetChanged(int, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
+ }
+
public static interface AudioManager.OnPreferredDevicesForStrategyChangedListener {
method public void onPreferredDevicesForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
}
@@ -4334,11 +4343,8 @@ package android.media {
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int RADIO_TUNER = 1998; // 0x7ce
}
- public final class MediaTranscodeManager implements java.lang.AutoCloseable {
- method public void close();
+ public final class MediaTranscodeManager {
method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException;
- method protected void finalize();
- field public static final int PRIORITY_OFFLINE = 2; // 0x2
field public static final int PRIORITY_REALTIME = 1; // 0x1
field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
}
@@ -4367,7 +4373,7 @@ package android.media {
}
@java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener {
- method public void onProgressUpdate(@IntRange(from=0, to=100) int);
+ method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int);
}
public static final class MediaTranscodeManager.TranscodingRequest {
@@ -10876,6 +10882,7 @@ package android.telephony {
method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
+ method public void onPhysicalChannelConfigurationChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
@@ -10883,12 +10890,29 @@ package android.telephony {
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 4294967296L; // 0x100000000L
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
}
+ public final class PhysicalChannelConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCellBandwidthDownlink();
+ method public int getChannelNumber();
+ method public int getConnectionStatus();
+ method public int getNetworkType();
+ method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
+ field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+ field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+ field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
+ }
+
public final class PreciseCallState implements android.os.Parcelable {
ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
diff --git a/api/test-current.txt b/api/test-current.txt
index 2dd740924275..af70562839ba 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1819,11 +1819,8 @@ package android.media {
method @NonNull public String getOriginalId();
}
- public final class MediaTranscodeManager implements java.lang.AutoCloseable {
- method public void close();
+ public final class MediaTranscodeManager {
method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException;
- method protected void finalize();
- field public static final int PRIORITY_OFFLINE = 2; // 0x2
field public static final int PRIORITY_REALTIME = 1; // 0x1
field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
}
@@ -1852,7 +1849,7 @@ package android.media {
}
@java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener {
- method public void onProgressUpdate(@IntRange(from=0, to=100) int);
+ method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int);
}
public static final class MediaTranscodeManager.TranscodingRequest {
@@ -3294,6 +3291,7 @@ package android.provider {
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_BIOMETRICS = "biometrics";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
+ field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 573961276e5b..3dbb6ed47ff8 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -69,13 +69,14 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
CountMetricProducer::CountMetricProducer(
const ConfigKey& key, const CountMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap) {
if (metric.has_bucket()) {
mBucketSizeNs =
TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index f05fb061ccc1..6b2f2ca61ecc 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -44,7 +44,7 @@ public:
CountMetricProducer(
const ConfigKey& key, const CountMetric& countMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t timeBaseNs, const int64_t startTimeNs,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {},
@@ -57,6 +57,10 @@ public:
const HashableDimensionKey& primaryKey, const FieldValue& oldState,
const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_COUNT;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index e9b043876d3d..3acafaa3560e 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -66,14 +66,15 @@ DurationMetricProducer::DurationMetricProducer(
const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
- const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap),
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap),
mAggregationType(metric.aggregation_type()),
mStartIndex(startIndex),
mStopIndex(stopIndex),
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index bfe1010c89de..3a94d9c775aa 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,8 +42,9 @@ public:
const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
- const sp<ConditionWizard>& wizard, const FieldMatcher& internalDimensions,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
+ const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap = {},
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap = {},
const vector<int>& slicedStateAtoms = {},
@@ -58,6 +59,10 @@ public:
const HashableDimensionKey& primaryKey, const FieldValue& oldState,
const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_DURATION;
+ }
+
protected:
void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index dc0036a687f3..dfe4559b05fb 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -55,13 +55,14 @@ const int FIELD_ID_ATOMS = 2;
EventMetricProducer::EventMetricProducer(
const ConfigKey& key, const EventMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap) {
+ protoHash, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap) {
if (metric.links().size() > 0) {
for (const auto& link : metric.links()) {
Metric2Condition mc;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index bfb2de36fad4..e828dddcbb18 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -36,7 +36,7 @@ public:
EventMetricProducer(
const ConfigKey& key, const EventMetric& eventMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs,
+ const uint64_t protoHash, const int64_t startTimeNs,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {},
@@ -45,6 +45,10 @@ public:
virtual ~EventMetricProducer();
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_EVENT;
+ }
+
private:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 020f4b638f4d..9dda248a6d1f 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -71,13 +71,14 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 8;
GaugeMetricProducer::GaugeMetricProducer(
const ConfigKey& key, const GaugeMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
- const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
- const int pullTagId, const int triggerAtomId, const int atomId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const uint64_t protoHash, const int whatMatcherIndex,
+ const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int triggerAtomId,
+ const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache, wizard,
- eventActivationMap, eventDeactivationMap, /*slicedStateAtoms=*/{},
+ protoHash, eventActivationMap, eventDeactivationMap, /*slicedStateAtoms=*/{},
/*stateGroupMap=*/{}),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index ef3a24a43dcc..e933d4b19716 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -59,10 +59,11 @@ public:
GaugeMetricProducer(
const ConfigKey& key, const GaugeMetric& gaugeMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
- const int triggerAtomId, const int atomId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int triggerAtomId, const int atomId,
+ const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap = {});
@@ -96,6 +97,10 @@ public:
}
};
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_GAUGE;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index fe143e496373..c1c1d20f00e2 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -46,13 +46,14 @@ const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3;
MetricProducer::MetricProducer(
const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
const int conditionIndex, const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& wizard,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: mMetricId(metricId),
+ mProtoHash(protoHash),
mConfigKey(key),
mTimeBaseNs(timeBaseNs),
mCurrentBucketStartTimeNs(timeBaseNs),
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index be4cd6724bb1..bb590aac54d6 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -87,6 +87,13 @@ enum BucketDropReason {
NO_DATA = 9
};
+enum MetricType {
+ METRIC_TYPE_EVENT = 1,
+ METRIC_TYPE_COUNT = 2,
+ METRIC_TYPE_DURATION = 3,
+ METRIC_TYPE_GAUGE = 4,
+ METRIC_TYPE_VALUE = 5,
+};
struct Activation {
Activation(const ActivationType& activationType, const int64_t ttlNs)
: ttl_ns(ttlNs),
@@ -130,7 +137,7 @@ class MetricProducer : public virtual android::RefBase, public virtual StateList
public:
MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
const int conditionIndex, const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& wizard,
+ const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
eventDeactivationMap,
@@ -259,10 +266,16 @@ public:
int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
// Start: getters/setters
- inline const int64_t& getMetricId() const {
+ inline int64_t getMetricId() const {
return mMetricId;
}
+ inline uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
+ virtual MetricType getMetricType() const = 0;
+
// For test only.
inline int64_t getCurrentBucketNum() const {
return mCurrentBucketNum;
@@ -400,6 +413,10 @@ protected:
const int64_t mMetricId;
+ // Hash of the Metric's proto bytes from StatsdConfig, including any activations.
+ // Used to determine if the definition of this metric has changed across a config update.
+ const uint64_t mProtoHash;
+
const ConfigKey mConfigKey;
// The time when this metric producer was first created. The end time for the current bucket
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index a0c701ea4229..39806890c42d 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -80,11 +80,11 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mConfigValid = initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
- mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mAllAnomalyTrackers,
- mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap,
- mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
+ mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
+ mAllAnomalyTrackers, mAllPeriodicAlarmTrackers, mConditionToMetricMap,
+ mTrackerToMetricMap, mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
mDeactivationAtomTrackerToMetricMap, mAlertTrackerMap, mMetricIndexesWithActivation,
- mNoReportMetricIds);
+ mStateProtoHashes, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
mVersionStringsInReport = config.version_strings_in_metric_report();
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index bd0c8161a884..27f3d51b07ce 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -248,6 +248,9 @@ private:
// Maps the id of a condition tracker to its index in mAllConditionTrackers.
std::unordered_map<int64_t, int> mConditionTrackerMap;
+ // Maps the id of a metric producer to its index in mAllMetricProducers.
+ std::unordered_map<int64_t, int> mMetricProducerMap;
+
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
@@ -295,6 +298,9 @@ private:
// The config is always active if any metric in the config does not have an activation signal.
bool mIsAlwaysActive;
+ // Hashes of the States used in this config, keyed by the state id, used in config updates.
+ std::map<int64_t, uint64_t> mStateProtoHashes;
+
FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index dcfbd5ea239b..39ae9a47f2bf 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -79,16 +79,17 @@ const Value ZERO_DOUBLE((int64_t)0);
ValueMetricProducer::ValueMetricProducer(
const ConfigKey& key, const ValueMetric& metric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
const vector<int>& slicedStateAtoms,
const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, initialConditionCache,
- conditionWizard, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
- stateGroupMap),
+ conditionWizard, protoHash, eventActivationMap, eventDeactivationMap,
+ slicedStateAtoms, stateGroupMap),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 472cc33b97fa..4b2599bdb517 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -52,9 +52,9 @@ public:
ValueMetricProducer(
const ConfigKey& key, const ValueMetric& valueMetric, const int conditionIndex,
const vector<ConditionState>& initialConditionCache,
- const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard, const int pullTagId,
- const int64_t timeBaseNs, const int64_t startTimeNs,
+ const sp<ConditionWizard>& conditionWizard, const uint64_t protoHash,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
@@ -92,6 +92,10 @@ public:
void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
const FieldValue& oldState, const FieldValue& newState) override;
+ MetricType getMetricType() const override {
+ return METRIC_TYPE_VALUE;
+ }
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 2e3e43413d54..3f40c90d515a 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -38,6 +38,7 @@
#include "state/StateManager.h"
#include "stats_util.h"
+using google::protobuf::MessageLite;
using std::set;
using std::unordered_map;
using std::vector;
@@ -60,6 +61,20 @@ bool hasLeafNode(const FieldMatcher& matcher) {
return true;
}
+bool getMetricProtoHash(const MessageLite& metric, const int64_t id, const bool hasActivation,
+ const uint64_t activationHash, uint64_t& metricHash) {
+ string serializedMetric;
+ if (!metric.SerializeToString(&serializedMetric)) {
+ ALOGE("Unable to serialize metric %lld", (long long)id);
+ return false;
+ }
+ metricHash = Hash64(serializedMetric);
+ if (hasActivation) {
+ metricHash = Hash64(to_string(metricHash).append(to_string(activationHash)));
+ }
+ return true;
+}
+
} // namespace
sp<AtomMatchingTracker> createAtomMatchingTracker(const AtomMatcher& logMatcher, const int index,
@@ -228,19 +243,31 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
bool handleMetricActivation(
const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
- const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap, bool& hasActivation,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation,
unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
- unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
+ unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
+ uint64_t& activationHash) {
// Check if metric has an associated activation
auto itr = metricToActivationMap.find(metricId);
- if (itr == metricToActivationMap.end()) return true;
+ if (itr == metricToActivationMap.end()) {
+ hasActivation = false;
+ return true;
+ }
+ hasActivation = true;
int activationIndex = itr->second;
const MetricActivation& metricActivation = config.metric_activation(activationIndex);
+ string serializedActivation;
+ if (!metricActivation.SerializeToString(&serializedActivation)) {
+ ALOGE("Unable to serialize metric activation for metric %lld", (long long)metricId);
+ return false;
+ }
+ activationHash = Hash64(serializedActivation);
+
for (int i = 0; i < metricActivation.event_activation_size(); i++) {
const EventActivation& activation = metricActivation.event_activation(i);
@@ -357,12 +384,20 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
}
bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps) {
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ map<int64_t, uint64_t>& stateProtoHashes) {
for (int i = 0; i < config.state_size(); i++) {
const State& state = config.state(i);
const int64_t stateId = state.id();
stateAtomIdMap[stateId] = state.atom_id();
+ string serializedState;
+ if (!state.SerializeToString(&serializedState)) {
+ ALOGE("Unable to serialize state %lld", (long long)stateId);
+ return false;
+ }
+ stateProtoHashes[stateId] = Hash64(serializedState);
+
const StateMap& stateMap = state.map();
for (auto group : stateMap.group()) {
for (auto value : group.value()) {
@@ -457,18 +492,25 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
- sp<MetricProducer> countProducer =
- new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- timeBaseTimeNs, currentTimeNs, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
+ sp<MetricProducer> countProducer = new CountMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap,
+ slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(countProducer);
}
@@ -566,19 +608,26 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> durationMetric = new DurationMetricProducer(
key, metric, conditionIndex, initialConditionCache, trackerIndices[0],
- trackerIndices[1], trackerIndices[2], nesting, wizard, internalDimensions,
- timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap,
- slicedStateAtoms, stateGroupMap);
+ trackerIndices[1], trackerIndices[2], nesting, wizard, metricHash,
+ internalDimensions, timeBaseTimeNs, currentTimeNs, eventActivationMap,
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(durationMetric);
}
@@ -614,17 +663,24 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
- sp<MetricProducer> eventMetric =
- new EventMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
- timeBaseTimeNs, eventActivationMap, eventDeactivationMap);
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
+ sp<MetricProducer> eventMetric = new EventMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ timeBaseTimeNs, eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(eventMetric);
}
@@ -703,18 +759,26 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> valueProducer = new ValueMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex,
- matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs, pullerManager,
- eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ trackerIndex, matcherWizard, pullTagId, timeBaseTimeNs, currentTimeNs,
+ pullerManager, eventActivationMap, eventDeactivationMap, slicedStateAtoms,
+ stateGroupMap);
allMetricProducers.push_back(valueProducer);
}
@@ -799,18 +863,25 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ bool hasActivation = false;
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ uint64_t activationHash;
bool success = handleMetricActivation(
config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
+ hasActivation, activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap, activationHash);
if (!success) return false;
+ uint64_t metricHash;
+ if (!getMetricProtoHash(metric, metric.id(), hasActivation, activationHash, metricHash)) {
+ return false;
+ }
+
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, trackerIndex,
- matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs,
- pullerManager, eventActivationMap, eventDeactivationMap);
+ key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
+ trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId, timeBaseTimeNs,
+ currentTimeNs, pullerManager, eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(gaugeProducer);
}
for (int i = 0; i < config.no_report_metric_size(); ++i) {
@@ -945,6 +1016,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
vector<sp<ConditionTracker>>& allConditionTrackers,
unordered_map<int64_t, int>& conditionTrackerMap,
vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int64_t, int>& metricProducerMap,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
unordered_map<int, std::vector<int>>& conditionToMetricMap,
@@ -953,9 +1025,9 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) {
+ vector<int>& metricsWithActivation, map<int64_t, uint64_t>& stateProtoHashes,
+ set<int64_t>& noReportMetricIds) {
vector<ConditionState> initialConditionCache;
- unordered_map<int64_t, int> metricProducerMap;
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
@@ -972,7 +1044,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
return false;
}
- if (!initStates(config, stateAtomIdMap, allStateGroupMaps)) {
+ if (!initStates(config, stateAtomIdMap, allStateGroupMaps, stateProtoHashes)) {
ALOGE("initStates failed");
return false;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 6eabcf4971d3..4979c3051133 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -98,8 +98,10 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
// [stateAtomIdMap]: this map should contain the mapping from state ids to atom ids
// [allStateGroupMaps]: this map should contain the mapping from states ids and state
// values to state group ids for all states
+// [stateProtoHashes]: contains a map of state id to the hash of the State proto from the config
bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAtomIdMap,
- unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps);
+ unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ std::map<int64_t, uint64_t>& stateProtoHashes);
// Initialize MetricProducers.
// input:
@@ -146,6 +148,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::unordered_map<int64_t, int>& conditionTrackerMap,
std::vector<sp<MetricProducer>>& allMetricProducers,
+ std::unordered_map<int64_t, int>& metricProducerMap,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
vector<sp<AlarmTracker>>& allPeriodicAlarmTrackers,
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
@@ -154,7 +157,9 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds);
+ vector<int>& metricsWithActivation,
+ std::map<int64_t, uint64_t>& stateProtoHashes,
+ std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index bb8e7bfd90f4..8e2864c6fba8 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -41,6 +41,7 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
@@ -75,7 +76,7 @@ TEST(CountMetricProducerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
+ wizard, protoHash, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, countProducer.mCurrentBucketNum);
EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
@@ -95,7 +96,7 @@ TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs, bucketStartTimeNs);
// 2 events in bucket 1.
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -158,7 +159,7 @@ TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
countProducer.onConditionChanged(true, bucketStartTimeNs);
@@ -226,8 +227,8 @@ TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
CountMetricProducer countProducer(kConfigKey, metric, 0 /*condition tracker index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs,
- bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs, bucketStartTimeNs);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
@@ -265,7 +266,7 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInCurrentBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -332,7 +333,7 @@ TEST_P(CountMetricProducerTest_PartialBucket, TestSplitInNextBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, {}, wizard,
- bucketStartTimeNs, bucketStartTimeNs);
+ protoHash, bucketStartTimeNs, bucketStartTimeNs);
// Bucket is flushed yet.
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -397,7 +398,7 @@ TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -459,7 +460,7 @@ TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
int64_t fiveWeeksNs = 5 * 7 * oneDayNs;
CountMetricProducer countProducer(kConfigKey, metric, -1 /* meaning no condition */, {}, wizard,
- oneDayNs, fiveWeeksNs);
+ protoHash, oneDayNs, fiveWeeksNs);
int64_t fiveWeeksOneDayNs = fiveWeeksNs + oneDayNs;
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index 05cfa37b0ee1..d1f89775ed6a 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -45,6 +45,7 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
void makeLogEvent(LogEvent* logEvent, int64_t timestampNs, int atomId) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
@@ -71,10 +72,10 @@ TEST(DurationMetricTrackerTest, TestFirstBucket) {
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions, 5,
+ 600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, durationProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, durationProducer.mCurrentBucketNum);
@@ -99,10 +100,10 @@ TEST(DurationMetricTrackerTest, TestNoCondition) {
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /*no condition*/, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
@@ -145,7 +146,7 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown},
1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/,
- wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.mCondition = ConditionState::kFalse;
EXPECT_FALSE(durationProducer.mCondition);
@@ -195,7 +196,7 @@ TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, {ConditionState::kUnknown},
1 /* start index */, 2 /* stop index */, 3 /* stop_all index */, false /*nesting*/,
- wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ wizard, protoHash, dimensions, bucketStartTimeNs, bucketStartTimeNs);
EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
@@ -238,10 +239,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDuration) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -301,10 +302,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationWithSplitInFollo
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -365,10 +366,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestSumDurationAnomaly) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -411,10 +412,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDuration) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -465,10 +466,10 @@ TEST_P(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextB
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
- DurationMetricProducer durationProducer(kConfigKey, metric, -1 /* no condition */, {},
- 1 /* start index */, 2 /* stop index */,
- 3 /* stop_all index */, false /*nesting*/, wizard,
- dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, -1 /* no condition */, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, protoHash, dimensions,
+ bucketStartTimeNs, bucketStartTimeNs);
int64_t startTimeNs = bucketStartTimeNs + 1;
LogEvent event1(/*uid=*/0, /*pid=*/0);
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index dfbb9da568b0..4bbbd2cb36ad 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -36,9 +36,11 @@ namespace android {
namespace os {
namespace statsd {
-const ConfigKey kConfigKey(0, 12345);
namespace {
+const ConfigKey kConfigKey(0, 12345);
+const uint64_t protoHash = 0x1234567890;
+
void makeLogEvent(LogEvent* logEvent, int32_t atomId, int64_t timestampNs, string str) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
AStatsEvent_setAtomId(statsEvent, atomId);
@@ -66,7 +68,7 @@ TEST(EventMetricProducerTest, TestNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EventMetricProducer eventProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, bucketStartTimeNs);
+ wizard, protoHash, bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
@@ -102,7 +104,8 @@ TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs);
eventProducer.onConditionChanged(true /*condition*/, bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
@@ -157,7 +160,8 @@ TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
EventMetricProducer eventProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, bucketStartTimeNs);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index ba919f1e0ad8..10606810d806 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -47,6 +47,7 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
+const uint64_t protoHash = 0x123456789;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -101,8 +102,9 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
// statsd started long ago.
// The metric starts in the middle of the bucket
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1, -1,
- tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
@@ -139,8 +141,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -213,7 +216,7 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) {
createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -306,8 +309,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -373,8 +377,9 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
.WillOnce(Return(false));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -426,9 +431,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, conditionChangeNs);
@@ -509,9 +514,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
}));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 0 /*condition index*/,
- {ConditionState::kUnknown}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ {ConditionState::kUnknown}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, sliceConditionChangeNs);
@@ -554,8 +559,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
- tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
gaugeProducer.prepareFirstBucket();
Alert alert;
@@ -649,8 +655,8 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -724,8 +730,8 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
@@ -783,8 +789,8 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
gaugeProducer.prepareFirstBucket();
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 8790fe428d19..b166cc1fe04e 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -46,6 +46,7 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
+const uint64_t protoHash = 0x1234567890;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10000000000;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -108,8 +109,8 @@ public:
sp<ValueMetricProducer> valueProducer =
new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -127,7 +128,7 @@ public:
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 0 /*condition index*/, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
valueProducer->mCondition = conditionAfterFirstBucketPrepared;
@@ -147,9 +148,9 @@ public:
.WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /* no condition */, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
- {}, slicedStateAtoms, stateGroupMap);
+ kConfigKey, metric, -1 /* no condition */, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -169,8 +170,9 @@ public:
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 0 /* condition tracker index */, {ConditionState::kUnknown},
- wizard, logEventMatcherIndex, eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms, stateGroupMap);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager, {}, {}, slicedStateAtoms,
+ stateGroupMap);
valueProducer->prepareFirstBucket();
valueProducer->mCondition = conditionAfterFirstBucketPrepared;
return valueProducer;
@@ -228,8 +230,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
// statsd started long ago.
// The metric starts in the middle of the bucket
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1,
- startTimeBase, 22, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, startTimeBase, 22, pullerManager);
valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -254,8 +256,8 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
// statsd started long ago.
// The metric starts in the middle of the bucket
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard, -1, 5,
- 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
+ -1, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
@@ -414,9 +416,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
return true;
}));
- sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ new ValueMetricProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {}, wizard,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -679,9 +682,9 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -749,9 +752,9 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -797,9 +800,9 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs, _))
.WillOnce(Return(true));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -869,9 +872,9 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -911,7 +914,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, -1,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, -1,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
@@ -978,7 +981,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
- wizard, logEventMatcherIndex, eventMatcherWizard,
+ wizard, protoHash, logEventMatcherIndex, eventMatcherWizard,
-1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
valueProducer.prepareFirstBucket();
@@ -1321,9 +1324,9 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1361,9 +1364,9 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1400,9 +1403,9 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1444,9 +1447,9 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1484,9 +1487,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -1553,9 +1556,9 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
- pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, -1,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -2089,7 +2092,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
ValueMetricProducer valueProducer(kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
+ protoHash, logEventMatcherIndex, eventMatcherWizard, tagId,
bucket2StartTimeNs, bucket2StartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
@@ -2922,9 +2925,9 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
ProtoOutputStream output;
@@ -2956,9 +2959,9 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -3005,9 +3008,9 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, {}, wizard, protoHash,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
valueProducer.prepareFirstBucket();
ProtoOutputStream output;
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 890884bc5d83..843d836a2c0b 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -58,6 +58,7 @@ unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
vector<sp<ConditionTracker>> oldConditionTrackers;
unordered_map<int64_t, int> oldConditionTrackerMap;
vector<sp<MetricProducer>> oldMetricProducers;
+unordered_map<int64_t, int> oldMetricProducerMap;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -67,6 +68,7 @@ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+map<int64_t, uint64_t> oldStateHashes;
std::set<int64_t> noReportMetricIds;
class ConfigUpdateTest : public ::testing::Test {
@@ -81,6 +83,7 @@ public:
oldConditionTrackers.clear();
oldConditionTrackerMap.clear();
oldMetricProducers.clear();
+ oldMetricProducerMap.clear();
oldAnomalyTrackers.clear();
oldAlarmTrackers.clear();
conditionToMetricMap.clear();
@@ -90,6 +93,7 @@ public:
deactivationAtomTrackerToMetricMap.clear();
alertTrackerMap.clear();
metricsWithActivation.clear();
+ oldStateHashes.clear();
noReportMetricIds.clear();
}
};
@@ -98,10 +102,11 @@ bool initConfig(const StatsdConfig& config) {
return initStatsdConfig(
key, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, timeBaseNs, allTagIds, oldAtomMatchingTrackers, oldAtomMatchingTrackerMap,
- oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldAnomalyTrackers,
- oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds);
+ oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap,
+ oldAnomalyTrackers, oldAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ oldStateHashes, noReportMetricIds);
}
} // anonymous namespace
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
index e6583c9686ec..0d0a8960043e 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -14,6 +14,7 @@
#include "src/metrics/parsing_utils/metrics_manager_util.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
@@ -388,6 +389,7 @@ TEST(MetricsManagerTest, TestInitialConditions) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -397,15 +399,17 @@ TEST(MetricsManagerTest, TestInitialConditions) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
ASSERT_EQ(4u, allMetricProducers.size());
ASSERT_EQ(5u, allConditionTrackers.size());
@@ -438,6 +442,7 @@ TEST(MetricsManagerTest, TestGoodConfig) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -447,16 +452,19 @@ TEST(MetricsManagerTest, TestGoodConfig) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_TRUE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
ASSERT_EQ(1u, allMetricProducers.size());
+ EXPECT_THAT(metricProducerMap, UnorderedElementsAre(Pair(config.count_metric(0).id(), 0)));
ASSERT_EQ(1u, allAnomalyTrackers.size());
ASSERT_EQ(1u, noReportMetricIds.size());
ASSERT_EQ(1u, alertTrackerMap.size());
@@ -476,6 +484,7 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -485,15 +494,17 @@ TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
@@ -508,6 +519,7 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -517,15 +529,17 @@ TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingMatchers) {
@@ -540,6 +554,7 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -549,14 +564,16 @@ TEST(MetricsManagerTest, TestMissingMatchers) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, TestMissingPredicate) {
@@ -571,6 +588,7 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -580,14 +598,16 @@ TEST(MetricsManagerTest, TestMissingPredicate) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCirclePredicateDependency) {
@@ -602,6 +622,7 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -611,15 +632,17 @@ TEST(MetricsManagerTest, TestCirclePredicateDependency) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
@@ -634,6 +657,7 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
vector<sp<ConditionTracker>> allConditionTrackers;
unordered_map<int64_t, int> conditionTrackerMap;
vector<sp<MetricProducer>> allMetricProducers;
+ unordered_map<int64_t, int> metricProducerMap;
std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
std::vector<sp<AlarmTracker>> allAlarmTrackers;
unordered_map<int, std::vector<int>> conditionToMetricMap;
@@ -643,15 +667,17 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
+ map<int64_t, uint64_t> stateProtoHashes;
std::set<int64_t> noReportMetricIds;
EXPECT_FALSE(initStatsdConfig(
kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, timeBaseSec, allTagIds, allAtomMatchingTrackers, atomMatchingTrackerMap,
- allConditionTrackers, conditionTrackerMap, allMetricProducers, allAnomalyTrackers,
- allAlarmTrackers, conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
- metricsWithActivation, noReportMetricIds));
+ allConditionTrackers, conditionTrackerMap, allMetricProducers, metricProducerMap,
+ allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap, trackerToMetricMap,
+ trackerToConditionMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ stateProtoHashes, noReportMetricIds));
}
TEST(MetricsManagerTest, TestCreateAtomMatchingTrackerInvalidMatcher) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6737972dc34e..1ff48f6baa6a 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -207,7 +207,7 @@ public class Notification implements Parcelable
* <p>
* Avoids spamming the system with overly large strings such as full e-mails.
*/
- private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
+ private static final int MAX_CHARSEQUENCE_LENGTH = 1024;
/**
* Maximum entries of reply text that are accepted by Builder and friends.
@@ -7863,7 +7863,7 @@ public class Notification implements Parcelable
*/
public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender,
boolean remoteInputHistory) {
- mText = text;
+ mText = safeCharSequence(text);
mTimestamp = timestamp;
mSender = sender;
mRemoteInputHistory = remoteInputHistory;
@@ -7977,7 +7977,7 @@ public class Notification implements Parcelable
bundle.putLong(KEY_TIMESTAMP, mTimestamp);
if (mSender != null) {
// Legacy listeners need this
- bundle.putCharSequence(KEY_SENDER, mSender.getName());
+ bundle.putCharSequence(KEY_SENDER, safeCharSequence(mSender.getName()));
bundle.putParcelable(KEY_SENDER_PERSON, mSender);
}
if (mDataMimeType != null) {
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 67d94dec88c5..18c4d70dd9b0 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Rect;
@@ -46,6 +47,8 @@ public final class PictureInPictureParams implements Parcelable {
@Nullable
private Rect mSourceRectHint;
+ private boolean mAutoEnterAllowed;
+
/**
* Sets the aspect ratio. This aspect ratio is defined as the desired width / height, and
* does not change upon device rotation.
@@ -103,6 +106,25 @@ public final class PictureInPictureParams implements Parcelable {
}
/**
+ * Sets whether the system is allowed to automatically put the activity in
+ * picture-in-picture mode without needing/waiting for the activity to call
+ * {@link Activity#enterPictureInPictureMode(PictureInPictureParams)}.
+ *
+ * If true, {@link Activity#onPictureInPictureRequested()} will never be called.
+ *
+ * This property is false by default.
+ * @param autoEnterAllowed {@code true} if the system is allowed to automatically put the
+ * activity in picture-in-picture mode.
+ *
+ * @return this builder instance.
+ */
+ @NonNull
+ public Builder setAutoEnterAllowed(boolean autoEnterAllowed) {
+ mAutoEnterAllowed = autoEnterAllowed;
+ return this;
+ }
+
+ /**
* @return an immutable {@link PictureInPictureParams} to be used when entering or updating
* the activity in picture-in-picture.
*
@@ -111,7 +133,7 @@ public final class PictureInPictureParams implements Parcelable {
*/
public PictureInPictureParams build() {
PictureInPictureParams params = new PictureInPictureParams(mAspectRatio, mUserActions,
- mSourceRectHint);
+ mSourceRectHint, mAutoEnterAllowed);
return params;
}
}
@@ -136,6 +158,11 @@ public final class PictureInPictureParams implements Parcelable {
@Nullable
private Rect mSourceRectHint;
+ /**
+ * Whether the system is allowed to automatically put the activity in picture-in-picture mode.
+ */
+ private boolean mAutoEnterAllowed;
+
/** {@hide} */
PictureInPictureParams() {
}
@@ -152,14 +179,18 @@ public final class PictureInPictureParams implements Parcelable {
if (in.readInt() != 0) {
mSourceRectHint = Rect.CREATOR.createFromParcel(in);
}
+ if (in.readInt() != 0) {
+ mAutoEnterAllowed = in.readBoolean();
+ }
}
/** {@hide} */
PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions,
- Rect sourceRectHint) {
+ Rect sourceRectHint, boolean autoEnterAllowed) {
mAspectRatio = aspectRatio;
mUserActions = actions;
mSourceRectHint = sourceRectHint;
+ mAutoEnterAllowed = autoEnterAllowed;
}
/**
@@ -176,6 +207,7 @@ public final class PictureInPictureParams implements Parcelable {
if (otherArgs.hasSourceBoundsHint()) {
mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
}
+ mAutoEnterAllowed = otherArgs.mAutoEnterAllowed;
}
/**
@@ -248,11 +280,20 @@ public final class PictureInPictureParams implements Parcelable {
}
/**
+ * @return whether auto pip allowed.
+ * @hide
+ */
+ public boolean isAutoEnterAllowed() {
+ return mAutoEnterAllowed;
+ }
+
+ /**
* @return True if no parameters are set
* @hide
*/
public boolean empty() {
- return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio();
+ return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio()
+ && !mAutoEnterAllowed;
}
@Override
@@ -281,6 +322,8 @@ public final class PictureInPictureParams implements Parcelable {
} else {
out.writeInt(0);
}
+ out.writeInt(1);
+ out.writeBoolean(mAutoEnterAllowed);
}
public static final @android.annotation.NonNull Creator<PictureInPictureParams> CREATOR =
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 98de85d9735d..7b3d9f113bda 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11992,6 +11992,9 @@ public class DevicePolicyManager {
* </ul>
* Common Criteria mode is disabled by default.
*
+ * <p><em>Note:</em> if Common Critera mode is turned off after being enabled previously,
+ * all existing WiFi configurations will be lost.
+ *
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @param enabled whether Common Criteria mode should be enabled or not.
*/
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d672c6ac6c2f..d2395ec9f69f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1155,7 +1155,8 @@ public abstract class PackageManager {
/**
* Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
- * if the new package uses a shared library that is not available.
+ * when the package being replaced is a system app and the caller didn't provide the
+ * {@link #DELETE_SYSTEM_APP} flag.
*
* @hide
*/
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 17851adac51b..7f01cad940ec 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -155,6 +155,19 @@ public class DynamicSystemManager {
}
}
/**
+ * Complete the current partition installation.
+ *
+ * @return true if the partition installation completes without error.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
+ public boolean closePartition() {
+ try {
+ return mService.closePartition();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ /**
* Finish a previously started installation. Installations without a cooresponding
* finishInstallation() will be cleaned up during device boot.
*/
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a1f927266de3..df0a69b47225 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -39,6 +39,13 @@ interface IDynamicSystemService
boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
/**
+ * Complete the current partition installation.
+ *
+ * @return true if the partition installation completes without error.
+ */
+ boolean closePartition();
+
+ /**
* Finish a previously started installation. Installations without
* a cooresponding finishInstallation() will be cleaned up during device boot.
*/
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 859b70382328..7a03953f2e9b 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -145,6 +145,15 @@ public final class DeviceConfig {
public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
/**
+ * Namespace for device idle configurations.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
+
+ /**
* Namespace for how dex runs. The feature requires a reboot to reach a clean state.
*
* @deprecated No longer used
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index d55fc511fc77..4e1f81919c7d 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -239,6 +239,10 @@ public abstract class DocumentsProvider extends ContentProvider {
}
}
+ private Uri validateIncomingNullableUri(@Nullable Uri uri) {
+ return uri == null ? null : validateIncomingUri(uri);
+ }
+
/**
* Create a new document and return its newly generated
* {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
@@ -1086,11 +1090,18 @@ public abstract class DocumentsProvider extends ContentProvider {
// If the URI is a tree URI performs some validation.
enforceTreeForExtraUris(extras);
+ final Uri extraUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_URI));
+ final Uri extraTargetUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI));
+ final Uri extraParentUri = validateIncomingNullableUri(
+ extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI));
+
if (METHOD_EJECT_ROOT.equals(method)) {
// Given that certain system apps can hold MOUNT_UNMOUNT permission, but only apps
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
// MANAGE_DOCUMENTS or associated URI permission here instead
- final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+ final Uri rootUri = extraUri;
enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(),
null);
@@ -1100,7 +1111,7 @@ public abstract class DocumentsProvider extends ContentProvider {
return out;
}
- final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+ final Uri documentUri = extraUri;
final String authority = documentUri.getAuthority();
final String documentId = DocumentsContract.getDocumentId(documentUri);
@@ -1113,7 +1124,7 @@ public abstract class DocumentsProvider extends ContentProvider {
enforceReadPermissionInner(documentUri, getCallingPackage(),
getCallingAttributionTag(), null);
- final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri childUri = extraTargetUri;
final String childAuthority = childUri.getAuthority();
final String childId = DocumentsContract.getDocumentId(childUri);
@@ -1180,7 +1191,7 @@ public abstract class DocumentsProvider extends ContentProvider {
revokeDocumentPermission(documentId);
} else if (METHOD_COPY_DOCUMENT.equals(method)) {
- final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
enforceReadPermissionInner(documentUri, getCallingPackage(),
@@ -1204,9 +1215,9 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_MOVE_DOCUMENT.equals(method)) {
- final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
+ final Uri parentSourceUri = extraParentUri;
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
- final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
+ final Uri targetUri = extraTargetUri;
final String targetId = DocumentsContract.getDocumentId(targetUri);
enforceWritePermissionInner(documentUri, getCallingPackage(),
@@ -1232,7 +1243,7 @@ public abstract class DocumentsProvider extends ContentProvider {
}
} else if (METHOD_REMOVE_DOCUMENT.equals(method)) {
- final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
+ final Uri parentSourceUri = extraParentUri;
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 03cf0cf2ca78..739e169e44c7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11534,38 +11534,6 @@ public final class Settings {
public static final String APP_OPS_CONSTANTS = "app_ops_constants";
/**
- * Device Idle (Doze) specific settings.
- * This is encoded as a key=value list, separated by commas. Ex:
- *
- * "inactive_to=60000,sensing_to=400000"
- *
- * The following keys are supported:
- *
- * <pre>
- * inactive_to (long)
- * sensing_to (long)
- * motion_inactive_to (long)
- * idle_after_inactive_to (long)
- * idle_pending_to (long)
- * max_idle_pending_to (long)
- * idle_pending_factor (float)
- * quick_doze_delay_to (long)
- * idle_to (long)
- * max_idle_to (long)
- * idle_factor (float)
- * min_time_to_alarm (long)
- * max_temp_app_whitelist_duration (long)
- * notification_whitelist_duration (long)
- * </pre>
- *
- * <p>
- * Type: string
- * @hide
- * @see com.android.server.DeviceIdleController.Constants
- */
- public static final String DEVICE_IDLE_CONSTANTS = "device_idle_constants";
-
- /**
* Battery Saver specific settings
* This is encoded as a key=value list, separated by commas. Ex:
*
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index cbc304b3293a..8f31d77ac180 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -486,6 +486,16 @@ public class PhoneStateListener {
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public static final int LISTEN_BARRING_INFO = 0x80000000;
+ /**
+ * Listen for changes to the physical channel configuration.
+ *
+ * @see #onPhysicalChannelConfigurationChanged
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+ public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x100000000L;
+
/*
* Subscription used to listen to the phone state changes
* @hide
@@ -1145,6 +1155,18 @@ public class PhoneStateListener {
}
/**
+ * Callback invoked when the current physical channel configuration has changed
+ *
+ * @param configs List of the current {@link PhysicalChannelConfig}s
+ * @hide
+ */
+ @SystemApi
+ public void onPhysicalChannelConfigurationChanged(
+ @NonNull List<PhysicalChannelConfig> configs) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*
@@ -1447,6 +1469,15 @@ public class PhoneStateListener {
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo)));
}
+
+ public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPhysicalChannelConfigurationChanged(configs)));
+ }
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index a720601d81ff..6d48dc36ceb4 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -211,7 +211,7 @@ public class TelephonyRegistryManager {
* @param notifyNow Whether to notify instantly
*/
public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
- @NonNull PhoneStateListener listener, int events, boolean notifyNow) {
+ @NonNull PhoneStateListener listener, long events, boolean notifyNow) {
try {
// subId from PhoneStateListener is deprecated Q on forward, use the subId from
// TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
@@ -754,4 +754,19 @@ public class TelephonyRegistryManager {
}
}
+ /**
+ * Notify {@link PhysicalChannelConfig} has changed for a specific subscription.
+ *
+ * @param subId the subId
+ * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
+ */
+ public void notifyPhysicalChannelConfigurationForSubscriber(
+ int subId, List<PhysicalChannelConfig> configs) {
+ try {
+ sRegistry.notifyPhysicalChannelConfigurationForSubscriber(subId, configs);
+ } catch (RemoteException ex) {
+ // system server crash
+ }
+ }
+
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6e17ac9960a8..6a5074cb8696 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -53,6 +53,9 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CO
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
@@ -1439,14 +1442,13 @@ public final class ViewRootImpl implements ViewParent,
}
// Don't lose the mode we last auto-computed.
- if ((attrs.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+ if ((attrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
- & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
- | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
+ & ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST);
}
- if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) {
+ if (mWindowAttributes.softInputMode != oldSoftInputMode) {
requestFitSystemWindows();
}
@@ -2063,6 +2065,7 @@ public final class ViewRootImpl implements ViewParent,
final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
final int flags = inOutParams.flags;
final int type = inOutParams.type;
+ final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST;
if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
inOutParams.insetsFlags.appearance = 0;
@@ -2088,12 +2091,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ inOutParams.privateFlags &= ~PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+
if ((inOutParams.privateFlags & PRIVATE_FLAG_FIT_INSETS_CONTROLLED) != 0) {
return;
}
int types = inOutParams.getFitInsetsTypes();
- int sides = inOutParams.getFitInsetsSides();
boolean ignoreVis = inOutParams.isFitInsetsIgnoringVisibility();
if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
@@ -2108,10 +2112,13 @@ public final class ViewRootImpl implements ViewParent,
if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
ignoreVis = true;
} else if ((types & Type.systemBars()) == Type.systemBars()) {
- types |= Type.ime();
+ if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
+ types |= Type.ime();
+ } else {
+ inOutParams.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+ }
}
inOutParams.setFitInsetsTypes(types);
- inOutParams.setFitInsetsSides(sides);
inOutParams.setFitInsetsIgnoringVisibility(ignoreVis);
// The fitting of insets are not really controlled by the clients, so we remove the flag.
@@ -2481,8 +2488,7 @@ public final class ViewRootImpl implements ViewParent,
if (mFirst || mAttachInfo.mViewVisibilityChanged) {
mAttachInfo.mViewVisibilityChanged = false;
- int resizeMode = mSoftInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+ int resizeMode = mSoftInputMode & SOFT_INPUT_MASK_ADJUST;
// If we are in auto resize mode, then we need to determine
// what mode to use now.
if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
@@ -2495,11 +2501,8 @@ public final class ViewRootImpl implements ViewParent,
if (resizeMode == 0) {
resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
}
- if ((lp.softInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
- lp.softInputMode = (lp.softInputMode &
- ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
- resizeMode;
+ if ((lp.softInputMode & SOFT_INPUT_MASK_ADJUST) != resizeMode) {
+ lp.softInputMode = (lp.softInputMode & ~SOFT_INPUT_MASK_ADJUST) | resizeMode;
params = lp;
}
}
@@ -3234,8 +3237,8 @@ public final class ViewRootImpl implements ViewParent,
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
- mImeFocusController.onPostWindowFocus(mView.findFocus(), hasWindowFocus,
- mWindowAttributes);
+ mImeFocusController.onPostWindowFocus(mView != null ? mView.findFocus() : null,
+ hasWindowFocus, mWindowAttributes);
if (hasWindowFocus) {
// Clear the forward bit. We can just do this directly, since
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 32ee290a0f47..0d62da6bc8e3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2105,6 +2105,12 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_TRUSTED_OVERLAY = 0x20000000;
/**
+ * Flag to indicate that the parent frame of a window should be inset by IME.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME = 0x40000000;
+
+ /**
* An internal annotation for flags that can be specified to {@link #softInputMode}.
*
* @hide
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index f9a2ecc10dc8..e5c845059a0d 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -26,6 +26,7 @@ import android.view.ThreadedRenderer;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor.Session;
+import com.android.internal.util.FrameworkStatsLog;
/**
* @hide
@@ -34,18 +35,19 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
private static final String TAG = FrameTracker.class.getSimpleName();
private static final boolean DEBUG = false;
//TODO (163431584): need also consider other refresh rates.
- private static final long CRITERIA = 1000000000 / 60;
- @VisibleForTesting
- public static final long UNKNOWN_TIMESTAMP = -1;
+ private static final long JANK_THRESHOLD_NANOS = 1000000000 / 60;
+ private static final long UNKNOWN_TIMESTAMP = -1;
- @VisibleForTesting
- public long mBeginTime = UNKNOWN_TIMESTAMP;
- @VisibleForTesting
- public long mEndTime = UNKNOWN_TIMESTAMP;
- public boolean mShouldTriggerTrace;
- public HardwareRendererObserver mObserver;
- public ThreadedRendererWrapper mRendererWrapper;
- public FrameMetricsWrapper mMetricsWrapper;
+ private final HardwareRendererObserver mObserver;
+ private final ThreadedRendererWrapper mRendererWrapper;
+ private final FrameMetricsWrapper mMetricsWrapper;
+
+ private long mBeginTime = UNKNOWN_TIMESTAMP;
+ private long mEndTime = UNKNOWN_TIMESTAMP;
+ private boolean mShouldTriggerTrace;
+ private long mTotalFramesCount = 0;
+ private long mMissedFramesCount = 0;
+ private long mMaxFrameTimeNanos = 0;
private Session mSession;
@@ -108,37 +110,6 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
Trace.endAsyncSection(mSession.getName(), (int) mBeginTime);
}
- /**
- * Check if we had a janky frame according to the metrics.
- * @param metrics frame metrics
- * @return true if it is a janky frame
- */
- @VisibleForTesting
- public boolean isJankyFrame(FrameMetricsWrapper metrics) {
- long totalDurationMs = metrics.getMetric(FrameMetrics.TOTAL_DURATION);
- boolean isFirstFrame = metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
- boolean isJanky = !isFirstFrame && totalDurationMs - CRITERIA > 0;
-
- if (DEBUG) {
- StringBuilder sb = new StringBuilder();
- sb.append(isJanky).append(",");
- sb.append(metrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.ANIMATION_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.DRAW_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.SYNC_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.SWAP_BUFFERS_DURATION)).append(",");
- sb.append(totalDurationMs).append(",");
- sb.append(metrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)).append(",");
- sb.append(metrics.getMetric(FrameMetrics.VSYNC_TIMESTAMP)).append(",");
- Log.v(TAG, "metrics=" + sb.toString());
- }
-
- return isJanky;
- }
-
@Override
public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
// Since this callback might come a little bit late after the end() call.
@@ -160,11 +131,29 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
triggerPerfetto();
}
+ if (mSession.logToStatsd()) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
+ mSession.getStatsdInteractionType(),
+ mTotalFramesCount,
+ mMissedFramesCount,
+ mMaxFrameTimeNanos);
+ }
return;
}
- // The frame is in the duration of the CUJ, check if it catches the deadline.
- if (isJankyFrame(mMetricsWrapper)) {
+ long totalDurationNanos = mMetricsWrapper.getMetric(FrameMetrics.TOTAL_DURATION);
+ boolean isFirstFrame = mMetricsWrapper.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
+ boolean isJankyFrame = !isFirstFrame && totalDurationNanos > JANK_THRESHOLD_NANOS;
+
+ mTotalFramesCount += 1;
+
+ if (!isFirstFrame) {
+ mMaxFrameTimeNanos = Math.max(totalDurationNanos, mMaxFrameTimeNanos);
+ }
+
+ if (isJankyFrame) {
+ mMissedFramesCount += 1;
mShouldTriggerTrace = true;
}
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 6bfb178bc102..5a0cbf9e93e4 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,6 +16,8 @@
package com.android.internal.jank;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.HandlerThread;
@@ -37,9 +39,20 @@ public class InteractionJankMonitor {
private static final String TAG = InteractionJankMonitor.class.getSimpleName();
private static final boolean DEBUG = false;
private static final Object LOCK = new Object();
+
+ // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
public static final int CUJ_NOTIFICATION_SHADE_MOTION = 0;
public static final int CUJ_NOTIFICATION_SHADE_GESTURE = 1;
+ private static final int NO_STATSD_LOGGING = -1;
+
+ // Used to convert CujType to InteractionType enum value for statsd logging.
+ // Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd.
+ private static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = {
+ NO_STATSD_LOGGING,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE,
+ };
+
private static ThreadedRenderer sRenderer;
private static Map<String, FrameTracker> sRunningTracker;
private static HandlerThread sWorker;
@@ -173,6 +186,15 @@ public class InteractionJankMonitor {
return mId;
}
+ public int getStatsdInteractionType() {
+ return CUJ_TO_STATSD_INTERACTION_TYPE[mId];
+ }
+
+ /** Describes whether the measurement from this session should be written to statsd. */
+ public boolean logToStatsd() {
+ return getStatsdInteractionType() != NO_STATSD_LOGGING;
+ }
+
public String getName() {
return "CujType<" + mId + ">";
}
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 51b41198e272..5e34c15c42e2 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -20,8 +20,10 @@ import android.content.AutofillOptions;
import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.res.AssetManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.view.ContextThemeWrapper;
+import android.view.Display;
import android.view.contentcapture.ContentCaptureManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -47,9 +49,17 @@ public class DecorContext extends ContextThemeWrapper {
public DecorContext(Context baseContext, PhoneWindow phoneWindow) {
super(null /* base */, null);
setPhoneWindow(phoneWindow);
- final Context displayContext = baseContext.createDisplayContext(
- // TODO(b/149790106): Non-activity context can be passed.
- phoneWindow.getContext().getDisplayNoVerify());
+ // TODO(b/149790106): Non-activity context can be passed.
+ final Display display = phoneWindow.getContext().getDisplayNoVerify();
+ final Context displayContext;
+ if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ // TODO(b/166174272): Creating a display context for the default display will result
+ // in additional resource creation.
+ displayContext = baseContext.createConfigurationContext(Configuration.EMPTY);
+ displayContext.updateDisplay(Display.DEFAULT_DISPLAY);
+ } else {
+ displayContext = baseContext.createDisplayContext(display);
+ }
attachBaseContext(displayContext);
}
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index d41d30735d7d..25d1ae699aa6 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -23,6 +23,7 @@ import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.PhoneCapability;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
@@ -68,4 +69,6 @@ oneway interface IPhoneStateListener {
void onRegistrationFailed(in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
void onBarringInfoChanged(in BarringInfo barringInfo);
+ void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
+
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index ea09fc8cd34a..313bd42fe8c1 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -47,10 +47,10 @@ interface ITelephonyRegistry {
*/
@UnsupportedAppUsage
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events,
+ void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, long events,
boolean notifyNow);
void listenForSubscriber(in int subId, String pkg, String featureId,
- IPhoneStateListener callback, int events, boolean notifyNow);
+ IPhoneStateListener callback, long events, boolean notifyNow);
@UnsupportedAppUsage
void notifyCallStateForAllSubs(int state, String incomingNumber);
void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
@@ -99,4 +99,6 @@ interface ITelephonyRegistry {
void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
+ void notifyPhysicalChannelConfigurationForSubscriber(in int subId,
+ in List<PhysicalChannelConfig> configs);
}
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 67cfc3a7dd49..555f62c53387 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -14,13 +14,9 @@
package com.android.internal.util;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Build;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.EventLog;
import android.util.Log;
@@ -29,18 +25,14 @@ import android.util.SparseLongArray;
import com.android.internal.logging.EventLogTags;
/**
- * Class to track various latencies in SystemUI. It then outputs the latency to logcat so these
- * latencies can be captured by tests and then used for dashboards.
+ * Class to track various latencies in SystemUI. It then writes the latency to statsd and also
+ * outputs it to logcat so these latencies can be captured by tests and then used for dashboards.
* <p>
* This is currently only in Keyguard so it can be shared between SystemUI and Keyguard, but
* eventually we'd want to merge these two packages together so Keyguard can use common classes
* that are shared with SystemUI.
*/
public class LatencyTracker {
-
- private static final String ACTION_RELOAD_PROPERTY =
- "com.android.systemui.RELOAD_LATENCY_TRACKER_PROPERTY";
-
private static final String TAG = "LatencyTracker";
/**
@@ -82,7 +74,7 @@ public class LatencyTracker {
/*
* Time between we get a face acquired signal until we start with the unlock animation
*/
- public static final int ACTION_FACE_WAKE_AND_UNLOCK = 6;
+ public static final int ACTION_FACE_WAKE_AND_UNLOCK = 7;
private static final String[] NAMES = new String[] {
"expand panel",
@@ -94,38 +86,34 @@ public class LatencyTracker {
"rotate the screen",
"face wake-and-unlock" };
+ private static final int[] STATSD_ACTION = new int[] {
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FINGERPRINT_WAKE_AND_UNLOCK,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TURN_ON_SCREEN,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN,
+ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK,
+ };
+
private static LatencyTracker sLatencyTracker;
private final SparseLongArray mStartRtc = new SparseLongArray();
- private boolean mEnabled;
public static LatencyTracker getInstance(Context context) {
if (sLatencyTracker == null) {
- sLatencyTracker = new LatencyTracker(context.getApplicationContext());
+ sLatencyTracker = new LatencyTracker();
}
return sLatencyTracker;
}
- private LatencyTracker(Context context) {
- context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- reloadProperty();
- }
- }, new IntentFilter(ACTION_RELOAD_PROPERTY));
- reloadProperty();
- }
-
- private void reloadProperty() {
- mEnabled = SystemProperties.getBoolean("debug.systemui.latency_tracking", false);
- }
-
public static boolean isEnabled(Context ctx) {
return getInstance(ctx).isEnabled();
}
public boolean isEnabled() {
- return Build.IS_DEBUGGABLE && mEnabled;
+ return Build.IS_DEBUGGABLE;
}
/**
@@ -134,7 +122,7 @@ public class LatencyTracker {
* @param action The action to start. One of the ACTION_* values.
*/
public void onActionStart(int action) {
- if (!mEnabled) {
+ if (!isEnabled()) {
return;
}
Trace.asyncTraceBegin(Trace.TRACE_TAG_APP, NAMES[action], 0);
@@ -147,7 +135,7 @@ public class LatencyTracker {
* @param action The action to end. One of the ACTION_* values.
*/
public void onActionEnd(int action) {
- if (!mEnabled) {
+ if (!isEnabled()) {
return;
}
long endRtc = SystemClock.elapsedRealtime();
@@ -169,5 +157,7 @@ public class LatencyTracker {
public static void logAction(int action, int duration) {
Log.i(TAG, "action=" + action + " latency=" + duration);
EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration);
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.UI_ACTION_LATENCY_REPORTED, STATSD_ACTION[action], duration);
}
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 3f39478ffd43..5c4c5099bf4c 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2407,6 +2407,79 @@ static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env,
return AUDIO_JAVA_SUCCESS;
}
+static jint android_media_AudioSystem_setDevicesRoleForCapturePreset(
+ JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes,
+ jobjectArray jDeviceAddresses) {
+ AudioDeviceTypeAddrVector nDevices;
+ jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices);
+ if (results != NO_ERROR) {
+ return results;
+ }
+ int status = check_AudioSystem_Command(
+ AudioSystem::setDevicesRoleForCapturePreset((audio_source_t)capturePreset,
+ (device_role_t)role, nDevices));
+ return (jint)status;
+}
+
+static jint android_media_AudioSystem_addDevicesRoleForCapturePreset(
+ JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes,
+ jobjectArray jDeviceAddresses) {
+ AudioDeviceTypeAddrVector nDevices;
+ jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices);
+ if (results != NO_ERROR) {
+ return results;
+ }
+ int status = check_AudioSystem_Command(
+ AudioSystem::addDevicesRoleForCapturePreset((audio_source_t)capturePreset,
+ (device_role_t)role, nDevices));
+ return (jint)status;
+}
+
+static jint android_media_AudioSystem_removeDevicesRoleForCapturePreset(
+ JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes,
+ jobjectArray jDeviceAddresses) {
+ AudioDeviceTypeAddrVector nDevices;
+ jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices);
+ if (results != NO_ERROR) {
+ return results;
+ }
+ int status = check_AudioSystem_Command(
+ AudioSystem::removeDevicesRoleForCapturePreset((audio_source_t)capturePreset,
+ (device_role_t)role, nDevices));
+ return (jint)status;
+}
+
+static jint android_media_AudioSystem_clearDevicesRoleForCapturePreset(JNIEnv *env, jobject thiz,
+ jint capturePreset,
+ jint role) {
+ return (jint)check_AudioSystem_Command(
+ AudioSystem::clearDevicesRoleForCapturePreset((audio_source_t)capturePreset,
+ (device_role_t)role));
+}
+
+static jint android_media_AudioSystem_getDevicesForRoleAndCapturePreset(JNIEnv *env, jobject thiz,
+ jint capturePreset,
+ jint role,
+ jobject jDevices) {
+ AudioDeviceTypeAddrVector nDevices;
+ status_t status = check_AudioSystem_Command(
+ AudioSystem::getDevicesForRoleAndCapturePreset((audio_source_t)capturePreset,
+ (device_role_t)role, nDevices));
+ if (status != NO_ERROR) {
+ return (jint)status;
+ }
+ for (const auto &device : nDevices) {
+ jobject jAudioDeviceAttributes = NULL;
+ jint jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &device);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
+ env->CallBooleanMethod(jDevices, gListMethods.add, jAudioDeviceAttributes);
+ env->DeleteLocalRef(jAudioDeviceAttributes);
+ }
+ return AUDIO_JAVA_SUCCESS;
+}
+
static jint
android_media_AudioSystem_getDevicesForAttributes(JNIEnv *env, jobject thiz,
jobject jaa, jobjectArray jDeviceArray)
@@ -2558,6 +2631,16 @@ static const JNINativeMethod gMethods[] =
(void *)android_media_AudioSystem_removeDevicesRoleForStrategy},
{"getDevicesForRoleAndStrategy", "(IILjava/util/List;)I",
(void *)android_media_AudioSystem_getDevicesForRoleAndStrategy},
+ {"setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ (void *)android_media_AudioSystem_setDevicesRoleForCapturePreset},
+ {"addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ (void *)android_media_AudioSystem_addDevicesRoleForCapturePreset},
+ {"removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ (void *)android_media_AudioSystem_removeDevicesRoleForCapturePreset},
+ {"clearDevicesRoleForCapturePreset", "(II)I",
+ (void *)android_media_AudioSystem_clearDevicesRoleForCapturePreset},
+ {"getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I",
+ (void *)android_media_AudioSystem_getDevicesForRoleAndCapturePreset},
{"getDevicesForAttributes",
"(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAttributes;)I",
(void *)android_media_AudioSystem_getDevicesForAttributes},
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index 54567e5010c5..8177ec6df803 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -20,6 +20,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
+#include <attestation/HmacKeyManager.h>
#include <input/Input.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 2e396f247979..ce8b59941a5a 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -21,12 +21,13 @@
#include <android/graphics/matrix.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
-#include <utils/Log.h>
+#include <attestation/HmacKeyManager.h>
#include <input/Input.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
#include "android_os_Parcel.h"
-#include "android_view_MotionEvent.h"
#include "android_util_Binder.h"
+#include "android_view_MotionEvent.h"
#include "core_jni_helpers.h"
diff --git a/core/proto/android/providers/settings/config.proto b/core/proto/android/providers/settings/config.proto
index b0a70ef56dbc..d433c0e1859d 100644
--- a/core/proto/android/providers/settings/config.proto
+++ b/core/proto/android/providers/settings/config.proto
@@ -31,11 +31,14 @@ message ConfigSettingsProto {
repeated SettingProto activity_manager_settings = 4;
repeated SettingProto app_compat_settings = 5;
repeated SettingProto autofill_settings = 6;
+ repeated SettingProto blobstore_settings = 23;
repeated SettingProto connectivity_settings = 7;
repeated SettingProto content_capture_settings = 8;
- repeated SettingProto dex_boot_settings = 9;
+ repeated SettingProto device_idle_settings = 24;
+ reserved 9; // dex_boot_settings
repeated SettingProto game_driver_settings = 10;
repeated SettingProto input_native_boot_settings = 11;
+ repeated SettingProto job_scheduler_settings = 25;
repeated SettingProto netd_native_settings = 12;
repeated SettingProto privacy_settings = 13;
repeated SettingProto rollback_boot_settings = 14;
@@ -47,7 +50,8 @@ message ConfigSettingsProto {
repeated SettingProto systemui_settings = 20;
repeated SettingProto telephony_settings = 21;
repeated SettingProto textclassifier_settings = 22;
- repeated SettingProto blobstore_settings = 23;
+
+ // Next tag: 26
message NamespaceProto {
optional string namespace = 1;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 9fccdaf9684f..3ec14c01c363 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -292,7 +292,7 @@ message GlobalSettingsProto {
optional SettingProto name = 1;
optional SettingProto provisioned = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto provisioning_mobile_data_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto idle_constants = 4;
+ reserved 4; // idle_constants
optional SettingProto policy_constants = 5;
optional SettingProto demo_mode = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index ff0ba8dd5ad4..3a59a16b54ca 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -316,6 +316,7 @@ message ActivityRecordProto {
optional bool front_of_task = 28;
optional int32 proc_id = 29;
optional bool translucent = 30;
+ optional bool pip_auto_enter_allowed = 31;
}
/* represents WindowToken */
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2b511706d024..20ef017f59f8 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2784,7 +2784,11 @@
exactly one parameter of type View. For instance, if you specify
<code>android:onClick="sayHello"</code>, you must declare a
<code>public void sayHello(View v)</code> method of your context
- (typically, your Activity). -->
+ (typically, your Activity).
+ {@deprecated View actually traverses the Context
+ hierarchy looking for the relevant method, which is fragile (an intermediate
+ ContextWrapper adding a same-named method would change behavior) and restricts
+ bytecode optimizers such as R8. Instead, use View.setOnClickListener.}-->
<attr name="onClick" format="string" />
<!-- Defines over-scrolling behavior. This property is used only if the
@@ -7505,7 +7509,11 @@
<attr name="enabled" />
<!-- Name of a method on the Context used to inflate the menu that will be
- called when the item is clicked. -->
+ called when the item is clicked.
+ {@deprecated Menu actually traverses the Context hierarchy looking for the
+ relevant method, which is fragile (an intermediate ContextWrapper adding a
+ same-named method would change behavior) and restricts bytecode optimizers
+ such as R8. Instead, use MenuItem.setOnMenuItemClickListener.} -->
<attr name="onClick" />
<!-- How this item should display in the Action Bar, if present. -->
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 5c16772488d0..4cf6715ba0ca 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -24,6 +24,7 @@ import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -117,7 +118,15 @@ public class ViewRootImplTest {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
- // A window which fits system bars must fit IME, unless its type is toast or system alert.
+ assertEquals(Type.systemBars(), attrs.getFitInsetsTypes());
+ }
+
+ @Test
+ public void adjustLayoutParamsForCompatibility_fitSystemBarsAndIme() {
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ attrs.softInputMode |= SOFT_INPUT_ADJUST_RESIZE;
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
assertEquals(Type.systemBars() | Type.ime(), attrs.getFitInsetsTypes());
}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 7480a200ee4e..ece5037de15f 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -23,8 +23,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.os.Handler;
import android.view.FrameMetrics;
@@ -66,6 +68,9 @@ public class FrameTrackerTest {
Handler handler = mRule.getActivity().getMainThreadHandler();
mWrapper = Mockito.spy(new FrameMetricsWrapper());
+ // For simplicity - provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP
+ when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
+ .then(unusedInvocation -> System.nanoTime());
mRenderer = Mockito.spy(new ThreadedRendererWrapper(view.getThreadedRenderer()));
doNothing().when(mRenderer).addObserver(any());
doNothing().when(mRenderer).removeObserver(any());
@@ -76,55 +81,104 @@ public class FrameTrackerTest {
}
@Test
- public void testIsJankyFrame() {
- // We skip the first frame.
- doReturn(1L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
- doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
- .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
- assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+ public void testIgnoresSecondBegin() {
+ // Observer should be only added once in continuous calls.
+ mTracker.begin();
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+ }
- // Should exceed the criteria.
- doReturn(0L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
- doReturn(TimeUnit.MILLISECONDS.toNanos(20L))
- .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
- assertThat(mTracker.isJankyFrame(mWrapper)).isTrue();
+ @Test
+ public void testOnlyFirstFrameOverThreshold() {
+ // Just provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP
+ when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
+ .then(unusedInvocation -> System.nanoTime());
- // Should be safe.
- doReturn(TimeUnit.MILLISECONDS.toNanos(10L))
- .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
- assertThat(mTracker.isJankyFrame(mWrapper)).isFalse();
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // send first frame with a long duration - should not be taken into account
+ setupFirstFrameMockWithDuration(100);
+ mTracker.onFrameMetricsAvailable(0);
+
+ // send another frame with a short duration - should not be considered janky
+ setupOtherFrameMockWithDuration(5);
+ mTracker.onFrameMetricsAvailable(0);
+
+ // end the trace session, the last janky frame is after the end() so is discarded.
+ mTracker.end();
+ setupOtherFrameMockWithDuration(500);
+ mTracker.onFrameMetricsAvailable(0);
+
+ verify(mRenderer).removeObserver(any());
+ verify(mTracker, never()).triggerPerfetto();
}
@Test
- public void testBeginEnd() {
- // assert the initial values
- assertThat(mTracker.mBeginTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
- assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
-
- // Observer should be only added once in continuous calls.
+ public void testOtherFrameOverThreshold() {
mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // send first frame - not janky
+ setupFirstFrameMockWithDuration(4);
+ mTracker.onFrameMetricsAvailable(0);
+
+ // send another frame - should be considered janky
+ setupOtherFrameMockWithDuration(40);
+ mTracker.onFrameMetricsAvailable(0);
+
+ // end the trace session
+ mTracker.end();
+ setupOtherFrameMockWithDuration(5);
+ mTracker.onFrameMetricsAvailable(0);
+
+ verify(mRenderer).removeObserver(any());
+
+ // We detected a janky frame - trigger Perfetto
+ verify(mTracker).triggerPerfetto();
+ }
+
+ @Test
+ public void testLastFrameOverThresholdBeforeEnd() {
mTracker.begin();
verify(mRenderer, only()).addObserver(any());
- // assert the values after begin call.
- assertThat(mTracker.mBeginTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
- assertThat(mTracker.mEndTime).isEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
+ // send first frame - not janky
+ setupFirstFrameMockWithDuration(4);
+ mTracker.onFrameMetricsAvailable(0);
- // simulate the callback during trace session
- // assert the isJankyFrame should be invoked as well.
- doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
- doReturn(true).when(mTracker).isJankyFrame(any());
+ // send another frame - not janky
+ setupOtherFrameMockWithDuration(4);
mTracker.onFrameMetricsAvailable(0);
- verify(mTracker).isJankyFrame(any());
- // end the trace session, simulate a callback came after the end call.
- // assert the end time should be set, the observer should be removed.
- // triggerPerfetto should be invoked as well.
+ // end the trace session, simulate one more valid callback came after the end call.
+ when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
+ .thenReturn(System.nanoTime());
+ setupOtherFrameMockWithDuration(50);
mTracker.end();
- doReturn(System.nanoTime()).when(mWrapper).getMetric(FrameMetrics.VSYNC_TIMESTAMP);
- assertThat(mTracker.mEndTime).isNotEqualTo(FrameTracker.UNKNOWN_TIMESTAMP);
mTracker.onFrameMetricsAvailable(0);
+
+ // One more callback with VSYNC after the end() timestamp.
+ when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
+ .thenReturn(System.nanoTime());
+ setupOtherFrameMockWithDuration(5);
+ mTracker.onFrameMetricsAvailable(0);
+
verify(mRenderer).removeObserver(any());
+
+ // We detected a janky frame - trigger Perfetto
verify(mTracker).triggerPerfetto();
}
+
+ private void setupFirstFrameMockWithDuration(long durationMillis) {
+ doReturn(1L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(durationMillis))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ }
+
+ private void setupOtherFrameMockWithDuration(long durationMillis) {
+ doReturn(0L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ doReturn(TimeUnit.MILLISECONDS.toNanos(durationMillis))
+ .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index 02870a53773e..7f4e9ada7b22 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -20,6 +20,9 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.app.EmptyActivity;
@@ -41,6 +44,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
/**
* Tests {@link DecorContext}.
@@ -63,13 +67,18 @@ public final class DecorContextTest {
@Test
public void testDecorContextWithDefaultDisplay() {
+ final Context baseContext = Mockito.spy(mContext.getApplicationContext());
Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(), DEFAULT_DISPLAY,
new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
final Context defaultDisplayContext = mContext.createDisplayContext(defaultDisplay);
final PhoneWindow window = new PhoneWindow(defaultDisplayContext);
- DecorContext context = new DecorContext(mContext.getApplicationContext(), window);
+ DecorContext context = new DecorContext(baseContext, window);
assertDecorContextDisplay(DEFAULT_DISPLAY, context);
+
+ // TODO(b/166174272): Creating a display context for the default display will result
+ // in additional resource creation.
+ verify(baseContext, never()).createDisplayContext(any());
}
@Test
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 1ab4c6385ac1..fe6eeeb66e40 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -28,12 +28,14 @@ key A {
label: 'A'
base: 'a'
shift, capslock: 'A'
+ shift+capslock: 'a'
}
key B {
label: 'B'
base: 'b'
shift, capslock: 'B'
+ shift+capslock: 'b'
}
key C {
@@ -42,12 +44,14 @@ key C {
shift, capslock: 'C'
alt: '\u00e7'
shift+alt: '\u00c7'
+ shift+capslock: 'c'
}
key D {
label: 'D'
base: 'd'
shift, capslock: 'D'
+ shift+capslock: 'd'
}
key E {
@@ -55,24 +59,28 @@ key E {
base: 'e'
shift, capslock: 'E'
alt: '\u0301'
+ shift+capslock: 'e'
}
key F {
label: 'F'
base: 'f'
shift, capslock: 'F'
+ shift+capslock: 'f'
}
key G {
label: 'G'
base: 'g'
shift, capslock: 'G'
+ shift+capslock: 'g'
}
key H {
label: 'H'
base: 'h'
shift, capslock: 'H'
+ shift+capslock: 'h'
}
key I {
@@ -80,30 +88,35 @@ key I {
base: 'i'
shift, capslock: 'I'
alt: '\u0302'
+ shift+capslock: 'i'
}
key J {
label: 'J'
base: 'j'
shift, capslock: 'J'
+ shift+capslock: 'j'
}
key K {
label: 'K'
base: 'k'
shift, capslock: 'K'
+ shift+capslock: 'k'
}
key L {
label: 'L'
base: 'l'
shift, capslock: 'L'
+ shift+capslock: 'l'
}
key M {
label: 'M'
base: 'm'
shift, capslock: 'M'
+ shift+capslock: 'm'
}
key N {
@@ -111,30 +124,35 @@ key N {
base: 'n'
shift, capslock: 'N'
alt: '\u0303'
+ shift+capslock: 'n'
}
key O {
label: 'O'
base: 'o'
shift, capslock: 'O'
+ shift+capslock: 'o'
}
key P {
label: 'P'
base: 'p'
shift, capslock: 'P'
+ shift+capslock: 'p'
}
key Q {
label: 'Q'
base: 'q'
shift, capslock: 'Q'
+ shift+capslock: 'q'
}
key R {
label: 'R'
base: 'r'
shift, capslock: 'R'
+ shift+capslock: 'r'
}
key S {
@@ -142,12 +160,14 @@ key S {
base: 's'
shift, capslock: 'S'
alt: '\u00df'
+ shift+capslock: 's'
}
key T {
label: 'T'
base: 't'
shift, capslock: 'T'
+ shift+capslock: 't'
}
key U {
@@ -155,36 +175,42 @@ key U {
base: 'u'
shift, capslock: 'U'
alt: '\u0308'
+ shift+capslock: 'u'
}
key V {
label: 'V'
base: 'v'
shift, capslock: 'V'
+ shift+capslock: 'v'
}
key W {
label: 'W'
base: 'w'
shift, capslock: 'W'
+ shift+capslock: 'w'
}
key X {
label: 'X'
base: 'x'
shift, capslock: 'X'
+ shift+capslock: 'x'
}
key Y {
label: 'Y'
base: 'y'
shift, capslock: 'Y'
+ shift+capslock: 'y'
}
key Z {
label: 'Z'
base: 'z'
shift, capslock: 'Z'
+ shift+capslock: 'z'
}
key 0 {
diff --git a/packages/SystemUI/res/anim/forced_resizable_enter.xml b/libs/WindowManager/Shell/res/anim/forced_resizable_enter.xml
index 01b8fdbe4437..01b8fdbe4437 100644
--- a/packages/SystemUI/res/anim/forced_resizable_enter.xml
+++ b/libs/WindowManager/Shell/res/anim/forced_resizable_enter.xml
diff --git a/packages/SystemUI/res/anim/forced_resizable_exit.xml b/libs/WindowManager/Shell/res/anim/forced_resizable_exit.xml
index 6f316a75dbed..6f316a75dbed 100644
--- a/packages/SystemUI/res/anim/forced_resizable_exit.xml
+++ b/libs/WindowManager/Shell/res/anim/forced_resizable_exit.xml
diff --git a/packages/SystemUI/res/layout/divider.xml b/libs/WindowManager/Shell/res/layout/divider.xml
index f1f0df054240..f1f0df054240 100644
--- a/packages/SystemUI/res/layout/divider.xml
+++ b/libs/WindowManager/Shell/res/layout/divider.xml
diff --git a/packages/SystemUI/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index 70e5451eed57..ad870252d819 100644
--- a/packages/SystemUI/res/layout/docked_stack_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<com.android.systemui.stackdivider.DividerView
+<com.android.wm.shell.splitscreen.DividerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
@@ -24,15 +24,15 @@
android:id="@+id/docked_divider_background"
android:background="@color/docked_divider_background"/>
- <com.android.systemui.stackdivider.MinimizedDockShadow
+ <com.android.wm.shell.splitscreen.MinimizedDockShadow
style="@style/DockedDividerMinimizedShadow"
android:id="@+id/minimized_dock_shadow"
android:alpha="0"/>">
- <com.android.systemui.stackdivider.DividerHandleView
+ <com.android.wm.shell.splitscreen.DividerHandleView
style="@style/DockedDividerHandle"
android:id="@+id/docked_divider_handle"
android:contentDescription="@string/accessibility_divider"
android:background="@null"/>
-</com.android.systemui.stackdivider.DividerView>
+</com.android.wm.shell.splitscreen.DividerView>
diff --git a/packages/SystemUI/res/layout/forced_resizable_activity.xml b/libs/WindowManager/Shell/res/layout/forced_resizable_activity.xml
index 3c778c431a2e..3c778c431a2e 100644
--- a/packages/SystemUI/res/layout/forced_resizable_activity.xml
+++ b/libs/WindowManager/Shell/res/layout/forced_resizable_activity.xml
diff --git a/libs/WindowManager/Shell/res/values-land/dimens.xml b/libs/WindowManager/Shell/res/values-land/dimens.xml
new file mode 100644
index 000000000000..77a601ddf440
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values-land/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+ <dimen name="docked_divider_handle_width">2dp</dimen>
+ <dimen name="docked_divider_handle_height">16dp</dimen>
+</resources> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml
new file mode 100644
index 000000000000..863bb69d4034
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values-land/styles.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="DockedDividerBackground">
+ <item name="android:layout_width">10dp</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ </style>
+
+ <style name="DockedDividerHandle">
+ <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:layout_width">48dp</item>
+ <item name="android:layout_height">96dp</item>
+ </style>
+
+ <style name="DockedDividerMinimizedShadow">
+ <item name="android:layout_width">8dp</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+</resources>
+
diff --git a/libs/WindowManager/Shell/res/values-sw600dp/config.xml b/libs/WindowManager/Shell/res/values-sw600dp/config.xml
new file mode 100644
index 000000000000..f194532f1e0d
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values-sw600dp/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <!-- Animation duration when using long press on recents to dock -->
+ <integer name="long_press_dock_anim_duration">290</integer>
+</resources> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
new file mode 100644
index 000000000000..6a19083e3788
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <color name="docked_divider_background">#ff000000</color>
+ <color name="docked_divider_handle">#ffffff</color>
+ <drawable name="forced_resizable_background">#59000000</drawable>
+ <color name="minimize_dock_shadow_start">#60000000</color>
+ <color name="minimize_dock_shadow_end">#00000000</color>
+</resources> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 245c0725c2a8..39efd0768eaa 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -26,4 +26,7 @@
<!-- Allow PIP to enable round corner, see also R.dimen.pip_corner_radius -->
<bool name="config_pipEnableRoundCorner">false</bool>
+
+ <!-- Animation duration when using long press on recents to dock -->
+ <integer name="long_press_dock_anim_duration">250</integer>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1c1217681b9f..ce690281b491 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -56,4 +56,10 @@
<dimen name="pip_resize_handle_size">12dp</dimen>
<dimen name="pip_resize_handle_margin">4dp</dimen>
<dimen name="pip_resize_handle_padding">0dp</dimen>
+
+ <!-- How high we lift the divider when touching -->
+ <dimen name="docked_stack_divider_lift_elevation">4dp</dimen>
+
+ <dimen name="docked_divider_handle_width">16dp</dimen>
+ <dimen name="docked_divider_handle_height">2dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/ids.xml b/libs/WindowManager/Shell/res/values/ids.xml
index ed20398f309d..fb892388cf74 100644
--- a/libs/WindowManager/Shell/res/values/ids.xml
+++ b/libs/WindowManager/Shell/res/values/ids.xml
@@ -16,4 +16,11 @@
-->
<resources>
<item type="id" name="action_pip_resize" />
+
+ <!-- Accessibility actions for the docked stack divider -->
+ <item type="id" name="action_move_tl_full" />
+ <item type="id" name="action_move_tl_70" />
+ <item type="id" name="action_move_tl_50" />
+ <item type="id" name="action_move_tl_30" />
+ <item type="id" name="action_move_rb_full" />
</resources>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 6752b56fcdf3..cad924771cd3 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -53,4 +53,39 @@
<!-- TODO Deprecated. Label for PIP the drag to dismiss hint. DO NOT TRANSLATE [CHAR LIMIT=NONE]-->
<string name="pip_phone_dismiss_hint">Drag down to dismiss</string>
+
+ <!-- Multi-Window strings -->
+ <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed in split-screen and that things might crash/not work properly [CHAR LIMIT=NONE] -->
+ <string name="dock_forced_resizable">App may not work with split-screen.</string>
+ <!-- Warning message when we try to dock a non-resizeable task and launch it in fullscreen instead. -->
+ <string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string>
+ <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed on a secondary display and that things might crash/not work properly [CHAR LIMIT=NONE] -->
+ <string name="forced_resizable_secondary_display">App may not work on a secondary display.</string>
+ <!-- Warning message when we try to launch a non-resizeable activity on a secondary display and launch it on the primary instead. -->
+ <string name="activity_launch_on_secondary_display_failed_text">App does not support launch on secondary displays.</string>
+
+ <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->
+ <string name="accessibility_divider">Split-screen divider</string>
+
+ <!-- Accessibility action for moving docked stack divider to make the left screen full screen [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_left_full">Left full screen</string>
+ <!-- Accessibility action for moving docked stack divider to make the left screen 70% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_left_70">Left 70%</string>
+ <!-- Accessibility action for moving docked stack divider to make the left screen 50% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_left_50">Left 50%</string>
+ <!-- Accessibility action for moving docked stack divider to make the left screen 30% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_left_30">Left 30%</string>
+ <!-- Accessibility action for moving docked stack divider to make the right screen full screen [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_right_full">Right full screen</string>
+
+ <!-- Accessibility action for moving docked stack divider to make the top screen full screen [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_top_full">Top full screen</string>
+ <!-- Accessibility action for moving docked stack divider to make the top screen 70% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_top_70">Top 70%</string>
+ <!-- Accessibility action for moving docked stack divider to make the top screen 50% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_top_50">Top 50%</string>
+ <!-- Accessibility action for moving docked stack divider to make the top screen 30% [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_top_30">Top 30%</string>
+ <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
+ <string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
new file mode 100644
index 000000000000..fffcd33f7992
--- /dev/null
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
+ <style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
+ <item name="android:windowBackground">@drawable/forced_resizable_background</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
+ </style>
+
+ <style name="Animation.ForcedResizable" parent="@android:style/Animation">
+ <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
+
+ <!-- If the target stack doesn't have focus, we do a task to front animation. -->
+ <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item>
+ <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
+ </style>
+
+ <style name="DockedDividerBackground">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">10dp</item>
+ <item name="android:layout_gravity">center_vertical</item>
+ </style>
+
+ <style name="DockedDividerMinimizedShadow">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">8dp</item>
+ </style>
+
+ <style name="DockedDividerHandle">
+ <item name="android:layout_gravity">center_horizontal</item>
+ <item name="android:layout_width">96dp</item>
+ <item name="android:layout_height">48dp</item>
+ </style>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java
index 12749fd8fce2..357f777e1270 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/FlingAnimationUtils.java
@@ -11,10 +11,10 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.statusbar;
+package com.android.wm.shell.animation;
import android.animation.Animator;
import android.util.DisplayMetrics;
@@ -23,11 +23,6 @@ import android.view.ViewPropertyAnimator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
-import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.notification.NotificationUtils;
-
-import javax.inject.Inject;
-
/**
* Utility class to calculate general fling animation when the finger is released.
*/
@@ -63,9 +58,9 @@ public class FlingAnimationUtils {
/**
* @param maxLengthSeconds the longest duration an animation can become in seconds
- * @param speedUpFactor a factor from 0 to 1 how much the slow down should be shifted towards
- * the end of the animation. 0 means it's at the beginning and no
- * acceleration will take place.
+ * @param speedUpFactor a factor from 0 to 1 how much the slow down should be shifted towards
+ * the end of the animation. 0 means it's at the beginning and no
+ * acceleration will take place.
*/
public FlingAnimationUtils(DisplayMetrics displayMetrics, float maxLengthSeconds,
float speedUpFactor) {
@@ -74,19 +69,19 @@ public class FlingAnimationUtils {
/**
* @param maxLengthSeconds the longest duration an animation can become in seconds
- * @param speedUpFactor a factor from 0 to 1 how much the slow down should be shifted towards
- * the end of the animation. 0 means it's at the beginning and no
- * acceleration will take place.
- * @param x2 the x value to take for the second point of the bezier spline. If a value below 0
- * is provided, the value is automatically calculated.
- * @param y2 the y value to take for the second point of the bezier spline
+ * @param speedUpFactor a factor from 0 to 1 how much the slow down should be shifted towards
+ * the end of the animation. 0 means it's at the beginning and no
+ * acceleration will take place.
+ * @param x2 the x value to take for the second point of the bezier spline. If a
+ * value below 0 is provided, the value is automatically calculated.
+ * @param y2 the y value to take for the second point of the bezier spline
*/
public FlingAnimationUtils(DisplayMetrics displayMetrics, float maxLengthSeconds,
float speedUpFactor, float x2, float y2) {
mMaxLengthSeconds = maxLengthSeconds;
mSpeedUpFactor = speedUpFactor;
if (x2 < 0) {
- mLinearOutSlowInX2 = NotificationUtils.interpolate(LINEAR_OUT_SLOW_IN_X2,
+ mLinearOutSlowInX2 = interpolate(LINEAR_OUT_SLOW_IN_X2,
LINEAR_OUT_SLOW_IN_X2_MAX,
mSpeedUpFactor);
} else {
@@ -102,10 +97,10 @@ public class FlingAnimationUtils {
* Applies the interpolator and length to the animator, such that the fling animation is
* consistent with the finger motion.
*
- * @param animator the animator to apply
+ * @param animator the animator to apply
* @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
*/
public void apply(Animator animator, float currValue, float endValue, float velocity) {
apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue));
@@ -115,10 +110,10 @@ public class FlingAnimationUtils {
* Applies the interpolator and length to the animator, such that the fling animation is
* consistent with the finger motion.
*
- * @param animator the animator to apply
+ * @param animator the animator to apply
* @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
*/
public void apply(ViewPropertyAnimator animator, float currValue, float endValue,
float velocity) {
@@ -129,10 +124,10 @@ public class FlingAnimationUtils {
* Applies the interpolator and length to the animator, such that the fling animation is
* consistent with the finger motion.
*
- * @param animator the animator to apply
- * @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param animator the animator to apply
+ * @param currValue the current value
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
* @param maxDistance the maximum distance for this interaction; the maximum animation length
* gets multiplied by the ratio between the actual distance and this value
*/
@@ -140,18 +135,18 @@ public class FlingAnimationUtils {
float maxDistance) {
AnimatorProperties properties = getProperties(currValue, endValue, velocity,
maxDistance);
- animator.setDuration(properties.duration);
- animator.setInterpolator(properties.interpolator);
+ animator.setDuration(properties.mDuration);
+ animator.setInterpolator(properties.mInterpolator);
}
/**
* Applies the interpolator and length to the animator, such that the fling animation is
* consistent with the finger motion.
*
- * @param animator the animator to apply
- * @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param animator the animator to apply
+ * @param currValue the current value
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
* @param maxDistance the maximum distance for this interaction; the maximum animation length
* gets multiplied by the ratio between the actual distance and this value
*/
@@ -159,8 +154,8 @@ public class FlingAnimationUtils {
float velocity, float maxDistance) {
AnimatorProperties properties = getProperties(currValue, endValue, velocity,
maxDistance);
- animator.setDuration(properties.duration);
- animator.setInterpolator(properties.interpolator);
+ animator.setDuration(properties.mDuration);
+ animator.setInterpolator(properties.mInterpolator);
}
private AnimatorProperties getProperties(float currValue,
@@ -171,28 +166,28 @@ public class FlingAnimationUtils {
float velAbs = Math.abs(velocity);
float velocityFactor = mSpeedUpFactor == 0.0f
? 1.0f : Math.min(velAbs / HIGH_VELOCITY_DP_PER_SECOND, 1.0f);
- float startGradient = NotificationUtils.interpolate(LINEAR_OUT_SLOW_IN_START_GRADIENT,
+ float startGradient = interpolate(LINEAR_OUT_SLOW_IN_START_GRADIENT,
mY2 / mLinearOutSlowInX2, velocityFactor);
float durationSeconds = startGradient * diff / velAbs;
Interpolator slowInInterpolator = getInterpolator(startGradient, velocityFactor);
if (durationSeconds <= maxLengthSeconds) {
- mAnimatorProperties.interpolator = slowInInterpolator;
+ mAnimatorProperties.mInterpolator = slowInInterpolator;
} else if (velAbs >= mMinVelocityPxPerSecond) {
// Cross fade between fast-out-slow-in and linear interpolator with current velocity.
durationSeconds = maxLengthSeconds;
- VelocityInterpolator velocityInterpolator
- = new VelocityInterpolator(durationSeconds, velAbs, diff);
+ VelocityInterpolator velocityInterpolator = new VelocityInterpolator(
+ durationSeconds, velAbs, diff);
InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
velocityInterpolator, slowInInterpolator, Interpolators.LINEAR_OUT_SLOW_IN);
- mAnimatorProperties.interpolator = superInterpolator;
+ mAnimatorProperties.mInterpolator = superInterpolator;
} else {
// Just use a normal interpolator which doesn't take the velocity into account.
durationSeconds = maxLengthSeconds;
- mAnimatorProperties.interpolator = Interpolators.FAST_OUT_SLOW_IN;
+ mAnimatorProperties.mInterpolator = Interpolators.FAST_OUT_SLOW_IN;
}
- mAnimatorProperties.duration = (long) (durationSeconds * 1000);
+ mAnimatorProperties.mDuration = (long) (durationSeconds * 1000);
return mAnimatorProperties;
}
@@ -225,10 +220,10 @@ public class FlingAnimationUtils {
* consistent with the finger motion for the case when the animation is making something
* disappear.
*
- * @param animator the animator to apply
- * @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param animator the animator to apply
+ * @param currValue the current value
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
* @param maxDistance the maximum distance for this interaction; the maximum animation length
* gets multiplied by the ratio between the actual distance and this value
*/
@@ -236,8 +231,8 @@ public class FlingAnimationUtils {
float velocity, float maxDistance) {
AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity,
maxDistance);
- animator.setDuration(properties.duration);
- animator.setInterpolator(properties.interpolator);
+ animator.setDuration(properties.mDuration);
+ animator.setInterpolator(properties.mInterpolator);
}
/**
@@ -245,10 +240,10 @@ public class FlingAnimationUtils {
* consistent with the finger motion for the case when the animation is making something
* disappear.
*
- * @param animator the animator to apply
- * @param currValue the current value
- * @param endValue the end value of the animator
- * @param velocity the current velocity of the motion
+ * @param animator the animator to apply
+ * @param currValue the current value
+ * @param endValue the end value of the animator
+ * @param velocity the current velocity of the motion
* @param maxDistance the maximum distance for this interaction; the maximum animation length
* gets multiplied by the ratio between the actual distance and this value
*/
@@ -256,8 +251,8 @@ public class FlingAnimationUtils {
float velocity, float maxDistance) {
AnimatorProperties properties = getDismissingProperties(currValue, endValue, velocity,
maxDistance);
- animator.setDuration(properties.duration);
- animator.setInterpolator(properties.interpolator);
+ animator.setDuration(properties.mDuration);
+ animator.setInterpolator(properties.mInterpolator);
}
private AnimatorProperties getDismissingProperties(float currValue, float endValue,
@@ -272,24 +267,24 @@ public class FlingAnimationUtils {
Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, LINEAR_OUT_FASTER_IN_X2, y2);
float durationSeconds = startGradient * diff / velAbs;
if (durationSeconds <= maxLengthSeconds) {
- mAnimatorProperties.interpolator = mLinearOutFasterIn;
+ mAnimatorProperties.mInterpolator = mLinearOutFasterIn;
} else if (velAbs >= mMinVelocityPxPerSecond) {
// Cross fade between linear-out-faster-in and linear interpolator with current
// velocity.
durationSeconds = maxLengthSeconds;
- VelocityInterpolator velocityInterpolator
- = new VelocityInterpolator(durationSeconds, velAbs, diff);
+ VelocityInterpolator velocityInterpolator = new VelocityInterpolator(
+ durationSeconds, velAbs, diff);
InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
velocityInterpolator, mLinearOutFasterIn, Interpolators.LINEAR_OUT_SLOW_IN);
- mAnimatorProperties.interpolator = superInterpolator;
+ mAnimatorProperties.mInterpolator = superInterpolator;
} else {
// Just use a normal interpolator which doesn't take the velocity into account.
durationSeconds = maxLengthSeconds;
- mAnimatorProperties.interpolator = Interpolators.FAST_OUT_LINEAR_IN;
+ mAnimatorProperties.mInterpolator = Interpolators.FAST_OUT_LINEAR_IN;
}
- mAnimatorProperties.duration = (long) (durationSeconds * 1000);
+ mAnimatorProperties.mDuration = (long) (durationSeconds * 1000);
return mAnimatorProperties;
}
@@ -361,10 +356,11 @@ public class FlingAnimationUtils {
}
private static class AnimatorProperties {
- Interpolator interpolator;
- long duration;
+ Interpolator mInterpolator;
+ long mDuration;
}
+ /** Builder for {@link #FlingAnimationUtils}. */
public static class Builder {
private final DisplayMetrics mDisplayMetrics;
float mMaxLengthSeconds;
@@ -372,32 +368,39 @@ public class FlingAnimationUtils {
float mX2;
float mY2;
- @Inject
public Builder(DisplayMetrics displayMetrics) {
mDisplayMetrics = displayMetrics;
reset();
}
+ /** Sets the longest duration an animation can become in seconds. */
public Builder setMaxLengthSeconds(float maxLengthSeconds) {
mMaxLengthSeconds = maxLengthSeconds;
return this;
}
+ /**
+ * Sets the factor for how much the slow down should be shifted towards the end of the
+ * animation.
+ */
public Builder setSpeedUpFactor(float speedUpFactor) {
mSpeedUpFactor = speedUpFactor;
return this;
}
+ /** Sets the x value to take for the second point of the bezier spline. */
public Builder setX2(float x2) {
mX2 = x2;
return this;
}
+ /** Sets the y value to take for the second point of the bezier spline. */
public Builder setY2(float y2) {
mY2 = y2;
return this;
}
+ /** Resets all parameters of the builder. */
public Builder reset() {
mMaxLengthSeconds = 0;
mSpeedUpFactor = 0.0f;
@@ -407,9 +410,14 @@ public class FlingAnimationUtils {
return this;
}
+ /** Builds {@link #FlingAnimationUtils}. */
public FlingAnimationUtils build() {
return new FlingAnimationUtils(mDisplayMetrics, mMaxLengthSeconds, mSpeedUpFactor,
mX2, mY2);
}
}
+
+ private static float interpolate(float start, float end, float amount) {
+ return start * (1.0f - amount) + end * amount;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
new file mode 100644
index 000000000000..b794b91568fc
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.animation;
+
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+/**
+ * Common interpolators used in wm shell library.
+ */
+public class Interpolators {
+ /**
+ * Interpolator for fast out linear in animation.
+ */
+ public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
+
+ /**
+ * Interpolator for fast out slow in animation.
+ */
+ public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
+
+ /**
+ * Interpolator for linear out slow in animation.
+ */
+ public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
+
+ /**
+ * Interpolator to be used when animating a move based on a click. Pair with enough duration.
+ */
+ public static final Interpolator TOUCH_RESPONSE = new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java
index 13ed02e9513e..9cb125087cd9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SyncTransactionQueue.java
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.common;
+import android.annotation.NonNull;
import android.os.Handler;
import android.util.Slog;
import android.view.SurfaceControl;
@@ -23,17 +24,13 @@ import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback;
import android.window.WindowOrganizer;
-import androidx.annotation.NonNull;
-
-import com.android.wm.shell.common.TransactionPool;
-
import java.util.ArrayList;
/**
* Helper for serializing sync-transactions and corresponding callbacks.
*/
-class SyncTransactionQueue {
- private static final boolean DEBUG = SplitScreenController.DEBUG;
+public final class SyncTransactionQueue {
+ private static final boolean DEBUG = false;
private static final String TAG = "SyncTransactionQueue";
// Just a little longer than the sync-engine timeout of 5s
@@ -58,7 +55,7 @@ class SyncTransactionQueue {
}
};
- SyncTransactionQueue(TransactionPool pool, Handler handler) {
+ public SyncTransactionQueue(TransactionPool pool, Handler handler) {
mTransactionPool = pool;
mHandler = handler;
}
@@ -66,7 +63,7 @@ class SyncTransactionQueue {
/**
* Queues a sync transaction to be sent serially to WM.
*/
- void queue(WindowContainerTransaction wct) {
+ public void queue(WindowContainerTransaction wct) {
SyncCallback cb = new SyncCallback(wct);
synchronized (mQueue) {
if (DEBUG) Slog.d(TAG, "Queueing up " + wct);
@@ -82,7 +79,7 @@ class SyncTransactionQueue {
* Otherwise just returns without queueing.
* @return {@code true} if queued, {@code false} if not.
*/
- boolean queueIfWaiting(WindowContainerTransaction wct) {
+ public boolean queueIfWaiting(WindowContainerTransaction wct) {
synchronized (mQueue) {
if (mQueue.isEmpty()) {
if (DEBUG) Slog.d(TAG, "Nothing in queue, so skip queueing up " + wct);
@@ -102,7 +99,7 @@ class SyncTransactionQueue {
* Runs a runnable in sync with sync transactions (ie. when the current in-flight transaction
* returns. If there are no transactions in-flight, runnable executes immediately.
*/
- void runInSync(TransactionRunnable runnable) {
+ public void runInSync(TransactionRunnable runnable) {
synchronized (mQueue) {
if (DEBUG) Slog.d(TAG, "Run in sync. mInFlight=" + mInFlight);
if (mInFlight != null) {
@@ -127,7 +124,9 @@ class SyncTransactionQueue {
t.close();
}
- interface TransactionRunnable {
+ /** Task to run with transaction. */
+ public interface TransactionRunnable {
+ /** Runs with transaction. */
void runWithTransaction(SurfaceControl.Transaction t);
}
@@ -154,7 +153,7 @@ class SyncTransactionQueue {
@Override
public void onTransactionReady(int id,
- @androidx.annotation.NonNull SurfaceControl.Transaction t) {
+ @NonNull SurfaceControl.Transaction t) {
mHandler.post(() -> {
synchronized (mQueue) {
if (mId != id) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
index a10242a689a2..2cb1fff4cde6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -28,43 +28,41 @@ import android.util.AttributeSet;
import android.util.Property;
import android.view.View;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
/**
* View for the handle in the docked stack divider.
*/
-class DividerHandleView extends View {
-
- private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
- = new Property<DividerHandleView, Integer>(Integer.class, "width") {
-
- @Override
- public Integer get(DividerHandleView object) {
- return object.mCurrentWidth;
- }
-
- @Override
- public void set(DividerHandleView object, Integer value) {
- object.mCurrentWidth = value;
- object.invalidate();
- }
- };
-
- private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY
- = new Property<DividerHandleView, Integer>(Integer.class, "height") {
-
- @Override
- public Integer get(DividerHandleView object) {
- return object.mCurrentHeight;
- }
-
- @Override
- public void set(DividerHandleView object, Integer value) {
- object.mCurrentHeight = value;
- object.invalidate();
- }
- };
+public class DividerHandleView extends View {
+
+ private static final Property<DividerHandleView, Integer> WIDTH_PROPERTY =
+ new Property<DividerHandleView, Integer>(Integer.class, "width") {
+ @Override
+ public Integer get(DividerHandleView object) {
+ return object.mCurrentWidth;
+ }
+
+ @Override
+ public void set(DividerHandleView object, Integer value) {
+ object.mCurrentWidth = value;
+ object.invalidate();
+ }
+ };
+
+ private static final Property<DividerHandleView, Integer> HEIGHT_PROPERTY =
+ new Property<DividerHandleView, Integer>(Integer.class, "height") {
+ @Override
+ public Integer get(DividerHandleView object) {
+ return object.mCurrentHeight;
+ }
+
+ @Override
+ public void set(DividerHandleView object, Integer value) {
+ object.mCurrentHeight = value;
+ object.invalidate();
+ }
+ };
private final Paint mPaint = new Paint();
private final int mWidth;
@@ -86,7 +84,7 @@ class DividerHandleView extends View {
mCircleDiameter = (mWidth + mHeight) / 3;
}
- public void setTouching(boolean touching, boolean animate) {
+ void setTouching(boolean touching, boolean animate) {
if (touching == mTouching) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
index 64ee7ed5e0e0..92cee8a1a874 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
@@ -22,6 +22,7 @@ import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Handler;
import android.util.Slog;
@@ -31,8 +32,6 @@ import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
-import androidx.annotation.Nullable;
-
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.TransactionPool;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
index 8e79d51ee209..23d86a00d4bf 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
@@ -11,15 +11,15 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
/**
* Class to hold state of divider that needs to persist across configuration changes.
*/
-public class DividerState {
+final class DividerState {
public boolean animateAfterRecentsDrawn;
public float mRatioPositionBeforeMinimized;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
index fdf24b1e1a7e..79bfda92bd92 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
@@ -62,9 +62,9 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+import com.android.wm.shell.animation.Interpolators;
import java.util.function.Consumer;
@@ -76,7 +76,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private static final String TAG = "DividerView";
private static final boolean DEBUG = SplitScreenController.DEBUG;
- public interface DividerCallbacks {
+ interface DividerCallbacks {
void onDraggingStart();
void onDraggingEnd();
}
@@ -187,7 +187,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
// Only show the middle target if there are more than 1 split target
info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
- mContext.getString(R.string.accessibility_action_divider_top_50)));
+ mContext.getString(R.string.accessibility_action_divider_top_50)));
}
if (snapAlgorithm.isLastSplitTargetAvailable()) {
info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
@@ -205,7 +205,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
if (snapAlgorithm.showMiddleSplitTargetForAccessibility()) {
// Only show the middle target if there are more than 1 split target
info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
- mContext.getString(R.string.accessibility_action_divider_left_50)));
+ mContext.getString(R.string.accessibility_action_divider_left_50)));
}
if (snapAlgorithm.isLastSplitTargetAvailable()) {
info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
@@ -373,6 +373,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
}
+ /** Gets non-minimized secondary bounds of split screen. */
public Rect getNonMinimizedSplitScreenSecondaryBounds() {
mOtherTaskRect.set(mSplitLayout.mSecondary);
return mOtherTaskRect;
@@ -409,6 +410,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
return mSurfaceHidden;
}
+ /** Starts dragging the divider bar. */
public boolean startDragging(boolean animate, boolean touching) {
cancelFlingAnimation();
if (touching) {
@@ -427,6 +429,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
return inSplitMode();
}
+ /** Stops dragging the divider bar. */
public void stopDragging(int position, float velocity, boolean avoidDismissStart,
boolean logMetrics) {
mHandle.setTouching(false, true /* animate */);
@@ -889,7 +892,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
WindowManagerProxy.applyResizeSplits(midPos, mSplitLayout);
}
- public void setMinimizedDockStack(boolean minimized, long animDuration,
+ void setMinimizedDockStack(boolean minimized, long animDuration,
boolean isHomeStackResizable) {
if (DEBUG) Slog.d(TAG, "setMinDock: " + mDockedStackMinimized + "->" + minimized);
mHomeStackResizable = isHomeStackResizable;
@@ -925,7 +928,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
}
- public void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
+ void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
if (mAdjustedForIme == adjustedForIme) {
return;
}
@@ -952,8 +955,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private void saveSnapTargetBeforeMinimized(SnapTarget target) {
mSnapTargetBeforeMinimized = target;
- mState.mRatioPositionBeforeMinimized = (float) target.position /
- (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+ mState.mRatioPositionBeforeMinimized = (float) target.position
+ / (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
: mSplitLayout.mDisplayLayout.width());
}
@@ -971,8 +974,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
private void repositionSnapTargetBeforeMinimized() {
- int position = (int) (mState.mRatioPositionBeforeMinimized *
- (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+ int position = (int) (mState.mRatioPositionBeforeMinimized
+ * (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
: mSplitLayout.mDisplayLayout.width()));
// Set the snap target before minimized but do not save until divider is attached and not
@@ -1011,7 +1014,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
containingRect.right, containingRect.bottom);
}
- public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
+ private void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect,
mSplitLayout.mDisplayLayout.width(), mSplitLayout.mDisplayLayout.height(),
mDividerSize);
@@ -1240,8 +1243,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
if (dismissTarget != null && fraction > 0f
&& isDismissing(splitTarget, position, dockSide)) {
fraction = calculateParallaxDismissingFraction(fraction, dockSide);
- int offsetPosition = (int) (start +
- fraction * (dismissTarget.position - splitTarget.position));
+ int offsetPosition = (int) (start + fraction
+ * (dismissTarget.position - splitTarget.position));
int width = taskRect.width();
int height = taskRect.height();
switch (dockSide) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
index d869333e11a7..0b4e17c27398 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -37,7 +37,7 @@ import com.android.wm.shell.common.SystemWindows;
/**
* Manages the window parameters of the docked stack divider.
*/
-public class DividerWindowManager {
+final class DividerWindowManager {
private static final String WINDOW_TITLE = "DockedStackDivider";
@@ -45,12 +45,12 @@ public class DividerWindowManager {
private WindowManager.LayoutParams mLp;
private View mView;
- public DividerWindowManager(SystemWindows systemWindows) {
+ DividerWindowManager(SystemWindows systemWindows) {
mSystemWindows = systemWindows;
}
/** Add a divider view */
- public void add(View view, int width, int height, int displayId) {
+ void add(View view, int width, int height, int displayId) {
mLp = new WindowManager.LayoutParams(
width, height, TYPE_DOCK_DIVIDER,
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
@@ -67,14 +67,14 @@ public class DividerWindowManager {
mView = view;
}
- public void remove() {
+ void remove() {
if (mView != null) {
mSystemWindows.removeView(mView);
}
mView = null;
}
- public void setSlippery(boolean slippery) {
+ void setSlippery(boolean slippery) {
boolean changed = false;
if (slippery && (mLp.flags & FLAG_SLIPPERY) == 0) {
mLp.flags |= FLAG_SLIPPERY;
@@ -88,7 +88,7 @@ public class DividerWindowManager {
}
}
- public void setTouchable(boolean touchable) {
+ void setTouchable(boolean touchable) {
if (mView == null) {
return;
}
@@ -106,7 +106,7 @@ public class DividerWindowManager {
}
/** Sets the touch region to `touchRegion`. Use null to unset.*/
- public void setTouchRegion(Region touchRegion) {
+ void setTouchRegion(Region touchRegion) {
if (mView == null) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
index 02f75050c061..7a1633530148 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
@@ -11,10 +11,10 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
@@ -29,7 +29,7 @@ import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
/**
* Translucent activity that gets started on top of a task in multi-window to inform the user that
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
index 4c26694cc22a..1ef142dacb9e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
@@ -11,13 +11,13 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
-import static com.android.systemui.stackdivider.ForcedResizableInfoActivity
- .EXTRA_FORCED_RESIZEABLE_REASON;
+
+import static com.android.wm.shell.splitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
import android.app.ActivityOptions;
import android.content.Context;
@@ -27,7 +27,7 @@ import android.os.UserHandle;
import android.util.ArraySet;
import android.widget.Toast;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
import java.util.function.Consumer;
@@ -55,20 +55,20 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
/** Record of force resized task that's pending to be handled. */
private class PendingTaskRecord {
- int taskId;
+ int mTaskId;
/**
* {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SPLIT_SCREEN} or
* {@link android.app.ITaskStackListener#FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY}
*/
- int reason;
+ int mReason;
PendingTaskRecord(int taskId, int reason) {
- this.taskId = taskId;
- this.reason = reason;
+ this.mTaskId = taskId;
+ this.mReason = reason;
}
}
- public ForcedResizableInfoActivityController(Context context,
+ ForcedResizableInfoActivityController(Context context,
SplitScreenController splitScreenController) {
mContext = context;
splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
@@ -116,11 +116,11 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
PendingTaskRecord pendingRecord = mPendingTasks.valueAt(i);
Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchTaskId(pendingRecord.taskId);
+ options.setLaunchTaskId(pendingRecord.mTaskId);
// Set as task overlay and allow to resume, so that when an app enters split-screen and
// becomes paused, the overlay will still be shown.
options.setTaskOverlay(true, true /* canResume */);
- intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.reason);
+ intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.mReason);
mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
}
mPendingTasks.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
index ecff54fd907d..06f4ef109193 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
@@ -11,10 +11,10 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import android.annotation.Nullable;
import android.content.Context;
@@ -27,7 +27,7 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.WindowManager;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
/**
* Shadow for the minimized dock state on homescreen.
@@ -42,7 +42,7 @@ public class MinimizedDockShadow extends View {
super(context, attrs);
}
- public void setDockSide(int dockSide) {
+ void setDockSide(int dockSide) {
if (dockSide != mDockSide) {
mDockSide = dockSide;
updatePaint(getLeft(), getTop(), getRight(), getBottom());
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
index a34e85517953..3c0f93906795 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 93b1f86a5dc2..184342f14d4f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import android.graphics.Rect;
import android.window.WindowContainerToken;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 360b49555612..d5326d4845a3 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -34,7 +34,7 @@ import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.systemui.R;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
index 325c5597f9d8..6d28c5e17d42 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
index 82b10bd40b17..cd96676ad1fe 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.wm.shell.splitscreen;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -40,6 +40,7 @@ import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
import com.android.internal.annotations.GuardedBy;
+import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import java.util.ArrayList;
diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java
index 0ab62c14ab9f..5096bf616a1f 100644
--- a/media/java/android/media/AudioDeviceAttributes.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -72,6 +72,11 @@ public final class AudioDeviceAttributes implements Parcelable {
private final @Role int mRole;
/**
+ * The internal audio device type
+ */
+ private final int mNativeType;
+
+ /**
* @hide
* Constructor from a valid {@link AudioDeviceInfo}
* @param deviceInfo the connected audio device from which to obtain the device-identifying
@@ -83,6 +88,7 @@ public final class AudioDeviceAttributes implements Parcelable {
mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
mType = deviceInfo.getType();
mAddress = deviceInfo.getAddress();
+ mNativeType = deviceInfo.getPort().type();
}
/**
@@ -109,12 +115,14 @@ public final class AudioDeviceAttributes implements Parcelable {
mRole = role;
mType = type;
mAddress = address;
+ mNativeType = AudioSystem.DEVICE_NONE;
}
/*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
mAddress = address;
+ mNativeType = nativeType;
}
/**
@@ -147,6 +155,15 @@ public final class AudioDeviceAttributes implements Parcelable {
return mAddress;
}
+ /**
+ * @hide
+ * Returns the internal device type of a device
+ * @return the internal device type
+ */
+ public int getInternalType() {
+ return mNativeType;
+ }
+
@Override
public int hashCode() {
return Objects.hash(mRole, mType, mAddress);
@@ -189,12 +206,14 @@ public final class AudioDeviceAttributes implements Parcelable {
dest.writeInt(mRole);
dest.writeInt(mType);
dest.writeString(mAddress);
+ dest.writeInt(mNativeType);
}
private AudioDeviceAttributes(@NonNull Parcel in) {
mRole = in.readInt();
mType = in.readInt();
mAddress = in.readString();
+ mNativeType = in.readInt();
}
public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR =
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index d4fb1be56890..ba880cc58888 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -513,10 +513,21 @@ public final class AudioDeviceInfo {
return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, TYPE_UNKNOWN);
}
+ /** @hide */
+ public static int convertDeviceTypeToInternalInputDevice(int deviceType) {
+ return EXT_TO_INT_INPUT_DEVICE_MAPPING.get(deviceType, AudioSystem.DEVICE_NONE);
+ }
+
private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
private static final SparseIntArray EXT_TO_INT_DEVICE_MAPPING;
+ /**
+ * EXT_TO_INT_INPUT_DEVICE_MAPPING aims at mapping external device type to internal input device
+ * type.
+ */
+ private static final SparseIntArray EXT_TO_INT_INPUT_DEVICE_MAPPING;
+
static {
INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, TYPE_BUILTIN_EARPIECE);
@@ -601,6 +612,32 @@ public final class AudioDeviceInfo {
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET);
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER);
+
+ // privileges mapping to input device
+ EXT_TO_INT_INPUT_DEVICE_MAPPING = new SparseIntArray();
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_WIRED_HEADSET, AudioSystem.DEVICE_IN_WIRED_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_HDMI, AudioSystem.DEVICE_IN_HDMI);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_IN_TELEPHONY_RX);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_DOCK, AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_USB_ACCESSORY, AudioSystem.DEVICE_IN_USB_ACCESSORY);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_USB_DEVICE, AudioSystem.DEVICE_IN_USB_DEVICE);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_USB_HEADSET, AudioSystem.DEVICE_IN_USB_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_LINE_ANALOG, AudioSystem.DEVICE_IN_LINE);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_LINE_DIGITAL, AudioSystem.DEVICE_IN_SPDIF);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_IN_BLUETOOTH_A2DP);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_IP, AudioSystem.DEVICE_IN_IP);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BUS, AudioSystem.DEVICE_IN_BUS);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_IN_REMOTE_SUBMIX);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_IN_BLE_HEADSET);
}
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a16e063fe969..aa2ff17a307b 100755..100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1949,6 +1949,349 @@ public class AudioManager {
}
//====================================================================
+ // Audio Capture Preset routing
+
+ /**
+ * @hide
+ * Set the preferred device for a given capture preset, i.e. the audio routing to be used by
+ * this capture preset. Note that the device may not be available at the time the preferred
+ * device is set, but it will be used once made available.
+ * <p>Use {@link #clearPreferredDevicesForCapturePreset(int)} to cancel setting this preference
+ * for this capture preset.</p>
+ * @param capturePreset the audio capture preset whose routing will be affected
+ * @param device the audio device to route to when available
+ * @return true if the operation was successful, false otherwise
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public boolean setPreferredDeviceForCapturePreset(int capturePreset,
+ @NonNull AudioDeviceAttributes device) {
+ return setPreferredDevicesForCapturePreset(capturePreset, Arrays.asList(device));
+ }
+
+ /**
+ * @hide
+ * Remove all the preferred audio devices previously set
+ * @param capturePreset the audio capture preset whose routing will be affected
+ * @return true if the operation was successful, false otherwise (invalid capture preset, or no
+ * device set for example)
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public boolean clearPreferredDevicesForCapturePreset(int capturePreset) {
+ if (!MediaRecorder.isValidAudioSource(capturePreset)) {
+ return false;
+ }
+ try {
+ final int status = getService().clearPreferredDevicesForCapturePreset(capturePreset);
+ return status == AudioSystem.SUCCESS;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Return the preferred devices for an audio capture preset, previously set with
+ * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)}
+ * @param capturePreset the capture preset to query
+ * @return a list that contains preferred devices for that capture preset.
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int capturePreset) {
+ if (!MediaRecorder.isValidAudioSource(capturePreset)) {
+ return new ArrayList<AudioDeviceAttributes>();
+ }
+ try {
+ return getService().getPreferredDevicesForCapturePreset(capturePreset);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private boolean setPreferredDevicesForCapturePreset(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
+ Objects.requireNonNull(devices);
+ if (!MediaRecorder.isValidAudioSource(capturePreset)) {
+ return false;
+ }
+ if (devices.size() != 1) {
+ throw new IllegalArgumentException(
+ "Only support setting one preferred devices for capture preset");
+ }
+ for (AudioDeviceAttributes device : devices) {
+ Objects.requireNonNull(device);
+ }
+ try {
+ final int status =
+ getService().setPreferredDevicesForCapturePreset(capturePreset, devices);
+ return status == AudioSystem.SUCCESS;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Interface to be notified of changes in the preferred audio devices set for a given capture
+ * preset.
+ * <p>Note that this listener will only be invoked whenever
+ * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)} or
+ * {@link #clearPreferredDevicesForCapturePreset(int)} causes a change in
+ * preferred device. It will not be invoked directly after registration with
+ * {@link #addOnPreferredDevicesForCapturePresetChangedListener(
+ * Executor, OnPreferredDevicesForCapturePresetChangedListener)}
+ * to indicate which strategies had preferred devices at the time of registration.</p>
+ * @see #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)
+ * @see #clearPreferredDevicesForCapturePreset(int)
+ * @see #getPreferredDevicesForCapturePreset(int)
+ */
+ @SystemApi
+ public interface OnPreferredDevicesForCapturePresetChangedListener {
+ /**
+ * Called on the listener to indicate that the preferred audio devices for the given
+ * capture preset has changed.
+ * @param capturePreset the capture preset whose preferred device changed
+ * @param devices a list of newly set preferred audio devices
+ */
+ void onPreferredDevicesForCapturePresetChanged(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices);
+ }
+
+ /**
+ * @hide
+ * Adds a listener for being notified of changes to the capture-preset-preferred audio device.
+ * @param executor
+ * @param listener
+ * @throws SecurityException if the caller doesn't hold the required permission
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public void addOnPreferredDevicesForCapturePresetChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnPreferredDevicesForCapturePresetChangedListener listener)
+ throws SecurityException {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ int status = addOnDevRoleForCapturePresetChangedListener(
+ executor, listener, AudioSystem.DEVICE_ROLE_PREFERRED);
+ if (status == AudioSystem.ERROR) {
+ // This must not happen
+ throw new RuntimeException("Unknown error happened");
+ }
+ if (status == AudioSystem.BAD_VALUE) {
+ throw new IllegalArgumentException(
+ "attempt to call addOnPreferredDevicesForCapturePresetChangedListener() "
+ + "on a previously registered listener");
+ }
+ }
+
+ /**
+ * @hide
+ * Removes a previously added listener of changes to the capture-preset-preferred audio device.
+ * @param listener
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public void removeOnPreferredDevicesForCapturePresetChangedListener(
+ @NonNull OnPreferredDevicesForCapturePresetChangedListener listener) {
+ Objects.requireNonNull(listener);
+ int status = removeOnDevRoleForCapturePresetChangedListener(
+ listener, AudioSystem.DEVICE_ROLE_PREFERRED);
+ if (status == AudioSystem.ERROR) {
+ // This must not happen
+ throw new RuntimeException("Unknown error happened");
+ }
+ if (status == AudioSystem.BAD_VALUE) {
+ throw new IllegalArgumentException(
+ "attempt to call removeOnPreferredDevicesForCapturePresetChangedListener() "
+ + "on an unregistered listener");
+ }
+ }
+
+ private <T> int addOnDevRoleForCapturePresetChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull T listener, int deviceRole) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ DevRoleListeners<T> devRoleListeners =
+ (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole);
+ if (devRoleListeners == null) {
+ return AudioSystem.ERROR;
+ }
+ synchronized (devRoleListeners.mDevRoleListenersLock) {
+ if (devRoleListeners.hasDevRoleListener(listener)) {
+ return AudioSystem.BAD_VALUE;
+ }
+ // lazy initialization of the list of device role listener
+ if (devRoleListeners.mListenerInfos == null) {
+ devRoleListeners.mListenerInfos = new ArrayList<>();
+ }
+ final int oldCbCount = devRoleListeners.mListenerInfos.size();
+ devRoleListeners.mListenerInfos.add(new DevRoleListenerInfo<T>(executor, listener));
+ if (oldCbCount == 0 && devRoleListeners.mListenerInfos.size() > 0) {
+ // register binder for callbacks
+ synchronized (mDevRoleForCapturePresetListenersLock) {
+ int deviceRoleListenerStatus = mDeviceRoleListenersStatus;
+ mDeviceRoleListenersStatus |= (1 << deviceRole);
+ if (deviceRoleListenerStatus != 0) {
+ // There are already device role changed listeners active.
+ return AudioSystem.SUCCESS;
+ }
+ if (mDevicesRoleForCapturePresetDispatcherStub == null) {
+ mDevicesRoleForCapturePresetDispatcherStub =
+ new CapturePresetDevicesRoleDispatcherStub();
+ }
+ try {
+ getService().registerCapturePresetDevicesRoleDispatcher(
+ mDevicesRoleForCapturePresetDispatcherStub);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+ return AudioSystem.SUCCESS;
+ }
+
+ private <T> int removeOnDevRoleForCapturePresetChangedListener(
+ @NonNull T listener, int deviceRole) {
+ Objects.requireNonNull(listener);
+ DevRoleListeners<T> devRoleListeners =
+ (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole);
+ if (devRoleListeners == null) {
+ return AudioSystem.ERROR;
+ }
+ synchronized (devRoleListeners.mDevRoleListenersLock) {
+ if (!devRoleListeners.removeDevRoleListener(listener)) {
+ return AudioSystem.BAD_VALUE;
+ }
+ if (devRoleListeners.mListenerInfos.size() == 0) {
+ // unregister binder for callbacks
+ synchronized (mDevRoleForCapturePresetListenersLock) {
+ mDeviceRoleListenersStatus ^= (1 << deviceRole);
+ if (mDeviceRoleListenersStatus != 0) {
+ // There are some other device role changed listeners active.
+ return AudioSystem.SUCCESS;
+ }
+ try {
+ getService().unregisterCapturePresetDevicesRoleDispatcher(
+ mDevicesRoleForCapturePresetDispatcherStub);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+ return AudioSystem.SUCCESS;
+ }
+
+ private final Map<Integer, Object> mDevRoleForCapturePresetListeners = new HashMap<>(){{
+ put(AudioSystem.DEVICE_ROLE_PREFERRED,
+ new DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>());
+ }};
+
+ private class DevRoleListenerInfo<T> {
+ final @NonNull Executor mExecutor;
+ final @NonNull T mListener;
+ DevRoleListenerInfo(Executor executor, T listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+ }
+
+ private class DevRoleListeners<T> {
+ private final Object mDevRoleListenersLock = new Object();
+ @GuardedBy("mDevRoleListenersLock")
+ private @Nullable ArrayList<DevRoleListenerInfo<T>> mListenerInfos;
+
+ @GuardedBy("mDevRoleListenersLock")
+ private @Nullable DevRoleListenerInfo<T> getDevRoleListenerInfo(T listener) {
+ if (mListenerInfos == null) {
+ return null;
+ }
+ for (DevRoleListenerInfo<T> listenerInfo : mListenerInfos) {
+ if (listenerInfo.mListener == listener) {
+ return listenerInfo;
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy("mDevRoleListenersLock")
+ private boolean hasDevRoleListener(T listener) {
+ return getDevRoleListenerInfo(listener) != null;
+ }
+
+ @GuardedBy("mDevRoleListenersLock")
+ private boolean removeDevRoleListener(T listener) {
+ final DevRoleListenerInfo<T> infoToRemove = getDevRoleListenerInfo(listener);
+ if (infoToRemove != null) {
+ mListenerInfos.remove(infoToRemove);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private final Object mDevRoleForCapturePresetListenersLock = new Object();
+ /**
+ * Record if there is a listener added for device role change. If there is a listener added for
+ * a specified device role change, the bit at position `1 << device_role` is set.
+ */
+ @GuardedBy("mDevRoleForCapturePresetListenersLock")
+ private int mDeviceRoleListenersStatus = 0;
+ @GuardedBy("mDevRoleForCapturePresetListenersLock")
+ private CapturePresetDevicesRoleDispatcherStub mDevicesRoleForCapturePresetDispatcherStub;
+
+ private final class CapturePresetDevicesRoleDispatcherStub
+ extends ICapturePresetDevicesRoleDispatcher.Stub {
+
+ @Override
+ public void dispatchDevicesRoleChanged(
+ int capturePreset, int role, List<AudioDeviceAttributes> devices) {
+ final Object listenersObj = mDevRoleForCapturePresetListeners.get(role);
+ if (listenersObj == null) {
+ return;
+ }
+ switch (role) {
+ case AudioSystem.DEVICE_ROLE_PREFERRED: {
+ final DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>
+ listeners =
+ (DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>)
+ listenersObj;
+ final ArrayList<DevRoleListenerInfo<
+ OnPreferredDevicesForCapturePresetChangedListener>> prefDevListeners;
+ synchronized (listeners.mDevRoleListenersLock) {
+ if (listeners.mListenerInfos.isEmpty()) {
+ return;
+ }
+ prefDevListeners = (ArrayList<DevRoleListenerInfo<
+ OnPreferredDevicesForCapturePresetChangedListener>>)
+ listeners.mListenerInfos.clone();
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ for (DevRoleListenerInfo<
+ OnPreferredDevicesForCapturePresetChangedListener> info :
+ prefDevListeners) {
+ info.mExecutor.execute(() ->
+ info.mListener.onPreferredDevicesForCapturePresetChanged(
+ capturePreset, devices));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+ }
+
+ //====================================================================
// Offload query
/**
* Returns whether offloaded playback of an audio format is supported on the device.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 243ec1f1fcd0..279ba0a55be0 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -27,6 +27,7 @@ import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
import android.telephony.TelephonyManager;
import android.util.Log;
+import android.util.Pair;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -524,6 +525,7 @@ public class AudioSystem
/** @hide Media server died. see ErrorCallback */
public static final int AUDIO_STATUS_SERVER_DIED = 100;
+ // all accesses must be synchronized (AudioSystem.class)
private static ErrorCallback sErrorCallback;
/** @hide
@@ -560,11 +562,9 @@ public class AudioSystem
@UnsupportedAppUsage
private static void errorCallbackFromNative(int error)
{
- ErrorCallback errorCallback = null;
+ ErrorCallback errorCallback;
synchronized (AudioSystem.class) {
- if (sErrorCallback != null) {
- errorCallback = sErrorCallback;
- }
+ errorCallback = sErrorCallback;
}
if (errorCallback != null) {
errorCallback.onError(error);
@@ -584,6 +584,7 @@ public class AudioSystem
//keep in sync with include/media/AudioPolicy.h
private final static int DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE = 0;
+ // all accesses must be synchronized (AudioSystem.class)
private static DynamicPolicyCallback sDynPolicyCallback;
/** @hide */
@@ -598,11 +599,9 @@ public class AudioSystem
@UnsupportedAppUsage
private static void dynamicPolicyCallbackFromNative(int event, String regId, int val)
{
- DynamicPolicyCallback cb = null;
+ DynamicPolicyCallback cb;
synchronized (AudioSystem.class) {
- if (sDynPolicyCallback != null) {
- cb = sDynPolicyCallback;
- }
+ cb = sDynPolicyCallback;
}
if (cb != null) {
switch(event) {
@@ -646,6 +645,7 @@ public class AudioSystem
int activeSource, String packName);
}
+ // all accesses must be synchronized (AudioSystem.class)
private static AudioRecordingCallback sRecordingCallback;
/** @hide */
@@ -678,7 +678,7 @@ public class AudioSystem
int source, int portId, boolean silenced, int[] recordingFormat,
AudioEffect.Descriptor[] clientEffects, AudioEffect.Descriptor[] effects,
int activeSource) {
- AudioRecordingCallback cb = null;
+ AudioRecordingCallback cb;
synchronized (AudioSystem.class) {
cb = sRecordingCallback;
}
@@ -1756,6 +1756,134 @@ public class AudioSystem
public static native int getDevicesForRoleAndStrategy(
int strategy, int role, @NonNull List<AudioDeviceAttributes> devices);
+ // use case routing by capture preset
+
+ private static Pair<int[], String[]> populateInputDevicesTypeAndAddress(
+ @NonNull List<AudioDeviceAttributes> devices) {
+ int[] types = new int[devices.size()];
+ String[] addresses = new String[devices.size()];
+ for (int i = 0; i < devices.size(); ++i) {
+ types[i] = devices.get(i).getInternalType();
+ if (types[i] == AudioSystem.DEVICE_NONE) {
+ types[i] = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(
+ devices.get(i).getType());
+ }
+ addresses[i] = devices.get(i).getAddress();
+ }
+ return new Pair<int[], String[]>(types, addresses);
+ }
+
+ /**
+ * @hide
+ * Set devices as role for capture preset.
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param devices the list of devices to be set as role for the given capture preset
+ * @return {@link #SUCCESS} if successfully set
+ */
+ public static int setDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ if (devices.isEmpty()) {
+ return BAD_VALUE;
+ }
+ Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices);
+ return setDevicesRoleForCapturePreset(
+ capturePreset, role, typeAddresses.first, typeAddresses.second);
+ }
+
+ /**
+ * @hide
+ * Set devices as role for capture preset.
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param types all device types
+ * @param addresses all device addresses
+ * @return {@link #SUCCESS} if successfully set
+ */
+ private static native int setDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses);
+
+ /**
+ * @hide
+ * Add devices as role for capture preset.
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param devices the list of devices to be added as role for the given capture preset
+ * @return {@link #SUCCESS} if successfully add
+ */
+ public static int addDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ if (devices.isEmpty()) {
+ return BAD_VALUE;
+ }
+ Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices);
+ return addDevicesRoleForCapturePreset(
+ capturePreset, role, typeAddresses.first, typeAddresses.second);
+ }
+
+ /**
+ * @hide
+ * Add devices as role for capture preset.
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param types all device types
+ * @param addresses all device addresses
+ * @return {@link #SUCCESS} if successfully set
+ */
+ private static native int addDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses);
+
+ /**
+ * @hide
+ * Remove devices as role for the capture preset
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param devices the devices to be removed
+ * @return {@link #SUCCESS} if successfully removed
+ */
+ public static int removeDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ if (devices.isEmpty()) {
+ return BAD_VALUE;
+ }
+ Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices);
+ return removeDevicesRoleForCapturePreset(
+ capturePreset, role, typeAddresses.first, typeAddresses.second);
+ }
+
+ /**
+ * @hide
+ * Remove devices as role for capture preset.
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param types all device types
+ * @param addresses all device addresses
+ * @return {@link #SUCCESS} if successfully set
+ */
+ private static native int removeDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses);
+
+ /**
+ * @hide
+ * Remove all devices as role for the capture preset
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @return {@link #SUCCESS} if successfully removed
+ */
+ public static native int clearDevicesRoleForCapturePreset(int capturePreset, int role);
+
+ /**
+ * @hide
+ * Query previously set devices as role for a capture preset
+ * @param capturePreset the capture preset to query for
+ * @param role the role of the devices
+ * @param devices a list that will contain the devices of role
+ * @return {@link #SUCCESS} if there is a preferred device and it was successfully retrieved
+ * and written to the array
+ */
+ public static native int getDevicesForRoleAndCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices);
+
// Items shared with audio service
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index ef8b0edb1fe5..85fb67df82d4 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -26,6 +26,7 @@ import android.media.AudioRoutesInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
import android.media.IAudioServerStateDispatcher;
+import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.IPlaybackConfigDispatcher;
import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
@@ -307,4 +308,16 @@ interface IAudioService {
// code via IAudioManager.h need to be added to the top section.
oneway void setMultiAudioFocusEnabled(in boolean enabled);
+
+ int setPreferredDevicesForCapturePreset(
+ in int capturePreset, in List<AudioDeviceAttributes> devices);
+
+ int clearPreferredDevicesForCapturePreset(in int capturePreset);
+
+ List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(in int capturePreset);
+
+ void registerCapturePresetDevicesRoleDispatcher(ICapturePresetDevicesRoleDispatcher dispatcher);
+
+ oneway void unregisterCapturePresetDevicesRoleDispatcher(
+ ICapturePresetDevicesRoleDispatcher dispatcher);
}
diff --git a/media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl b/media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl
new file mode 100644
index 000000000000..5e03e632c4ff
--- /dev/null
+++ b/media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioDeviceAttributes;
+
+/**
+ * AIDL for AudioService to signal devices role for capture preset updates.
+ *
+ * {@hide}
+ */
+oneway interface ICapturePresetDevicesRoleDispatcher {
+
+ void dispatchDevicesRoleChanged(
+ int capturePreset, int role, in List<AudioDeviceAttributes> devices);
+
+}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4198d7917932..1db02beaea1a 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -404,6 +404,32 @@ public class MediaRecorder implements AudioRouting,
}
}
+ /**
+ * @hide
+ * @param source An audio source to test
+ * @return true if the source is a valid one
+ */
+ public static boolean isValidAudioSource(int source) {
+ switch(source) {
+ case AudioSource.MIC:
+ case AudioSource.VOICE_UPLINK:
+ case AudioSource.VOICE_DOWNLINK:
+ case AudioSource.VOICE_CALL:
+ case AudioSource.CAMCORDER:
+ case AudioSource.VOICE_RECOGNITION:
+ case AudioSource.VOICE_COMMUNICATION:
+ case AudioSource.REMOTE_SUBMIX:
+ case AudioSource.UNPROCESSED:
+ case AudioSource.VOICE_PERFORMANCE:
+ case AudioSource.ECHO_REFERENCE:
+ case AudioSource.RADIO_TUNER:
+ case AudioSource.HOTWORD:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/** @hide */
public static final String toLogFriendlyAudioSource(int source) {
switch(source) {
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index cf61152c4775..1c5288b04685 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -102,7 +102,7 @@ import java.util.concurrent.Executors;
*/
@TestApi
@SystemApi
-public final class MediaTranscodeManager implements AutoCloseable {
+public final class MediaTranscodeManager {
private static final String TAG = "MediaTranscodeManager";
private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding";
@@ -131,28 +131,6 @@ public final class MediaTranscodeManager implements AutoCloseable {
*/
public static final int TRANSCODING_TYPE_IMAGE = 2;
- @Override
- public void close() {
- release();
- }
-
- /**
- * Releases the MediaTranscodeManager.
- */
- private void release() {
- synchronized (mLock) {
- try {
- if (mTranscodingClient != null) {
- mTranscodingClient.unregister();
- }
- } catch (Exception ex) {
- Log.e(TAG, "Failed to unregister the client");
- } finally {
- mTranscodingClient = null;
- }
- }
- }
-
/** @hide */
@IntDef(prefix = {"TRANSCODING_TYPE_"}, value = {
TRANSCODING_TYPE_UNKNOWN,
@@ -182,6 +160,7 @@ public final class MediaTranscodeManager implements AutoCloseable {
* <p>Jobs with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set to
* PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept
* delay of the transcoding result.
+ * @hide
* TODO(hkuang): Add more description of this when priority is finalized.
*/
public static final int PRIORITY_OFFLINE = 2;
@@ -287,7 +266,7 @@ public final class MediaTranscodeManager implements AutoCloseable {
// Notifies client the progress update.
if (job.mProgressUpdateExecutor != null && job.mProgressUpdateListener != null) {
job.mProgressUpdateExecutor.execute(
- () -> job.mProgressUpdateListener.onProgressUpdate(newProgress));
+ () -> job.mProgressUpdateListener.onProgressUpdate(job, newProgress));
}
}
}
@@ -503,11 +482,6 @@ public final class MediaTranscodeManager implements AutoCloseable {
mTranscodingClient = registerClient(service);
}
- @Override
- protected void finalize() {
- release();
- }
-
public static final class TranscodingRequest {
/** Uri of the source media file. */
private @NonNull Uri mSourceUri;
@@ -892,9 +866,12 @@ public final class MediaTranscodeManager implements AutoCloseable {
/**
* Called when the progress changes. The progress is in percentage between 0 and 1,
* where 0 means that the job has not yet started and 100 means that it has finished.
+ *
+ * @param job The job associated with the progress.
* @param progress The new progress ranging from 0 ~ 100 inclusive.
*/
- void onProgressUpdate(@IntRange(from = 0, to = 100) int progress);
+ void onProgressUpdate(@NonNull TranscodingJob job,
+ @IntRange(from = 0, to = 100) int progress);
}
private final ITranscodingClient mJobOwner;
diff --git a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh b/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
index 43db3530a16b..c8fb3a63fe2c 100644
--- a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
+++ b/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
@@ -31,6 +31,9 @@ do
adb push --sync $file /data/user/0/com.android.mediatranscodingtest/cache/
done
-echo "[==========] running real transcoding tests"
+echo "[==========] running MediaTranscodeManagerTest"
adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
+echo "[==========] running MediaTranscodeManagerDiedTest"
+adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
+
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
new file mode 100644
index 000000000000..f00c14d79bec
--- /dev/null
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediatranscodingtest;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.media.MediaFormat;
+import android.media.MediaTranscodeManager;
+import android.media.MediaTranscodeManager.TranscodingJob;
+import android.media.MediaTranscodeManager.TranscodingRequest;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
+
+import org.junit.Test;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/*
+ * Service died tests for MediaTranscodeManager in the media framework.
+ *
+ * To run this test suite:
+ make frameworks/base/media/tests/MediaTranscodingTest
+ make mediatranscodingtest
+
+ adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
+
+ adb shell am instrument -e class \
+ com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest \
+ -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
+ *
+ */
+public class MediaTranscodeManagerDiedTest
+ extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
+ private static final String TAG = "MediaTranscodeManagerDiedTest";
+ /** The time to wait for the transcode operation to complete before failing the test. */
+ private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
+
+ /** Maximum number of retry to connect to the service. */
+ private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
+
+ /** Interval between trying to reconnect to the service. */
+ private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
+
+ private Context mContext;
+ private MediaTranscodeManager mMediaTranscodeManager = null;
+ private Uri mSourceHEVCVideoUri = null;
+ private Uri mSourceAVCVideoUri = null;
+ private Uri mDestinationUri = null;
+
+ // Setting for transcoding to H.264.
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final int BIT_RATE = 20000000; // 20Mbps
+ private static final int WIDTH = 1920;
+ private static final int HEIGHT = 1080;
+
+ public MediaTranscodeManagerDiedTest() {
+ super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class);
+ }
+
+ // Copy the resource to cache.
+ private Uri resourceToUri(Context context, int resId, String name) throws IOException {
+ Uri resUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(context.getResources().getResourcePackageName(resId))
+ .appendPath(context.getResources().getResourceTypeName(resId))
+ .appendPath(context.getResources().getResourceEntryName(resId))
+ .build();
+
+ Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ + mContext.getCacheDir().getAbsolutePath() + "/" + name);
+
+ InputStream is = mContext.getResources().openRawResource(resId);
+ OutputStream os = mContext.getContentResolver().openOutputStream(cacheUri);
+
+ FileUtils.copy(is, os);
+
+ return cacheUri;
+ }
+
+ private static Uri generateNewUri(Context context, String filename) {
+ File outFile = new File(context.getExternalCacheDir(), filename);
+ return Uri.fromFile(outFile);
+ }
+
+ /**
+ * Creates a MediaFormat with the basic set of values.
+ */
+ private static MediaFormat createMediaFormat() {
+ MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
+ return format;
+ }
+
+ private MediaTranscodeManager getManager() {
+ for (int count = 1; count <= CONNECT_SERVICE_RETRY_COUNT; count++) {
+ Log.d(TAG, "Trying to connect to service. Try count: " + count);
+ MediaTranscodeManager manager = mContext.getSystemService(MediaTranscodeManager.class);
+ if (manager != null) {
+ return manager;
+ }
+ try {
+ // Sleep a bit before retry.
+ Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
+ } catch (InterruptedException ie) {
+ /* ignore */
+ }
+ }
+
+ throw new UnsupportedOperationException("Failed to acquire MediaTranscodeManager");
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ Log.d(TAG, "setUp");
+ super.setUp();
+
+ mContext = getInstrumentation().getContext();
+ mMediaTranscodeManager = getManager();
+ assertNotNull(mMediaTranscodeManager);
+ androidx.test.InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
+
+ // Setup source HEVC file uri.
+ mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC, "VideoOnlyHEVC.mp4");
+
+ // Setup source AVC file uri.
+ mSourceAVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyAVC,
+ "VideoOnlyAVC.mp4");
+
+ // Setup destination file.
+ mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // [[ $(adb shell whoami) == "root" ]]
+ private boolean checkIfRoot() {
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation()
+ .executeShellCommand("whoami");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ if (line.contains("root")) {
+ return true;
+ }
+ }
+ } catch (IOException ie) {
+ return false;
+ }
+ return false;
+ }
+
+ private String executeShellCommand(String cmd) throws Exception {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ }
+
+ @Test
+ public void testHandleTranscoderServiceDied() throws Exception {
+ if (!checkIfRoot()) {
+ throw new AssertionError("must be root to run this test; try adb root?");
+ }
+
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+ Semaphore jobStartedSemaphore = new Semaphore(0);
+
+ // Transcode a 15 seconds video, so that the transcoding is not finished when we kill the
+ // service.
+ Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
+ Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
+
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setDestinationUri(destinationUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ Executor listenerExecutor = Executors.newSingleThreadExecutor();
+
+ Log.i(TAG, "transcoding to " + createMediaFormat());
+
+ TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
+ transcodingJob -> {
+ Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
+ transcodeCompleteSemaphore.release();
+ });
+ assertNotNull(job);
+
+ AtomicInteger progressUpdateCount = new AtomicInteger(0);
+
+ // Set progress update executor and use the same executor as result listener.
+ job.setOnProgressUpdateListener(listenerExecutor,
+ new TranscodingJob.OnProgressUpdateListener() {
+ @Override
+ public void onProgressUpdate(TranscodingJob job, int newProgress) {
+ if (newProgress > 0) {
+ jobStartedSemaphore.release();
+ }
+ }
+ });
+
+ // Wait for progress update so the job is in running state.
+ jobStartedSemaphore.tryAcquire(TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Job is not running", job.getStatus() == TranscodingJob.STATUS_RUNNING);
+
+ // Kills the service and expects receiving failure of the job.
+ executeShellCommand("pkill -f media.transcoding");
+
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode result.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Invalid job status", job.getStatus() == TranscodingJob.STATUS_FINISHED);
+ assertTrue("Invalid job result", job.getResult()== TranscodingJob.RESULT_ERROR);
+ }
+}
+
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
index a707c7a7955b..1a3e3608f37f 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
@@ -16,12 +16,15 @@
package com.android.mediatranscodingtest;
+import static org.testng.Assert.assertThrows;
+
import android.content.ContentResolver;
import android.content.Context;
import android.media.MediaFormat;
import android.media.MediaTranscodeManager;
import android.media.MediaTranscodeManager.TranscodingJob;
import android.media.MediaTranscodeManager.TranscodingRequest;
+import android.media.TranscodingTestConfig;
import android.net.Uri;
import android.os.Bundle;
import android.os.FileUtils;
@@ -180,6 +183,227 @@ public class MediaTranscodeManagerTest
super.tearDown();
}
+
+ /**
+ * Verify that setting null destination uri will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithNullDestinationUri() throws Exception {
+ assertThrows(IllegalArgumentException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setDestinationUri(null)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ });
+ }
+
+ /**
+ * Verify that setting null source uri will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithNullSourceUri() throws Exception {
+ assertThrows(IllegalArgumentException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(null)
+ .setDestinationUri(mDestinationUri)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .build();
+ });
+ }
+
+ /**
+ * Verify that not setting source uri will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithoutSourceUri() throws Exception {
+ assertThrows(UnsupportedOperationException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setDestinationUri(mDestinationUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ });
+ }
+
+ /**
+ * Verify that not setting destination uri will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithoutDestinationUri() throws Exception {
+ assertThrows(UnsupportedOperationException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ });
+ }
+
+ /**
+ * Verify that setting image transcoding mode will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithUnsupportedMode() throws Exception {
+ assertThrows(UnsupportedOperationException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setDestinationUri(mDestinationUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_IMAGE)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ });
+ }
+
+ /**
+ * Verify that setting video transcoding without setting video format will throw exception.
+ */
+ @Test
+ public void testCreateTranscodingRequestWithoutVideoFormat() throws Exception {
+ assertThrows(UnsupportedOperationException.class, () -> {
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setDestinationUri(mDestinationUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .build();
+ });
+ }
+
+ void testTranscodingWithExpectResult(Uri srcUri, Uri dstUri, int expectedResult)
+ throws Exception {
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+ TranscodingTestConfig testConfig = new TranscodingTestConfig();
+ testConfig.passThroughMode = true;
+ testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding.
+
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(srcUri)
+ .setDestinationUri(dstUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .setTestConfig(testConfig)
+ .build();
+ Executor listenerExecutor = Executors.newSingleThreadExecutor();
+
+ TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
+ transcodingJob -> {
+ Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
+ assertTrue("Transcoding should failed.",
+ transcodingJob.getResult() == expectedResult);
+ transcodeCompleteSemaphore.release();
+ });
+ assertNotNull(job);
+
+ if (job != null) {
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Transcode failed to complete in time.", finishedOnTime);
+ }
+
+ if (expectedResult == TranscodingJob.RESULT_SUCCESS) {
+ // Checks the destination file get generated.
+ File file = new File(dstUri.getPath());
+ assertTrue("Failed to create destination file", file.exists());
+
+ // Removes the file.
+ file.delete();
+ }
+ }
+
+ // Tests transcoding from invalid a invalid and expects failure.
+ @Test
+ public void testTranscodingInvalidSrcUri() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ Uri invalidSrcUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ + mContext.getPackageName() + "/source.mp4");
+ Log.d(TAG, "Transcoding from source: " + invalidSrcUri);
+
+ // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ // The full path of this file is:
+ // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ + mContext.getPackageName() + "/temp.mp4");
+ Log.d(TAG, "Transcoding to destination: " + destinationUri);
+
+ testTranscodingWithExpectResult(invalidSrcUri, destinationUri, TranscodingJob.RESULT_ERROR);
+ }
+
+ // Tests transcoding to a uri in res folder and expects failure as we could not write to res
+ // folder.
+ @Test
+ public void testTranscodingToResFolder() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ // The full path of this file is:
+ // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ + mContext.getPackageName() + "/temp.mp4");
+ Log.d(TAG, "Transcoding to destination: " + destinationUri);
+
+ testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
+ TranscodingJob.RESULT_ERROR);
+ }
+
+ // Tests transcoding to a uri in internal storage folder and expects success.
+ @Test
+ public void testTranscodingToCacheDir() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ // The full path of this file is:
+ // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ + mContext.getCacheDir().getAbsolutePath() + "/temp.mp4");
+
+ testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
+ TranscodingJob.RESULT_SUCCESS);
+ }
+
+ // Tests transcoding to a uri in internal files directory and expects success.
+ @Test
+ public void testTranscodingToInternalFilesDir() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ // Create a file Uri:
+ // file:///storage/emulated/0/Android/data/com.android.mediatranscodingtest/files/temp.mp4
+ Uri destinationUri = Uri.fromFile(new File(mContext.getFilesDir(), "temp.mp4"));
+ Log.i(TAG, "Transcoding to files dir: " + destinationUri);
+
+ testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
+ TranscodingJob.RESULT_SUCCESS);
+ }
+
+ // Tests transcoding to a uri in external files directory and expects success.
+ @Test
+ public void testTranscodingToExternalFilesDir() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/files/temp.mp4
+ Uri destinationUri = Uri.fromFile(new File(mContext.getExternalFilesDir(null), "temp.mp4"));
+ Log.i(TAG, "Transcoding to files dir: " + destinationUri);
+
+ testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
+ TranscodingJob.RESULT_SUCCESS);
+ }
+
@Test
public void testTranscodingFromHevcToAvc() throws Exception {
Semaphore transcodeCompleteSemaphore = new Semaphore(0);
@@ -308,7 +532,7 @@ public class MediaTranscodeManagerTest
int mPreviousProgress = 0;
@Override
- public void onProgressUpdate(int newProgress) {
+ public void onProgressUpdate(TranscodingJob job, int newProgress) {
assertTrue("Invalid proress update", newProgress > mPreviousProgress);
assertTrue("Invalid proress update", newProgress <= 100);
if (newProgress > 0) {
@@ -354,73 +578,5 @@ public class MediaTranscodeManagerTest
return UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
}
-
- @Test
- public void testHandleTranscoderServiceDied() throws Exception {
- try {
- if (!checkIfRoot()) {
- throw new AssertionError("must be root to run this test; try adb root?");
- } else {
- Log.i(TAG, "Device is root");
- }
- } catch (IOException e) {
- throw new AssertionError(e);
- }
-
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- Semaphore jobStartedSemaphore = new Semaphore(0);
-
- // Transcode a 15 seconds video, so that the transcoding is not finished when we kill the
- // service.
- Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(destinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- Log.i(TAG, "transcoding to " + createMediaFormat());
-
- TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
- transcodingJob -> {
- Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
- assertEquals(transcodingJob.getResult(), TranscodingJob.RESULT_ERROR);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(job);
-
- AtomicInteger progressUpdateCount = new AtomicInteger(0);
-
- // Set progress update executor and use the same executor as result listener.
- job.setOnProgressUpdateListener(listenerExecutor,
- new TranscodingJob.OnProgressUpdateListener() {
- @Override
- public void onProgressUpdate(int newProgress) {
- if (newProgress > 0) {
- jobStartedSemaphore.release();
- }
- }
- });
-
- // Wait for progress update so the job is in running state.
- jobStartedSemaphore.tryAcquire(TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Job is not running", job.getStatus() == TranscodingJob.STATUS_RUNNING);
-
- // Kills the service and expects receiving failure of the job.
- executeShellCommand("pkill -f media.transcoding");
-
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode result.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Invalid job status", job.getStatus() == TranscodingJob.STATUS_FINISHED);
- }
}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java
deleted file mode 100644
index 167e474eb143..000000000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerWithMockServiceTest.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.mediatranscodingtest;
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.IMediaTranscodingService;
-import android.media.ITranscodingClient;
-import android.media.ITranscodingClientCallback;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingJob;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.TranscodingJobParcel;
-import android.media.TranscodingRequestParcel;
-import android.media.TranscodingResultParcel;
-import android.media.TranscodingTestConfig;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import org.junit.Test;
-
-import java.io.File;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/*
- * Functional tests for MediaTranscodeManager in the media framework.
- * The test uses a mock Transcoding service as backend to test the API functionality.
- *
- * To run this test suite:
- make frameworks/base/media/tests/MediaTranscodingTest
- make mediatranscodingtest
-
- adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
- adb shell am instrument -e class \
- com.android.mediatranscodingtest.MediaTranscodeManagerWithMockServiceTest \
- -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodeManagerWithMockServiceTest
- extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
- private static final String TAG = "MediaTranscodeManagerWithMockServiceTest";
- /** The time to wait for the transcode operation to complete before failing the test. */
- private static final int TRANSCODE_TIMEOUT_SECONDS = 2;
- private Context mContext;
- private MediaTranscodeManager mMediaTranscodeManager = null;
- private Uri mSourceHEVCVideoUri = null;
- private Uri mDestinationUri = null;
- // Use mock transcoding service for testing the api.
- private MockTranscodingService mTranscodingService = null;
-
- // Setting for transcoding to H.264.
- private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final int BIT_RATE = 2000000; // 2Mbps
- private static final int WIDTH = 1920;
- private static final int HEIGHT = 1080;
-
- // A mock transcoding service that will take constant 300ms to process each transcoding job.
- // Instead of doing real transcoding, it will return the dst uri directly.
- class MockTranscodingService extends IMediaTranscodingService.Stub {
- private final ScheduledExecutorService mJobScheduler = Executors.newScheduledThreadPool(1);
- private int mNumOfClients = 0;
- private AtomicInteger mJobId = new AtomicInteger();
-
- // A runnable that will process the job.
- private class ProcessingJobRunnable implements Runnable {
- private TranscodingJobParcel mJob;
- private ITranscodingClientCallback mCallback;
- private ConcurrentMap<Integer, ScheduledFuture<?>> mJobMap;
-
- ProcessingJobRunnable(ITranscodingClientCallback callback,
- TranscodingJobParcel job,
- ConcurrentMap<Integer, ScheduledFuture<?>> jobMap) {
- mJob = job;
- mCallback = callback;
- mJobMap = jobMap;
- }
-
- @Override
- public void run() {
- Log.d(TAG, "Start to process job " + mJob.jobId);
- TranscodingResultParcel result = new TranscodingResultParcel();
- try {
- // Try to open the source fd.
- ParcelFileDescriptor sourceFd = mCallback.openFileDescriptor(
- mJob.request.sourceFilePath, "r");
- if (sourceFd == null) {
- Log.d(TAG, "Failed to open sourceFd");
- // TODO(hkuang): Pass the correct error code.
- mCallback.onTranscodingFailed(mJob.jobId, 1);
- return;
- } else {
- Log.d(TAG, "Successfully open sourceFd");
- }
-
- // Try to write to the destination fd.
- ParcelFileDescriptor destinationFd = mCallback.openFileDescriptor(
- mJob.request.destinationFilePath, "w");
- if (destinationFd == null) {
- Log.d(TAG, "Failed to open destinationFd");
- // TODO(hkuang): Pass the correct error code.
- mCallback.onTranscodingFailed(mJob.jobId, 1);
- return;
- } else {
- Log.d(TAG, "Successfully open destinationFd");
- }
-
- mCallback.onTranscodingFinished(mJob.jobId, result);
- // Removes the job from job map.
- mJobMap.remove(mJob.jobId);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to callback to client");
- }
- }
- }
-
- @Override
- public ITranscodingClient registerClient(ITranscodingClientCallback callback,
- String clientName, String opPackageName, int clientUid, int clientPid)
- throws RemoteException {
- Log.d(TAG, "MockTranscodingService creates one client");
-
- ITranscodingClient client = new ITranscodingClient.Stub() {
- private final ConcurrentMap<Integer, ScheduledFuture<?>> mPendingTranscodingJobs =
- new ConcurrentHashMap<Integer, ScheduledFuture<?>>();
-
- @Override
- public boolean submitRequest(TranscodingRequestParcel inRequest,
- TranscodingJobParcel outjob) {
- Log.d(TAG, "Mock client gets submitRequest");
- try {
- outjob.request = inRequest;
- outjob.jobId = mJobId.getAndIncrement();
- Log.i(TAG, "Generate new job " + outjob.jobId);
- Log.i(TAG, "Source Uri " + inRequest.sourceFilePath);
- Log.i(TAG, "Destination Uri " + inRequest.destinationFilePath);
-
- // Schedules the job to run after inRequest.processingDelayMs.
- ScheduledFuture<?> transcodingFuture = mJobScheduler.schedule(
- new ProcessingJobRunnable(callback, outjob,
- mPendingTranscodingJobs),
- inRequest.testConfig == null ? 0
- : inRequest.testConfig.processingTotalTimeMs,
- TimeUnit.MILLISECONDS);
- mPendingTranscodingJobs.put(outjob.jobId, transcodingFuture);
- } catch (RejectedExecutionException e) {
- Log.e(TAG, "Failed to schedule transcoding job: " + e);
- return false;
- }
-
- return true;
- }
-
- @Override
- public boolean cancelJob(int jobId) throws RemoteException {
- Log.d(TAG, "Mock client gets cancelJob " + jobId);
- // Cancels the job is still in the mPendingTranscodingJobs.
- if (mPendingTranscodingJobs.containsKey(jobId)) {
- // Cancel the future task for transcoding.
- mPendingTranscodingJobs.get(jobId).cancel(true);
-
- // Remove the job from the mPendingTranscodingJobs.
- mPendingTranscodingJobs.remove(jobId);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean getJobWithId(int jobId, TranscodingJobParcel job)
- throws RemoteException {
- // This will be implemented this if needed in the test.
- return true;
- }
-
- @Override
- public void unregister() throws RemoteException {
- Log.d(TAG, "Mock client gets unregister");
- // This will be implemented this if needed in the test.
- mNumOfClients--;
- }
- };
- mNumOfClients++;
- return client;
- }
-
- @Override
- public int getNumOfClients() throws RemoteException {
- return mNumOfClients;
- }
- }
-
- public MediaTranscodeManagerWithMockServiceTest() {
- super("com.android.MediaTranscodeManagerWithMockServiceTest", MediaTranscodingTest.class);
- }
-
- private static Uri resourceToUri(Context context, int resId) {
- Uri uri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(context.getResources().getResourcePackageName(resId))
- .appendPath(context.getResources().getResourceTypeName(resId))
- .appendPath(context.getResources().getResourceEntryName(resId))
- .build();
- return uri;
- }
-
- private static Uri generateNewUri(Context context, String filename) {
- File outFile = new File(context.getExternalCacheDir(), filename);
- return Uri.fromFile(outFile);
- }
-
- // Generates a invalid uri which will let the mock service return transcoding failure.
- private static Uri generateInvalidTranscodingUri(Context context) {
- File outFile = new File(context.getExternalCacheDir(), "InvalidUri.mp4");
- return Uri.fromFile(outFile);
- }
-
- /**
- * Creates a MediaFormat with the basic set of values.
- */
- private static MediaFormat createMediaFormat() {
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- return format;
- }
-
- @Override
- public void setUp() throws Exception {
- Log.d(TAG, "setUp");
- super.setUp();
- mTranscodingService = new MockTranscodingService();
- mContext = getInstrumentation().getContext();
- mMediaTranscodeManager = mContext.getSystemService(MediaTranscodeManager.class);
- assertNotNull(mMediaTranscodeManager);
-
- // Setup source HEVC file uri.
- mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC);
-
- // Setup destination file.
- mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
- }
-
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- /**
- * Verify that setting null destination uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithNullDestinationUri() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(null)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting null source uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithNullSourceUri() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(null)
- .setDestinationUri(mDestinationUri)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .build();
- });
- }
-
- /**
- * Verify that not setting source uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutSourceUri() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that not setting destination uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutDestinationUri() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting image transcoding mode will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithUnsupportedMode() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_IMAGE)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting video transcoding without setting video format will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutVideoFormat() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .build();
- });
- }
-
- void testTranscodingWithExpectResult(Uri srcUri, Uri dstUri, int expectedResult)
- throws Exception {
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- TranscodingTestConfig testConfig = new TranscodingTestConfig();
- testConfig.passThroughMode = true;
- testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding.
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(srcUri)
- .setDestinationUri(dstUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .setTestConfig(testConfig)
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
- transcodingJob -> {
- Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
- assertTrue("Transcoding should failed.",
- transcodingJob.getResult() == expectedResult);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(job);
-
- if (job != null) {
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Transcode failed to complete in time.", finishedOnTime);
- }
-
- if (expectedResult == TranscodingJob.RESULT_SUCCESS) {
- // Checks the destination file get generated.
- File file = new File(dstUri.getPath());
- assertTrue("Failed to create destination file", file.exists());
-
- // Removes the file.
- file.delete();
- }
- }
-
- // Tests transcoding from invalid a invalid and expects failure.
- @Test
- public void testTranscodingInvalidSrcUri() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- Uri invalidSrcUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/source.mp4");
- Log.d(TAG, "Transcoding from source: " + invalidSrcUri);
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/temp.mp4");
- Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
- testTranscodingWithExpectResult(invalidSrcUri, destinationUri, TranscodingJob.RESULT_ERROR);
- }
-
- // Tests transcoding to a uri in res folder and expects failure as we could not write to res
- // folder.
- @Test
- public void testTranscodingToResFolder() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/temp.mp4");
- Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingJob.RESULT_ERROR);
- }
-
- // Tests transcoding to a uri in internal storage folder and expects success.
- @Test
- public void testTranscodingToCacheDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/temp.mp4");
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingJob.RESULT_SUCCESS);
- }
-
- // Tests transcoding to a uri in internal files directory and expects success.
- @Test
- public void testTranscodingToInternalFilesDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri:
- // file:///storage/emulated/0/Android/data/com.android.mediatranscodingtest/files/temp.mp4
- Uri destinationUri = Uri.fromFile(new File(mContext.getFilesDir(), "temp.mp4"));
- Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingJob.RESULT_SUCCESS);
- }
-
- // Tests transcoding to a uri in external files directory and expects success.
- @Test
- public void testTranscodingToExternalFilesDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/files/temp.mp4
- Uri destinationUri = Uri.fromFile(new File(mContext.getExternalFilesDir(null), "temp.mp4"));
- Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingJob.RESULT_SUCCESS);
- }
-
- @Test
- public void testTranscodingOneVideo() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, mDestinationUri,
- TranscodingJob.RESULT_SUCCESS);
- }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
index 53b23927fc64..bd1551f352f4 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
@@ -36,8 +36,8 @@ public class MediaTranscodingTestRunner extends InstrumentationTestRunner {
@Override
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(MediaTranscodeManagerDiedTest.class);
suite.addTestSuite(MediaTranscodeManagerTest.class);
- suite.addTestSuite(MediaTranscodeManagerWithMockServiceTest.class);
suite.addTestSuite(MediaTranscodingBenchmark.class);
return suite;
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index e1b3151acd5b..bb40e24a68ac 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -1005,7 +1005,7 @@ package android {
field public static final int numericModifiers = 16844111; // 0x101054f
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int offset = 16844052; // 0x1010514
- field public static final int onClick = 16843375; // 0x101026f
+ field @Deprecated public static final int onClick = 16843375; // 0x101026f
field public static final int oneshot = 16843159; // 0x1010197
field public static final int opacity = 16843550; // 0x101031e
field public static final int opticalInsetBottom = 16844171; // 0x101058b
@@ -6188,6 +6188,7 @@ package android.app {
method public android.app.PictureInPictureParams build();
method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>);
method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational);
+ method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterAllowed(boolean);
method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect);
}
@@ -46546,7 +46547,8 @@ package android.telephony {
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
- method public void listen(android.telephony.PhoneStateListener, int);
+ method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
+ method public void listen(long, @NonNull android.telephony.PhoneStateListener);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 8892a2954afb..b20e6712be61 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -84,6 +84,14 @@ package android.os {
}
+package android.provider {
+
+ public final class DeviceConfig {
+ field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
+ }
+
+}
+
package android.util {
public class AtomicFile {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index f64be2b1ff03..024f4acd8940 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -4139,8 +4139,10 @@ package android.media {
public class AudioManager {
method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForCapturePresetChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener) throws java.lang.SecurityException;
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener) throws java.lang.SecurityException;
method public void clearAudioServerStateCallback();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean clearPreferredDevicesForCapturePreset(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
@@ -4151,6 +4153,7 @@ package android.media {
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
@@ -4159,6 +4162,7 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDeviceForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForCapturePresetChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean removePreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
@@ -4168,6 +4172,7 @@ package android.media {
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForCapturePreset(int, @NonNull android.media.AudioDeviceAttributes);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
@@ -4197,6 +4202,10 @@ package android.media {
method @Deprecated public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes);
}
+ public static interface AudioManager.OnPreferredDevicesForCapturePresetChangedListener {
+ method public void onPreferredDevicesForCapturePresetChanged(int, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
+ }
+
public static interface AudioManager.OnPreferredDevicesForStrategyChangedListener {
method public void onPreferredDevicesForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>);
}
@@ -4274,11 +4283,8 @@ package android.media {
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int RADIO_TUNER = 1998; // 0x7ce
}
- public final class MediaTranscodeManager implements java.lang.AutoCloseable {
- method public void close();
+ public final class MediaTranscodeManager {
method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException;
- method protected void finalize();
- field public static final int PRIORITY_OFFLINE = 2; // 0x2
field public static final int PRIORITY_REALTIME = 1; // 0x1
field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
}
@@ -4307,7 +4313,7 @@ package android.media {
}
@java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener {
- method public void onProgressUpdate(@IntRange(from=0, to=100) int);
+ method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int);
}
public static final class MediaTranscodeManager.TranscodingRequest {
@@ -9742,6 +9748,7 @@ package android.telephony {
method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
+ method public void onPhysicalChannelConfigurationChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
@@ -9749,12 +9756,29 @@ package android.telephony {
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
+ field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 4294967296L; // 0x100000000L
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
}
+ public final class PhysicalChannelConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCellBandwidthDownlink();
+ method public int getChannelNumber();
+ method public int getConnectionStatus();
+ method public int getNetworkType();
+ method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
+ field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+ field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+ field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
+ }
+
public final class PreciseCallState implements android.os.Parcelable {
ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 616e56288392..3def945dd03c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -28,7 +28,6 @@ import com.android.systemui.car.window.SystemUIOverlayWindowManager;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
-import com.android.systemui.onehanded.OneHandedUI;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -94,12 +93,6 @@ public abstract class CarSystemUIBinder {
@ClassKey(LatencyTester.class)
public abstract SystemUI bindLatencyTester(LatencyTester sysui);
- /** Inject into OneHandedUI. */
- @Binds
- @IntoMap
- @ClassKey(OneHandedUI.class)
- public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
-
/** Inject into PowerUI. */
@Binds
@IntoMap
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index fe4cba8e73cd..8d91e7eae91a 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -54,8 +54,8 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import java.util.concurrent.Executor;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
index 1b00c6301011..d928ad0f42c9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
@@ -34,7 +34,7 @@ import androidx.annotation.CallSuper;
import com.android.systemui.R;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
index 7311cdb68a3c..bed803eedc22 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
@@ -40,8 +40,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarSystemUiTest;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.tests.R;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index f8952ace3cb3..4d31ce97e8b7 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -334,6 +334,11 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
throw new IOException(
"Failed to start installation with requested size: " + mUserdataSize);
}
+ // Reset installation session and verify that installation completes successfully.
+ mInstallationSession = null;
+ if (!mDynSystem.closePartition()) {
+ throw new IOException("Failed to complete partition installation: userdata");
+ }
}
private void installImages()
@@ -503,6 +508,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
imageValidationThrowOrWarning(new KeyRevokedException(publicKey));
}
}
+
+ // Reset installation session and verify that installation completes successfully.
+ mInstallationSession = null;
+ if (!mDynSystem.closePartition()) {
+ throw new IOException("Failed to complete partition installation: " + partitionName);
+ }
}
private static String toHexString(byte[] bytes) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index b2808061586b..2fd46d94d5cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -13,6 +13,7 @@ import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -29,6 +30,10 @@ import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
+import androidx.annotation.NonNull;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.UserIcons;
import com.android.launcher3.icons.IconFactory;
@@ -504,4 +509,25 @@ public class Utils {
== NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
return !isInIwlan;
}
+
+ /**
+ * Returns a bitmap with rounded corner.
+ *
+ * @param context application context.
+ * @param source bitmap to apply round corner.
+ * @param cornerRadius corner radius value.
+ */
+ public static Bitmap convertCornerRadiusBitmap(@NonNull Context context,
+ @NonNull Bitmap source, @NonNull float cornerRadius) {
+ final Bitmap roundedBitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ final RoundedBitmapDrawable drawable =
+ RoundedBitmapDrawableFactory.create(context.getResources(), source);
+ drawable.setAntiAlias(true);
+ drawable.setCornerRadius(cornerRadius);
+ final Canvas canvas = new Canvas(roundedBitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return roundedBitmap;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 68f72896c251..8f8f859d1ada 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -18,6 +18,7 @@ import android.util.Log;
import android.util.Pair;
import androidx.annotation.DrawableRes;
+import androidx.core.graphics.drawable.IconCompat;
import com.android.settingslib.R;
import com.android.settingslib.widget.AdaptiveIcon;
@@ -216,6 +217,23 @@ public class BluetoothUtils {
}
/**
+ * Create an Icon pointing to a drawable.
+ */
+ public static IconCompat createIconWithDrawable(Drawable drawable) {
+ Bitmap bitmap;
+ if (drawable instanceof BitmapDrawable) {
+ bitmap = ((BitmapDrawable) drawable).getBitmap();
+ } else {
+ final int width = drawable.getIntrinsicWidth();
+ final int height = drawable.getIntrinsicHeight();
+ bitmap = createBitmap(drawable,
+ width > 0 ? width : 1,
+ height > 0 ? height : 1);
+ }
+ return IconCompat.createWithBitmap(bitmap);
+ }
+
+ /**
* Build device icon with advanced outline
*/
public static Drawable buildAdvancedDrawable(Context context, Drawable drawable) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index a29314817a8f..fbd88763fff4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -58,10 +58,14 @@ class SettingsProtoDumpUtil {
ConfigSettingsProto.CONNECTIVITY_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ConfigSettingsProto.CONTENT_CAPTURE_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_DEVICE_IDLE,
+ ConfigSettingsProto.DEVICE_IDLE_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_GAME_DRIVER,
ConfigSettingsProto.GAME_DRIVER_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
ConfigSettingsProto.INPUT_NATIVE_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ ConfigSettingsProto.JOB_SCHEDULER_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_NETD_NATIVE,
ConfigSettingsProto.NETD_NATIVE_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_PRIVACY,
@@ -564,9 +568,6 @@ class SettingsProtoDumpUtil {
Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
GlobalSettingsProto.Device.PROVISIONING_MOBILE_DATA_ENABLED);
dumpSetting(s, p,
- Settings.Global.DEVICE_IDLE_CONSTANTS,
- GlobalSettingsProto.Device.IDLE_CONSTANTS);
- dumpSetting(s, p,
Settings.Global.DEVICE_POLICY_CONSTANTS,
GlobalSettingsProto.Device.POLICY_CONSTANTS);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index f219aecfc9d9..d8f772d7f440 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -230,7 +230,6 @@ public class SettingsBackupTest {
Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR,
Settings.Global.DEVICE_DEMO_MODE,
- Settings.Global.DEVICE_IDLE_CONSTANTS,
Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS,
Settings.Global.BATTERY_SAVER_CONSTANTS,
Settings.Global.BATTERY_TIP_CONSTANTS,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6db3d0b8dff2..e3f75e3e0b34 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -390,7 +390,7 @@
</activity-alias>
<activity
- android:name=".stackdivider.ForcedResizableInfoActivity"
+ android:name="com.android.wm.shell.splitscreen.ForcedResizableInfoActivity"
android:theme="@style/ForcedResizableTheme"
android:excludeFromRecents="true"
android:stateNotNeeded="true"
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index bd93c396aa16..ee8d02301d5d 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -111,10 +111,6 @@ Plays ringtones.
Shows UI for keyboard shortcuts (triggered by keyboard shortcut).
-### [com.android.systemui.onehanded.OneHandedUI](/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java)
-
-Shows the overlay controls when One handed is triggered.
-
### [com.android.systemui.shortcut.ShortcutKeyDispatcher](/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java)
Dispatches shortcut to System UI components.
diff --git a/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..998db3b44b19
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..998db3b44b19
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
+
diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
index 708dfd01975a..d28d5664d725 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
@@ -37,6 +37,7 @@
android:layout_height="@dimen/tv_volume_dialog_bubble_size"
android:maxLength="2"
android:gravity="center"
+ android:fontFeatureSettings="tnum"
android:background="@drawable/tv_volume_dialog_circle"
android:textSize="@dimen/tv_volume_number_text_size"
android:textColor="@color/accent_tint_color_selector"/>
diff --git a/packages/SystemUI/res/layout/media_view.xml b/packages/SystemUI/res/layout/media_view.xml
index ed870f8bb2ef..170f2c4e0bea 100644
--- a/packages/SystemUI/res/layout/media_view.xml
+++ b/packages/SystemUI/res/layout/media_view.xml
@@ -166,8 +166,7 @@
android:layout_height="wrap_content"
android:clickable="true"
android:maxHeight="@dimen/qs_media_enabled_seekbar_height"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
+ android:paddingVertical="@dimen/qs_media_enabled_seekbar_vertical_padding"
android:thumbTint="@color/media_primary_text"
android:progressTint="@color/media_seekbar_progress"
android:progressBackgroundTint="@color/media_disabled"
diff --git a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml b/packages/SystemUI/res/values-mcc310-mnc004/strings.xml
new file mode 100644
index 000000000000..f8ed0c01fa83
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc310-mnc004/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml b/packages/SystemUI/res/values-mcc311-mnc480/strings.xml
new file mode 100644
index 000000000000..f8ed0c01fa83
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc311-mnc480/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 5d20564a3ab8..be66320975d9 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -29,9 +29,6 @@
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">left;back,home,recent;right</string>
- <!-- Animation duration when using long press on recents to dock -->
- <integer name="long_press_dock_anim_duration">290</integer>
-
<!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
<integer name="navigation_bar_deadzone_orientation">0</integer>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 4a94038f4533..66304013da46 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -39,7 +39,6 @@
<item>com.android.systemui.SizeCompatModeActivityController</item>
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.toast.ToastUI</item>
- <item>com.android.systemui.onehanded.OneHandedUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7faa2a44bb6c..1c3fba2abacd 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -161,9 +161,6 @@
<!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) -->
<integer name="ambient_notification_extension_time">10000</integer>
- <!-- Animation duration when using long press on recents to dock -->
- <integer name="long_press_dock_anim_duration">250</integer>
-
<!-- Whether to enable KeyguardService or not -->
<bool name="config_enableKeyguardService">true</bool>
@@ -320,7 +317,6 @@
<item>com.android.systemui.accessibility.WindowMagnification</item>
<item>com.android.systemui.accessibility.SystemActions</item>
<item>com.android.systemui.toast.ToastUI</item>
- <item>com.android.systemui.onehanded.OneHandedUI</item>
<item>com.android.systemui.wmshell.WMShell</item>
</string-array>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7b80f00e8333..76c61fb6e1e5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -954,12 +954,6 @@
<dimen name="fab_elevation">12dp</dimen>
<dimen name="fab_press_translation_z">9dp</dimen>
- <!-- How high we lift the divider when touching -->
- <dimen name="docked_stack_divider_lift_elevation">4dp</dimen>
-
- <dimen name="docked_divider_handle_width">16dp</dimen>
- <dimen name="docked_divider_handle_height">2dp</dimen>
-
<dimen name="battery_detail_graph_space_top">27dp</dimen>
<dimen name="battery_detail_graph_space_bottom">27dp</dimen>
@@ -1261,6 +1255,8 @@
<dimen name="qs_footer_horizontal_margin">22dp</dimen>
<dimen name="qs_media_disabled_seekbar_height">1dp</dimen>
<dimen name="qs_media_enabled_seekbar_height">3dp</dimen>
+ <dimen name="qs_media_enabled_seekbar_vertical_padding">15dp</dimen>
+ <dimen name="qs_media_disabled_seekbar_vertical_padding">16dp</dimen>
<!-- Window magnification -->
<dimen name="magnification_border_drag_size">35dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index a56f6f56836a..2f018b9239b5 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -103,13 +103,6 @@
<item type="id" name="contains_transformed_view" />
<item type="id" name="is_clicked_heads_up_tag" />
- <!-- Accessibility actions for the docked stack divider -->
- <item type="id" name="action_move_tl_full" />
- <item type="id" name="action_move_tl_70" />
- <item type="id" name="action_move_tl_50" />
- <item type="id" name="action_move_tl_30" />
- <item type="id" name="action_move_rb_full" />
-
<item type="id" name="bottom_roundess_animator_tag"/>
<item type="id" name="bottom_roundess_animator_start_tag"/>
<item type="id" name="bottom_roundess_animator_end_tag"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bfa7532349aa..e58bf3bad795 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2260,31 +2260,6 @@
<!-- SysUI Tuner: Other section -->
<string name="other">Other</string>
- <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->
- <string name="accessibility_divider">Split-screen divider</string>
-
- <!-- Accessibility action for moving docked stack divider to make the left screen full screen [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_left_full">Left full screen</string>
- <!-- Accessibility action for moving docked stack divider to make the left screen 70% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_left_70">Left 70%</string>
- <!-- Accessibility action for moving docked stack divider to make the left screen 50% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_left_50">Left 50%</string>
- <!-- Accessibility action for moving docked stack divider to make the left screen 30% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_left_30">Left 30%</string>
- <!-- Accessibility action for moving docked stack divider to make the right screen full screen [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_right_full">Right full screen</string>
-
- <!-- Accessibility action for moving docked stack divider to make the top screen full screen [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_top_full">Top full screen</string>
- <!-- Accessibility action for moving docked stack divider to make the top screen 70% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_top_70">Top 70%</string>
- <!-- Accessibility action for moving docked stack divider to make the top screen 50% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_top_50">Top 50%</string>
- <!-- Accessibility action for moving docked stack divider to make the top screen 30% [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_top_30">Top 30%</string>
- <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
- <string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
-
<!-- Accessibility description of a QS tile while editing positions [CHAR LIMIT=NONE] -->
<string name="accessibility_qs_edit_tile_label">Position <xliff:g id="position" example="2">%1$d</xliff:g>, <xliff:g id="tile_name" example="Wi-Fi">%2$s</xliff:g>. Double tap to edit.</string>
@@ -2312,16 +2287,6 @@
<!-- Label for button that reports a touch that was wrongly rejected by the lockscreen. For debugging only. [CHAR LIMIT=NONE] -->
<string name="report_rejected_touch" translatable="false">Report rejected touch</string>
- <!-- Multi-Window strings -->
- <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed in split-screen and that things might crash/not work properly [CHAR LIMIT=NONE] -->
- <string name="dock_forced_resizable">App may not work with split-screen.</string>
- <!-- Warning message when we try to dock a non-resizeable task and launch it in fullscreen instead. -->
- <string name="dock_non_resizeble_failed_to_dock_text">App does not support split-screen.</string>
- <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity to be displayed on a secondary display and that things might crash/not work properly [CHAR LIMIT=NONE] -->
- <string name="forced_resizable_secondary_display">App may not work on a secondary display.</string>
- <!-- Warning message when we try to launch a non-resizeable activity on a secondary display and launch it on the primary instead. -->
- <string name="activity_launch_on_secondary_display_failed_text">App does not support launch on secondary displays.</string>
-
<!-- accessibility label for button to open settings [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_settings">Open settings.</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ee07e613a0c5..58563f49dce4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -24,21 +24,6 @@
<item name="android:layout_marginBottom">0dp</item>
</style>
- <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
- <style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
- <item name="android:windowBackground">@drawable/forced_resizable_background</item>
- <item name="android:statusBarColor">@*android:color/transparent</item>
- <item name="android:windowAnimationStyle">@style/Animation.ForcedResizable</item>
- </style>
-
- <style name="Animation.ForcedResizable" parent="@android:style/Animation">
- <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
-
- <!-- If the target stack doesn't have focus, we do a task to front animation. -->
- <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item>
- <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
- </style>
-
<style name="PipPhoneOverlayControlTheme" parent="@android:style/Theme.Material">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
@@ -483,23 +468,6 @@
<item name="android:background">@drawable/btn_borderless_rect</item>
</style>
- <style name="DockedDividerBackground">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">10dp</item>
- <item name="android:layout_gravity">center_vertical</item>
- </style>
-
- <style name="DockedDividerMinimizedShadow">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">8dp</item>
- </style>
-
- <style name="DockedDividerHandle">
- <item name="android:layout_gravity">center_horizontal</item>
- <item name="android:layout_width">96dp</item>
- <item name="android:layout_height">48dp</item>
- </style>
-
<style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="android:windowActionBar">false</item>
<item name="preferenceTheme">@style/TunerPreferenceTheme</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 17b840cc7a20..744a77f5cff9 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -32,10 +32,10 @@ import android.view.View;
import android.view.ViewConfiguration;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.policy.ScrollAdapter;
+import com.android.wm.shell.animation.FlingAnimationUtils;
public class ExpandHelper implements Gefingerpoken {
public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index e91284b546db..8aa3493cc105 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -37,8 +37,8 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.wm.shell.animation.FlingAnimationUtils;
public class SwipeHelper implements Gefingerpoken {
static final String TAG = "com.android.systemui.SwipeHelper";
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 80150c9b7e32..33310962a6f2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -164,7 +164,7 @@ public class BubbleExpandedView extends LinearLayout {
ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
0 /* enterResId */, 0 /* exitResId */);
options.setTaskAlwaysOnTop(true);
- options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ // Soptions.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
// Post to keep the lifecycle normal
post(() -> {
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 0dd9488f1d3e..ac01ba1539b3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -65,7 +65,6 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -78,6 +77,7 @@ import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.util.leak.LeakDetector;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
import java.util.concurrent.Executor;
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index c331bd377eec..3a5ce4d82540 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -28,7 +28,6 @@ import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
-import com.android.systemui.onehanded.OneHandedUI;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -90,12 +89,6 @@ public abstract class SystemUIBinder {
@ClassKey(LatencyTester.class)
public abstract SystemUI bindLatencyTester(LatencyTester sysui);
- /** Inject into OneHandedUI. */
- @Binds
- @IntoMap
- @ClassKey(OneHandedUI.class)
- public abstract SystemUI bindOneHandedUI(OneHandedUI sysui);
-
/** Inject into PowerUI. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
index 1ae54d60d3fa..d789501ffdef 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -28,10 +28,14 @@ import com.android.systemui.R
*/
class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarViewModel.Progress> {
- val seekBarDefaultMaxHeight = holder.seekBar.context.resources
+ val seekBarEnabledMaxHeight = holder.seekBar.context.resources
.getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_height)
val seekBarDisabledHeight = holder.seekBar.context.resources
.getDimensionPixelSize(R.dimen.qs_media_disabled_seekbar_height)
+ val seekBarEnabledVerticalPadding = holder.seekBar.context.resources
+ .getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_vertical_padding)
+ val seekBarDisabledVerticalPadding = holder.seekBar.context.resources
+ .getDimensionPixelSize(R.dimen.qs_media_disabled_seekbar_vertical_padding)
/** Updates seek bar views when the data model changes. */
@UiThread
@@ -39,6 +43,7 @@ class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarVi
if (!data.enabled) {
if (holder.seekBar.maxHeight != seekBarDisabledHeight) {
holder.seekBar.maxHeight = seekBarDisabledHeight
+ setVerticalPadding(seekBarDisabledVerticalPadding)
}
holder.seekBar.setEnabled(false)
holder.seekBar.getThumb().setAlpha(0)
@@ -51,8 +56,9 @@ class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarVi
holder.seekBar.getThumb().setAlpha(if (data.seekAvailable) 255 else 0)
holder.seekBar.setEnabled(data.seekAvailable)
- if (holder.seekBar.maxHeight != seekBarDefaultMaxHeight) {
- holder.seekBar.maxHeight = seekBarDefaultMaxHeight
+ if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) {
+ holder.seekBar.maxHeight = seekBarEnabledMaxHeight
+ setVerticalPadding(seekBarEnabledVerticalPadding)
}
data.duration?.let {
@@ -67,4 +73,11 @@ class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarVi
it / DateUtils.SECOND_IN_MILLIS))
}
}
+
+ @UiThread
+ fun setVerticalPadding(padding: Int) {
+ val leftPadding = holder.seekBar.paddingLeft
+ val rightPadding = holder.seekBar.paddingRight
+ holder.seekBar.setPadding(leftPadding, padding, rightPadding, padding)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index c7e78174f474..4e0df214d884 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -122,7 +122,6 @@ import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -137,6 +136,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.PrintWriter;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 9b9dc6dec583..339e504a3cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -55,7 +55,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -65,6 +64,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 8a468f6eb709..13b9a552d75c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -87,12 +87,12 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.PrintWriter;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
new file mode 100644
index 000000000000..b7c6262b07e0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.onehanded;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+
+import java.io.PrintWriter;
+
+/**
+ * Interface to engage one handed feature.
+ */
+public interface OneHanded {
+ /**
+ * Return whether the device has one handed feature or not.
+ */
+ boolean hasOneHandedFeature();
+
+ /**
+ * Return one handed settings enabled or not.
+ */
+ boolean isOneHandedEnabled();
+
+ /**
+ * Return swipe to notification settings enabled or not.
+ */
+ boolean isSwipeToNotificationEnabled();
+
+ /**
+ * Enters one handed mode.
+ */
+ void startOneHanded();
+
+ /**
+ * Exits one handed mode.
+ */
+ void stopOneHanded();
+
+ /**
+ * Exits one handed mode with {@link OneHandedEvents}.
+ */
+ void stopOneHanded(int event);
+
+ /**
+ * Set navigation 3 button mode enabled or disabled by users.
+ */
+ void setThreeButtonModeEnabled(boolean enabled);
+
+ /**
+ * Register callback to be notified after {@link OneHandedDisplayAreaOrganizer}
+ * transition start or finish
+ */
+ void registerTransitionCallback(OneHandedTransitionCallback callback);
+
+ /**
+ * Register callback for one handed gesture, this gesture callbcak will be activated on
+ * 3 button navigation mode only
+ */
+ void registerGestureCallback(OneHandedGestureEventCallback callback);
+
+ /**
+ * Dump one handed status.
+ */
+ void dump(@NonNull PrintWriter pw);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
index bb59449d114d..90adf838440c 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
@@ -16,195 +16,262 @@
package com.android.systemui.onehanded;
+import static android.os.UserHandle.USER_CURRENT;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
-
-import android.content.ComponentName;
import android.content.Context;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.database.ContentObserver;
import android.graphics.Point;
-import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.view.KeyEvent;
+import android.provider.Settings;
+import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
-import javax.inject.Inject;
-
/**
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
-@SysUISingleton
-public class OneHandedController implements Dumpable {
- private static final String TAG = "OneHandedManager";
+public class OneHandedController implements OneHanded {
+ private static final String TAG = "OneHandedController";
+
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
+ private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
+ "com.android.internal.systemui.onehanded.gestural";
+
+ static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
+ private final boolean mHasOneHandedFeature;
private boolean mIsOneHandedEnabled;
private boolean mIsSwipeToNotificationEnabled;
private boolean mTaskChangeToExit;
private float mOffSetFraction;
- private final CommandQueue mCommandQueue;
+ private final Context mContext;
private final DisplayController mDisplayController;
private final OneHandedGestureHandler mGestureHandler;
private final OneHandedTimeoutHandler mTimeoutHandler;
private final OneHandedTouchHandler mTouchHandler;
private final OneHandedTutorialHandler mTutorialHandler;
- private final SysUiState mSysUiFlagContainer;
+ private final IOverlayManager mOverlayManager;
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
/**
- * Handler for system task stack changes, exit when user lunch new task or bring task to front
+ * Handle rotation based on OnDisplayChangingListener callback
*/
- private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ private final DisplayChangeController.OnDisplayChangingListener mRotationController =
+ (display, fromRotation, toRotation, wct) -> {
+ if (mDisplayAreaOrganizer != null) {
+ mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation);
+ }
+ };
+
+ private final ContentObserver mEnabledObserver = new ContentObserver(mMainHandler) {
@Override
- public void onTaskCreated(int taskId, ComponentName componentName) {
- if (!mIsOneHandedEnabled || !mDisplayAreaOrganizer.isInOneHanded()) {
- return;
- }
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
- stopOneHanded();
+ public void onChange(boolean selfChange) {
+ final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+ mContext.getContentResolver());
+ OneHandedEvents.writeEvent(enabled
+ ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
+ : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
+
+ setOneHandedEnabled(enabled);
+
+ // Also checks swipe to notification settings since they all need gesture overlay.
+ setEnabledGesturalOverlay(
+ enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver()));
}
+ };
+ private final ContentObserver mTimeoutObserver = new ContentObserver(mMainHandler) {
@Override
- public void onTaskMovedToFront(int taskId) {
- if (!mIsOneHandedEnabled || !mDisplayAreaOrganizer.isInOneHanded()) {
- return;
+ public void onChange(boolean selfChange) {
+ final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
+ mContext.getContentResolver());
+ int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
+ switch (newTimeout) {
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
+ break;
+ case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
+ metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ OneHandedEvents.writeEvent(metricsId);
+
+ if (mTimeoutHandler != null) {
+ mTimeoutHandler.setTimeout(newTimeout);
}
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
- stopOneHanded();
}
};
- /**
- * Handle rotation based on OnDisplayChangingListener callback
- */
- private final DisplayChangeController.OnDisplayChangingListener mRotationController =
- (display, fromRotation, toRotation, wct) -> {
- if (mDisplayAreaOrganizer != null) {
- mDisplayAreaOrganizer.onRotateDisplay(fromRotation, toRotation);
+ private final ContentObserver mTaskChangeExitObserver = new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
+ mContext.getContentResolver());
+ OneHandedEvents.writeEvent(enabled
+ ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
+ : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);
+
+ setTaskChangeToExit(enabled);
+ }
+ };
+
+ private final ContentObserver mSwipeToNotificationEnabledObserver =
+ new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled =
+ OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver());
+ setSwipeToNotificationEnabled(enabled);
+
+ // Also checks one handed mode settings since they all need gesture overlay.
+ setEnabledGesturalOverlay(
+ enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+ mContext.getContentResolver()));
}
};
/**
- * Constructor of OneHandedManager
+ * The static constructor method to create OneHnadedController.
*/
- @Inject
- public OneHandedController(Context context,
- CommandQueue commandQueue,
- DisplayController displayController,
- NavigationModeController navigationModeController,
- SysUiState sysUiState) {
- mCommandQueue = commandQueue;
- mDisplayController = displayController;
- mDisplayController.addDisplayChangingController(mRotationController);
- mSysUiFlagContainer = sysUiState;
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
-
- mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- context.getContentResolver());
- mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- context.getContentResolver());
- mTimeoutHandler = OneHandedTimeoutHandler.get();
- mTouchHandler = new OneHandedTouchHandler();
- mTutorialHandler = new OneHandedTutorialHandler(context);
- mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(context, displayController,
- new OneHandedAnimationController(context), mTutorialHandler);
- mGestureHandler = new OneHandedGestureHandler(
- context, displayController, navigationModeController);
- updateOneHandedEnabled();
- setupGestures();
+ public static OneHandedController create(
+ Context context, DisplayController displayController) {
+ OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context);
+ OneHandedAnimationController animationController =
+ new OneHandedAnimationController(context);
+ OneHandedTouchHandler touchHandler = new OneHandedTouchHandler();
+ OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
+ context, displayController);
+ OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
+ context, displayController, animationController, tutorialHandler);
+ return new OneHandedController(context, displayController, organizer, touchHandler,
+ tutorialHandler, gestureHandler);
}
- /**
- * Constructor of OneHandedManager for testing
- */
- // TODO(b/161980408): Should remove extra constructor.
@VisibleForTesting
OneHandedController(Context context,
- CommandQueue commandQueue,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
- OneHandedGestureHandler gestureHandler,
- SysUiState sysUiState) {
- mCommandQueue = commandQueue;
+ OneHandedGestureHandler gestureHandler) {
+ mHasOneHandedFeature = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
+ if (!mHasOneHandedFeature) {
+ Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
+ mContext = null;
+ mDisplayAreaOrganizer = null;
+ mDisplayController = null;
+ mTouchHandler = null;
+ mTutorialHandler = null;
+ mGestureHandler = null;
+ mTimeoutHandler = null;
+ mOverlayManager = null;
+ return;
+ }
+
+ mContext = context;
mDisplayAreaOrganizer = displayAreaOrganizer;
mDisplayController = displayController;
- mDisplayController.addDisplayChangingController(mRotationController);
- mSysUiFlagContainer = sysUiState;
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
+ mTouchHandler = touchHandler;
+ mTutorialHandler = tutorialHandler;
+ mGestureHandler = gestureHandler;
+ mOverlayManager = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
context.getContentResolver());
mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
context.getContentResolver());
mTimeoutHandler = OneHandedTimeoutHandler.get();
- mTouchHandler = touchHandler;
- mTutorialHandler = tutorialHandler;
- mGestureHandler = gestureHandler;
- updateOneHandedEnabled();
- setupGestures();
+
+ mDisplayController.addDisplayChangingController(mRotationController);
+
+ setupCallback();
+ setupSettingObservers();
+ setupTimeoutListener();
+ setupGesturalOverlay();
+ updateSettings();
}
/**
- * Set one handed enabled or disabled by OneHanded UI when user update settings
+ * Set one handed enabled or disabled when user update settings
*/
- public void setOneHandedEnabled(boolean enabled) {
+ void setOneHandedEnabled(boolean enabled) {
mIsOneHandedEnabled = enabled;
updateOneHandedEnabled();
}
/**
- * Set one handed enabled or disabled by OneHanded UI when user update settings
+ * Set one handed enabled or disabled by when user update settings
*/
- public void setTaskChangeToExit(boolean enabled) {
- if (mTaskChangeToExit == enabled) {
- return;
- }
+ void setTaskChangeToExit(boolean enabled) {
mTaskChangeToExit = enabled;
- updateOneHandedEnabled();
}
/**
* Sets whether to enable swipe bottom to notification gesture when user update settings.
*/
- public void setSwipeToNotificationEnabled(boolean enabled) {
+ void setSwipeToNotificationEnabled(boolean enabled) {
mIsSwipeToNotificationEnabled = enabled;
updateOneHandedEnabled();
}
- /**
- * Enters one handed mode.
- */
+ @Override
+ public boolean hasOneHandedFeature() {
+ return mHasOneHandedFeature;
+ }
+
+ @Override
+ public boolean isOneHandedEnabled() {
+ return mIsOneHandedEnabled;
+ }
+
+ @Override
+ public boolean isSwipeToNotificationEnabled() {
+ return mIsSwipeToNotificationEnabled;
+ }
+
+ @Override
public void startOneHanded() {
if (!mDisplayAreaOrganizer.isInOneHanded()) {
final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
mTimeoutHandler.resetTimer();
+
+ OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN);
}
}
- /**
- * Exits one handed mode.
- */
+ @Override
public void stopOneHanded() {
if (mDisplayAreaOrganizer.isInOneHanded()) {
mDisplayAreaOrganizer.scheduleOffset(0, 0);
@@ -212,64 +279,72 @@ public class OneHandedController implements Dumpable {
}
}
- private void setupGestures() {
- mTouchHandler.registerTouchEventListener(
- new OneHandedTouchHandler.OneHandedTouchEventCallback() {
- @Override
- public void onStart() {
- if (mIsOneHandedEnabled) {
- startOneHanded();
- }
- }
-
- @Override
- public void onStop() {
- if (mIsOneHandedEnabled) {
- stopOneHanded();
- }
- }
- });
-
- mGestureHandler.setGestureEventListener(
- new OneHandedGestureHandler.OneHandedGestureEventCallback() {
- @Override
- public void onStart() {
- if (mIsOneHandedEnabled) {
- startOneHanded();
- } else if (mIsSwipeToNotificationEnabled) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
- }
- }
-
- @Override
- public void onStop() {
- if (mIsOneHandedEnabled) {
- stopOneHanded();
- } else if (mIsSwipeToNotificationEnabled) {
- mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
- }
- }
- });
-
- mDisplayAreaOrganizer.registerTransitionCallback(new OneHandedTransitionCallback() {
- @Override
- public void onStartFinished(Rect bounds) {
- mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
- true).commitUpdate(DEFAULT_DISPLAY);
- }
+ @Override
+ public void stopOneHanded(int event) {
+ if (!mTaskChangeToExit && event == OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT) {
+ //Task change exit not enable, do nothing and return here.
+ return;
+ }
- @Override
- public void onStopFinished(Rect bounds) {
- mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
- false).commitUpdate(DEFAULT_DISPLAY);
- }
- });
+ if (mDisplayAreaOrganizer.isInOneHanded()) {
+ OneHandedEvents.writeEvent(event);
+ }
+
+ stopOneHanded();
+ }
+
+ @Override
+ public void setThreeButtonModeEnabled(boolean enabled) {
+ mGestureHandler.onThreeButtonModeEnabled(enabled);
+ }
+
+ @Override
+ public void registerTransitionCallback(OneHandedTransitionCallback callback) {
+ mDisplayAreaOrganizer.registerTransitionCallback(callback);
+ }
+
+ @Override
+ public void registerGestureCallback(OneHandedGestureEventCallback callback) {
+ mGestureHandler.setGestureEventListener(callback);
+ }
+ private void setupCallback() {
+ mTouchHandler.registerTouchEventListener(() ->
+ stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_OVERSPACE_OUT));
mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler);
}
+ private void setupSettingObservers() {
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED,
+ mContext.getContentResolver(), mEnabledObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
+ mContext.getContentResolver(), mTimeoutObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT,
+ mContext.getContentResolver(), mTaskChangeExitObserver);
+ OneHandedSettingsUtil.registerSettingsKeyObserver(
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ mContext.getContentResolver(), mSwipeToNotificationEnabledObserver);
+ }
+
+ private void updateSettings() {
+ setOneHandedEnabled(OneHandedSettingsUtil
+ .getSettingsOneHandedModeEnabled(mContext.getContentResolver()));
+ mTimeoutHandler.setTimeout(OneHandedSettingsUtil
+ .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
+ setTaskChangeToExit(OneHandedSettingsUtil
+ .getSettingsTapsAppToExit(mContext.getContentResolver()));
+ setSwipeToNotificationEnabled(OneHandedSettingsUtil
+ .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
+ }
+
+ private void setupTimeoutListener() {
+ mTimeoutHandler.registerTimeoutListener(timeoutTime -> {
+ stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT);
+ });
+ }
+
/**
* Query the current display real size from {@link DisplayController}
*
@@ -293,25 +368,73 @@ public class OneHandedController implements Dumpable {
mDisplayAreaOrganizer.registerOrganizer(
OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
}
- ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
- if (mTaskChangeToExit) {
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
- }
mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
}
+ private void setupGesturalOverlay() {
+ if (!OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(mContext.getContentResolver())) {
+ return;
+ }
+
+ OverlayInfo info = null;
+ try {
+ // TODO(b/157958539) migrate new RRO config file after S+
+ mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+ info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+ } catch (RemoteException e) { /* Do nothing */ }
+
+ if (info != null && !info.isEnabled()) {
+ // Enable the default gestural one handed overlay.
+ setEnabledGesturalOverlay(true);
+ }
+ }
+
+ @androidx.annotation.VisibleForTesting
+ private void setEnabledGesturalOverlay(boolean enabled) {
+ try {
+ mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ public void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
- pw.print(innerPrefix + "mSysUiFlagContainer=");
- pw.println(mSysUiFlagContainer.getFlags());
pw.print(innerPrefix + "mOffSetFraction=");
pw.println(mOffSetFraction);
if (mDisplayAreaOrganizer != null) {
- mDisplayAreaOrganizer.dump(fd, pw, args);
+ mDisplayAreaOrganizer.dump(pw);
+ }
+
+ if (mTouchHandler != null) {
+ mTouchHandler.dump(pw);
+ }
+
+ if (mTimeoutHandler != null) {
+ mTimeoutHandler.dump(pw);
+ }
+
+ if (mTutorialHandler != null) {
+ mTutorialHandler.dump(pw);
+ }
+
+ OneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver());
+
+ if (mOverlayManager != null) {
+ OverlayInfo info = null;
+ try {
+ info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY,
+ USER_CURRENT);
+ } catch (RemoteException e) { /* Do nothing */ }
+
+ if (info != null && !info.isEnabled()) {
+ pw.print(innerPrefix + "OverlayInfo=");
+ pw.println(info);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
index ad9f7ea4e945..ec40bad06b71 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -38,10 +38,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.SomeArgs;
-import com.android.systemui.Dumpable;
import com.android.wm.shell.common.DisplayController;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -58,7 +56,7 @@ import java.util.Objects;
*
* This class is also responsible for translating one handed operations within SysUI component
*/
-public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implements Dumpable {
+public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
private static final String TAG = "OneHandedDisplayAreaOrganizer";
private static final String ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION =
"persist.debug.one_handed_translate_animation_duration";
@@ -353,8 +351,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
return args;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mIsInOneHanded=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index f3be699ab821..4a493ba800ba 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -17,7 +17,6 @@
package com.android.systemui.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import android.annotation.Nullable;
import android.content.Context;
@@ -40,7 +39,6 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.navigationbar.NavigationModeController;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
@@ -49,7 +47,6 @@ import com.android.wm.shell.common.DisplayController;
* others(e.g, 2-button, full gesture mode) are handled by Launcher quick steps.
*/
public class OneHandedGestureHandler implements OneHandedTransitionCallback,
- NavigationModeController.ModeChangedListener,
DisplayChangeController.OnDisplayChangingListener {
private static final String TAG = "OneHandedGestureHandler";
private static final boolean DEBUG_GESTURE = false;
@@ -66,7 +63,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
private boolean mAllowGesture;
private boolean mIsEnabled;
private int mNavGestureHeight;
- private boolean mIsThreeButtonModeEnable;
+ private boolean mIsThreeButtonModeEnabled;
private int mRotation = Surface.ROTATION_0;
@VisibleForTesting
@@ -85,14 +82,10 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
*
* @param context {@link Context}
* @param displayController {@link DisplayController}
- * @param navigationModeController {@link NavigationModeController}
*/
- public OneHandedGestureHandler(Context context, DisplayController displayController,
- NavigationModeController navigationModeController) {
+ public OneHandedGestureHandler(Context context, DisplayController displayController) {
mDisplayController = displayController;
displayController.addDisplayChangingController(this);
- final int NavBarMode = navigationModeController.addListener(this);
- mIsThreeButtonModeEnable = (NavBarMode == NAV_BAR_MODE_3BUTTON);
mNavGestureHeight = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_gesture_height);
mDragDistThreshold = context.getResources().getDimensionPixelSize(
@@ -115,6 +108,11 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
updateIsEnabled();
}
+ void onThreeButtonModeEnabled(boolean isEnabled) {
+ mIsThreeButtonModeEnabled = isEnabled;
+ updateIsEnabled();
+ }
+
/**
* Register {@link OneHandedGestureEventCallback} to receive onStart(), onStop() callback
*/
@@ -199,7 +197,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
private void updateIsEnabled() {
disposeInputChannel();
- if (mIsEnabled && mIsThreeButtonModeEnable) {
+ if (mIsEnabled && mIsThreeButtonModeEnabled) {
final Point displaySize = new Point();
if (mDisplayController != null) {
final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY);
@@ -224,15 +222,6 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
}
@Override
- public void onNavigationModeChanged(int mode) {
- if (DEBUG_GESTURE) {
- Log.d(TAG, "onNavigationModeChanged, mode =" + mode);
- }
- mIsThreeButtonModeEnable = (mode == NAV_BAR_MODE_3BUTTON);
- updateIsEnabled();
- }
-
- @Override
public void onRotateDisplay(int displayId, int fromRotation, int toRotation,
WindowContainerTransaction t) {
mRotation = toRotation;
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
index 6bed30425c55..21329ea1b0e6 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java
@@ -25,9 +25,6 @@ import android.os.Message;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.Dumpable;
-
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +33,7 @@ import java.util.concurrent.TimeUnit;
/**
* Timeout handler for stop one handed mode operations.
*/
-public class OneHandedTimeoutHandler implements Dumpable {
+public class OneHandedTimeoutHandler {
private static final String TAG = "OneHandedTimeoutHandler";
private static boolean sIsDragging = false;
// Default timeout is ONE_HANDED_TIMEOUT_MEDIUM
@@ -150,8 +147,7 @@ public class OneHandedTimeoutHandler implements Dumpable {
}
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "sTimeout=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
index 8265da6a5f14..3d28a426f4f8 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
@@ -30,9 +30,6 @@ import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import com.android.systemui.Dumpable;
-
-import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -40,7 +37,7 @@ import java.io.PrintWriter;
* to exit, reset timer when user is in one-handed mode.
* Refer {@link OneHandedGestureHandler} to see start and stop one handed gesture
*/
-public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpable {
+public class OneHandedTouchHandler implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedTouchHandler";
private final Rect mLastUpdatedBounds = new Rect();
@@ -146,8 +143,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
mIsOnStopTransitioning = false;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mLastUpdatedBounds=");
@@ -170,11 +166,6 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
*/
public interface OneHandedTouchEventCallback {
/**
- * Handle the start event.
- */
- void onStart();
-
- /**
* Handle the exit event.
*/
void onStop();
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
index 8ef9b092bc00..beccf3dbc8de 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -33,10 +33,8 @@ import android.widget.FrameLayout;
import androidx.annotation.NonNull;
-import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
@@ -45,7 +43,7 @@ import java.io.PrintWriter;
* Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop
* one handed gesture
*/
-public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable {
+public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
private static final String TAG = "OneHandedTutorialHandler";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
@@ -170,8 +168,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Du
return lp;
}
- @Override
- public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG + "states: ");
pw.print(innerPrefix + "mLastUpdatedBounds=");
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
deleted file mode 100644
index 3348a06d5cac..000000000000
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.onehanded;
-
-import static android.os.UserHandle.USER_CURRENT;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.content.Context;
-import android.content.om.IOverlayManager;
-import android.content.om.OverlayInfo;
-import android.database.ContentObserver;
-import android.inputmethodservice.InputMethodService;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.statusbar.CommandQueue;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-import javax.inject.Inject;
-
-/**
- * A service that controls UI of the one handed mode function.
- */
-@SysUISingleton
-public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dumpable {
- private static final String TAG = "OneHandedUI";
- private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
- "com.android.internal.systemui.onehanded.gestural";
- private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
-
- private final OneHandedController mOneHandedController;
- private final CommandQueue mCommandQueue;
- private final Handler mMainHandler = new Handler(Looper.getMainLooper());
- private final IOverlayManager mOverlayManager;
- private final OneHandedTimeoutHandler mTimeoutHandler;
- private final ScreenLifecycle mScreenLifecycle;
-
- private final ContentObserver mEnabledObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- mContext.getContentResolver());
- OneHandedEvents.writeEvent(enabled
- ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
- : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
- if (mOneHandedController != null) {
- mOneHandedController.setOneHandedEnabled(enabled);
- }
-
- // Also checks swipe to notification settings since they all need gesture overlay.
- setEnabledGesturalOverlay(
- enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver()));
- }
- };
-
- private final ContentObserver mTimeoutObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
- mContext.getContentResolver());
- int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
- switch (newTimeout) {
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
- break;
- case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
- metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
- break;
- default:
- // do nothing
- break;
- }
- OneHandedEvents.writeEvent(metricsId);
-
- if (mTimeoutHandler != null) {
- mTimeoutHandler.setTimeout(newTimeout);
- }
- }
- };
-
- private final ContentObserver mTaskChangeExitObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
- mContext.getContentResolver());
- OneHandedEvents.writeEvent(enabled
- ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
- : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);
-
- if (mOneHandedController != null) {
- mOneHandedController.setTaskChangeToExit(enabled);
- }
- }
- };
-
- private final ContentObserver mSwipeToNotificationEnabledObserver =
- new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- final boolean enabled =
- OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- mContext.getContentResolver());
- if (mOneHandedController != null) {
- mOneHandedController.setSwipeToNotificationEnabled(enabled);
- }
-
- // Also checks one handed mode settings since they all need gesture overlay.
- setEnabledGesturalOverlay(
- enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- mContext.getContentResolver()));
- }
- };
-
- @Inject
- public OneHandedUI(Context context,
- CommandQueue commandQueue,
- OneHandedController oneHandedController,
- ScreenLifecycle screenLifecycle) {
- super(context);
-
- if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
- mCommandQueue = null;
- mOneHandedController = null;
- mOverlayManager = null;
- mTimeoutHandler = null;
- mScreenLifecycle = null;
- return;
- }
-
- mCommandQueue = commandQueue;
- mOneHandedController = oneHandedController;
- mTimeoutHandler = OneHandedTimeoutHandler.get();
- mScreenLifecycle = screenLifecycle;
- mOverlayManager = IOverlayManager.Stub.asInterface(
- ServiceManager.getService(Context.OVERLAY_SERVICE));
- }
-
- @Override
- public void start() {
- if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- return;
- }
- mCommandQueue.addCallback(this);
- setupKeyguardUpdateMonitor();
- setupScreenObserver();
- setupSettingObservers();
- setupTimeoutListener();
- setupGesturalOverlay();
- updateSettings();
- }
-
- private void setupGesturalOverlay() {
- if (!OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(mContext.getContentResolver())) {
- return;
- }
-
- OverlayInfo info = null;
- try {
- // TODO(b/157958539) migrate new RRO config file after S+
- mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
- info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
- } catch (RemoteException e) { /* Do nothing */ }
-
- if (info != null && !info.isEnabled()) {
- // Enable the default gestural one handed overlay.
- setEnabledGesturalOverlay(true);
- }
- }
-
- private void setupTimeoutListener() {
- mTimeoutHandler.registerTimeoutListener(timeoutTime -> {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT);
- stopOneHanded();
- });
- }
-
- private void setupKeyguardUpdateMonitor() {
- final KeyguardUpdateMonitorCallback keyguardCallback =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onKeyguardBouncerChanged(boolean bouncer) {
- if (bouncer) {
- stopOneHanded();
- }
- }
-
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
- stopOneHanded();
- }
- };
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(keyguardCallback);
- }
-
- @Override
- public void onCameraLaunchGestureDetected(int source) {
- stopOneHanded();
- }
-
- private void setupScreenObserver() {
- final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
- @Override
- public void onScreenTurningOff() {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_SCREEN_OFF_OUT);
- stopOneHanded();
- }
- };
- mScreenLifecycle.addObserver(mScreenObserver);
- }
-
- private void setupSettingObservers() {
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED,
- mContext.getContentResolver(), mEnabledObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
- mContext.getContentResolver(), mTimeoutObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT,
- mContext.getContentResolver(), mTaskChangeExitObserver);
- OneHandedSettingsUtil.registerSettingsKeyObserver(
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
- mContext.getContentResolver(), mSwipeToNotificationEnabledObserver);
- }
-
- private void updateSettings() {
- mOneHandedController.setOneHandedEnabled(OneHandedSettingsUtil
- .getSettingsOneHandedModeEnabled(mContext.getContentResolver()));
- mTimeoutHandler.setTimeout(OneHandedSettingsUtil
- .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
- mOneHandedController.setTaskChangeToExit(OneHandedSettingsUtil
- .getSettingsTapsAppToExit(mContext.getContentResolver()));
- mOneHandedController.setSwipeToNotificationEnabled(OneHandedSettingsUtil
- .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
- }
-
- @Override
- public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
- if ((vis & InputMethodService.IME_VISIBLE) != 0) {
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
- stopOneHanded();
- }
- }
-
- @VisibleForTesting
- private void setEnabledGesturalOverlay(boolean enabled) {
- try {
- mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Trigger one handed more
- */
- public void startOneHanded() {
- mOneHandedController.startOneHanded();
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN);
- }
-
- /**
- * Dismiss one handed more
- */
- public void stopOneHanded() {
- mOneHandedController.stopOneHanded();
- OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
- }
-
- /**
- * Dump all one handed data of states
- */
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- final String innerPrefix = " ";
- pw.println(TAG + "one handed states: ");
-
- if (mOneHandedController != null) {
- mOneHandedController.dump(fd, pw, args);
- }
-
- if (mTimeoutHandler != null) {
- mTimeoutHandler.dump(fd, pw, args);
- }
-
- OneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver());
-
- if (mOverlayManager != null) {
- OverlayInfo info = null;
- try {
- info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY,
- USER_CURRENT);
- } catch (RemoteException e) { /* Do nothing */ }
-
- if (info != null && !info.isEnabled()) {
- pw.print(innerPrefix + "OverlayInfo=");
- pw.println(info);
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 6f44090d2744..862405609de8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -63,10 +63,10 @@ import com.android.internal.os.SomeArgs;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.pip.phone.PipMenuActivityController;
import com.android.systemui.pip.phone.PipUpdateThread;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
index 1a805daef77e..6998e90b3a7c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java
@@ -280,6 +280,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
PackageManager pm = context.getPackageManager();
boolean supportsPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
if (!supportsPip) {
+ Log.w(TAG, "Device not support PIP feature");
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index b4f1fe72f944..5e6a6ce45b46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -130,7 +130,8 @@ public class CellularTile extends QSTileImpl<SignalState> {
return;
}
String carrierName = mController.getMobileDataNetworkName();
- if (TextUtils.isEmpty(carrierName)) {
+ boolean isInService = mController.isMobileDataNetworkInService();
+ if (TextUtils.isEmpty(carrierName) || !isInService) {
carrierName = mContext.getString(R.string.mobile_data_disable_message_default_carrier);
}
AlertDialog dialog = new Builder(mContext)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 1a7e2290e044..47002683c6b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -38,8 +38,8 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 62b35f9f5e2d..cba938f5e1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
@@ -74,7 +75,8 @@ import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.onehanded.OneHandedUI;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedEvents;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipAnimationController;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -86,12 +88,12 @@ import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -134,7 +136,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
private final Intent mQuickStepIntent;
private final ScreenshotHelper mScreenshotHelper;
- private final OneHandedUI mOneHandedUI;
+ private final Optional<OneHanded> mOneHandedOptional;
private final CommandQueue mCommandQueue;
private Region mActiveNavBarRegion;
@@ -143,6 +145,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private int mConnectionBackoffAttempts;
private boolean mBound;
private boolean mIsEnabled;
+ private boolean mHasPipFeature;
private int mCurrentBoundedUserId = -1;
private float mNavBarButtonAlpha;
private boolean mInputFocusTransferStarted;
@@ -383,7 +386,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
@Override
public void setShelfHeight(boolean visible, int shelfHeight) {
- if (!verifyCaller("setShelfHeight")) {
+ if (!verifyCaller("setShelfHeight") || !mHasPipFeature) {
+ Log.w(TAG_OPS,
+ "ByPass setShelfHeight, FEATURE_PICTURE_IN_PICTURE:" + mHasPipFeature);
return;
}
long token = Binder.clearCallingIdentity();
@@ -409,7 +414,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
@Override
public void notifySwipeToHomeFinished() {
- if (!verifyCaller("notifySwipeToHomeFinished")) {
+ if (!verifyCaller("notifySwipeToHomeFinished") || !mHasPipFeature) {
+ Log.w(TAG_OPS, "ByPass notifySwipeToHomeFinished, FEATURE_PICTURE_IN_PICTURE:"
+ + mHasPipFeature);
return;
}
long token = Binder.clearCallingIdentity();
@@ -424,7 +431,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
@Override
public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
- if (!verifyCaller("setPinnedStackAnimationListener")) {
+ if (!verifyCaller("setPinnedStackAnimationListener") || !mHasPipFeature) {
+ Log.w(TAG_OPS, "ByPass setPinnedStackAnimationListener, FEATURE_PICTURE_IN_PICTURE:"
+ + mHasPipFeature);
return;
}
long token = Binder.clearCallingIdentity();
@@ -456,9 +465,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- if (mOneHandedUI != null) {
- mOneHandedUI.startOneHanded();
- }
+ mOneHandedOptional.ifPresent(oneHanded -> oneHanded.startOneHanded());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -471,9 +478,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- if (mOneHandedUI != null) {
- mOneHandedUI.stopOneHanded();
- }
+ mOneHandedOptional.ifPresent(oneHanded -> oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -612,11 +618,13 @@ public class OverviewProxyService extends CurrentUserTracker implements
NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional,
- Optional<Lazy<StatusBar>> statusBarOptionalLazy, OneHandedUI oneHandedUI,
+ Optional<Lazy<StatusBar>> statusBarOptionalLazy,
+ Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
mPipOptional = pipOptional;
+ mHasPipFeature = mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
mStatusBarOptionalLazy = statusBarOptionalLazy;
mHandler = new Handler();
mNavBarControllerLazy = navBarControllerLazy;
@@ -631,7 +639,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
.supportsRoundedCornersOnWindows(mContext.getResources());
mSysUiState = sysUiState;
mSysUiState.addCallback(this::notifySystemUiStateFlags);
- mOneHandedUI = oneHandedUI;
+ mOneHandedOptional = oneHandedOptional;
// Assumes device always starts with back button until launcher tells it that it does not
mNavBarButtonAlpha = 1.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 0d92d1e198e7..b9b4f42a66e1 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -30,8 +30,8 @@ import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.DividerView;
-import com.android.systemui.stackdivider.SplitScreen;
+import com.android.wm.shell.splitscreen.DividerView;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 2c296353bd14..4b9d5924a8d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -40,6 +40,7 @@ import android.widget.ImageView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.wm.shell.animation.FlingAnimationUtils;
/**
* An ImageView which does not have overlapping renderings commands and therefore does not need a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index c01bdc4c2f28..8bf134d9c5b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_W
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
import android.annotation.MainThread;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
@@ -57,6 +58,7 @@ import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
@@ -233,8 +235,17 @@ public class NotificationMediaManager implements Dumpable {
NotificationVisibility visibility,
boolean removedByUser,
int reason) {
- onNotificationRemoved(entry.getKey());
- mediaDataManager.onNotificationRemoved(entry.getKey());
+ removeEntry(entry);
+ }
+ });
+
+ // Pending entries are never inflated, and will never generate a call to onEntryRemoved().
+ // This can happen when notifications are added and canceled before inflation. Add this
+ // separate listener for cleanup, since media inflation occurs onPendingEntryAdded().
+ notificationEntryManager.addCollectionListener(new NotifCollectionListener() {
+ @Override
+ public void onEntryCleanUp(@NonNull NotificationEntry entry) {
+ removeEntry(entry);
}
});
@@ -247,6 +258,11 @@ public class NotificationMediaManager implements Dumpable {
mPropertiesChangedListener);
}
+ private void removeEntry(NotificationEntry entry) {
+ onNotificationRemoved(entry.getKey());
+ mMediaDataManager.onNotificationRemoved(entry.getKey());
+ }
+
/**
* Check if a state should be considered actively playing
* @param state a PlaybackState
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 8cf8a2299922..01d31039a749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -390,17 +390,21 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
}
private Drawable getIcon(StatusBarIcon icon) {
- return getIcon(getContext(), icon);
+ Context notifContext = mNotification != null ?
+ mNotification.getPackageContext(getContext()) : getContext();
+ return getIcon(getContext(), notifContext, icon);
}
/**
* Returns the right icon to use for this item
*
- * @param context Context to use to get resources
+ * @param sysuiContext Context to use to get scale factor
+ * @param context Context to use to get resources of notification icon
* @return Drawable for this item, or null if the package or item could not
* be found
*/
- public static Drawable getIcon(Context context, StatusBarIcon statusBarIcon) {
+ public static Drawable getIcon(Context sysuiContext,
+ Context context, StatusBarIcon statusBarIcon) {
int userId = statusBarIcon.user.getIdentifier();
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_SYSTEM;
@@ -409,7 +413,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
Drawable icon = statusBarIcon.icon.loadDrawableAsUser(context, userId);
TypedValue typedValue = new TypedValue();
- context.getResources().getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
+ sysuiContext.getResources().getValue(R.dimen.status_bar_icon_scale_factor,
+ typedValue, true);
float scaleFactor = typedValue.getFloat();
// No need to scale the icon, so return it as is.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 838cf0c9a6d0..6f7b32b3ac74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -55,10 +55,10 @@ import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.List;
import java.util.Optional;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 05d9fe757dfd..1d72557c6a89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -145,13 +145,6 @@ public class ExpandableNotificationRowController implements NodeController {
mOnUserInteractionCallback
);
- mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() {
- @Override
- public void onStateChanged(int newState) {
- mView.setOnKeyguard(newState == KEYGUARD);
- }
- });
- mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
mView.setLongPressListener((v, x, y, item) -> {
@@ -172,15 +165,26 @@ public class ExpandableNotificationRowController implements NodeController {
mView.getEntry().setInitializationTime(mClock.elapsedRealtime());
mPluginManager.addPluginListener(mView,
NotificationMenuRowPlugin.class, false /* Allow multiple */);
+ mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD);
+ mStatusBarStateController.addCallback(mStatusBarStateListener);
}
@Override
public void onViewDetachedFromWindow(View v) {
mPluginManager.removePluginListener(mView);
+ mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
});
}
+ private final StatusBarStateController.StateListener mStatusBarStateListener =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onStateChanged(int newState) {
+ mView.setOnKeyguard(newState == KEYGUARD);
+ }
+ };
+
private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
mNotificationLogger.onExpansionChanged(key, userAction, expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index ba9420265849..5dfb22faee7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -29,8 +29,8 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.wm.shell.animation.FlingAnimationUtils;
/**
* A touch handler of the keyguard which is responsible for launching phone and camera affordances.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index f62783502e5b..cd9cc0775c66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -86,7 +86,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -123,6 +122,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.InjectionInflationController;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 0e72506c6d94..6fa99ba41006 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -48,12 +48,12 @@ import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 298672769b56..31c1a5e5a9aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -177,7 +177,6 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
@@ -231,6 +230,7 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 16c3dc460a9c..b7f83145f477 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -46,7 +46,6 @@ import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -99,6 +98,7 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
import java.util.concurrent.Executor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index cf83603997c0..eb2d9bce6c4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -418,6 +418,10 @@ public class MobileSignalController extends SignalController<
return (mServiceState != null && mServiceState.isEmergencyOnly());
}
+ public boolean isInService() {
+ return Utils.isInService(mServiceState);
+ }
+
private boolean isRoaming() {
// During a carrier change, roaming indications need to be supressed.
if (isCarrierNetworkChangeActive()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index b790c92b293c..8722fecdad96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -35,6 +35,7 @@ public interface NetworkController extends CallbackController<SignalCallback>, D
DataUsageController getMobileDataController();
DataSaverController getDataSaverController();
String getMobileDataNetworkName();
+ boolean isMobileDataNetworkInService();
int getNumberSubscriptions();
boolean hasVoiceCallingFeature();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 2253ce7a62a3..62b922e23532 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -460,6 +460,12 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
+ public boolean isMobileDataNetworkInService() {
+ MobileSignalController controller = getDataController();
+ return controller != null && controller.isInService();
+ }
+
+ @Override
public int getNumberSubscriptions() {
return mMobileSignalControllers.size();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index d8cb280bc7e0..0869cf739d02 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -31,13 +31,13 @@ import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.pip.tv.PipController;
import com.android.systemui.pip.tv.PipNotification;
import com.android.systemui.pip.tv.dagger.TvPipComponent;
-import com.android.systemui.stackdivider.SplitScreen;
-import com.android.systemui.stackdivider.SplitScreenController;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index e1e18a22af51..c7a9af3642e5 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -16,26 +16,43 @@
package com.android.systemui.wmshell;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
+import android.view.KeyEvent;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedEvents;
+import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
+import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.tracing.ProtoTraceable;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -48,28 +65,42 @@ import javax.inject.Inject;
* Proxy in SysUiScope to delegate events to controllers in WM Shell library.
*/
@SysUISingleton
-public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTraceProto>,
- CommandQueue.Callbacks {
+public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTraceProto> {
private final CommandQueue mCommandQueue;
private final DisplayImeController mDisplayImeController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final ActivityManagerWrapper mActivityManagerWrapper;
+ private final NavigationModeController mNavigationModeController;
+ private final ScreenLifecycle mScreenLifecycle;
+ private final SysUiState mSysUiState;
private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<OneHanded> mOneHandedOptional;
private final ProtoTracer mProtoTracer;
@Inject
public WMShell(Context context, CommandQueue commandQueue,
KeyguardUpdateMonitor keyguardUpdateMonitor,
+ ActivityManagerWrapper activityManagerWrapper,
DisplayImeController displayImeController,
+ NavigationModeController navigationModeController,
+ ScreenLifecycle screenLifecycle,
+ SysUiState sysUiState,
Optional<Pip> pipOptional,
Optional<SplitScreen> splitScreenOptional,
+ Optional<OneHanded> oneHandedOptional,
ProtoTracer protoTracer) {
super(context);
mCommandQueue = commandQueue;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mActivityManagerWrapper = activityManagerWrapper;
mDisplayImeController = displayImeController;
+ mNavigationModeController = navigationModeController;
+ mScreenLifecycle = screenLifecycle;
+ mSysUiState = sysUiState;
mPipOptional = pipOptional;
mSplitScreenOptional = splitScreenOptional;
+ mOneHandedOptional = oneHandedOptional;
mProtoTracer = protoTracer;
mProtoTracer.add(this);
}
@@ -79,14 +110,14 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
// This is to prevent circular init problem by separating registration step out of its
// constructor. And make sure the initialization of DisplayImeController won't depend on
// specific feature anymore.
- mCommandQueue.addCallback(this);
mDisplayImeController.startMonitorDisplays();
-
mPipOptional.ifPresent(this::initPip);
mSplitScreenOptional.ifPresent(this::initSplitScreen);
+ mOneHandedOptional.ifPresent(this::initOneHanded);
}
- private void initPip(Pip pip) {
+ @VisibleForTesting
+ void initPip(Pip pip) {
mCommandQueue.addCallback(new CommandQueue.Callbacks() {
@Override
public void showPictureInPictureMenu() {
@@ -95,7 +126,8 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
});
}
- private void initSplitScreen(SplitScreen splitScreen) {
+ @VisibleForTesting
+ void initSplitScreen(SplitScreen splitScreen) {
mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
@@ -107,7 +139,7 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
}
});
- ActivityManagerWrapper.getInstance().registerTaskStackListener(
+ mActivityManagerWrapper.registerTaskStackListener(
new TaskStackChangeListener() {
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
@@ -141,6 +173,104 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr
});
}
+ @VisibleForTesting
+ void initOneHanded(OneHanded oneHanded) {
+ if (!oneHanded.hasOneHandedFeature()) {
+ return;
+ }
+
+ int currentMode = mNavigationModeController.addListener(mode ->
+ oneHanded.setThreeButtonModeEnabled(mode == NAV_BAR_MODE_3BUTTON));
+ oneHanded.setThreeButtonModeEnabled(currentMode == NAV_BAR_MODE_3BUTTON);
+
+ oneHanded.registerTransitionCallback(new OneHandedTransitionCallback() {
+ @Override
+ public void onStartFinished(Rect bounds) {
+ mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
+ true).commitUpdate(DEFAULT_DISPLAY);
+ }
+
+ @Override
+ public void onStopFinished(Rect bounds) {
+ mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
+ false).commitUpdate(DEFAULT_DISPLAY);
+ }
+ });
+
+ oneHanded.registerGestureCallback(new OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {
+ if (oneHanded.isOneHandedEnabled()) {
+ oneHanded.startOneHanded();
+ } else if (oneHanded.isSwipeToNotificationEnabled()) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (oneHanded.isOneHandedEnabled()) {
+ oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
+ } else if (oneHanded.isSwipeToNotificationEnabled()) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+ }
+ }
+ });
+
+ mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onKeyguardBouncerChanged(boolean bouncer) {
+ if (bouncer) {
+ oneHanded.stopOneHanded();
+ }
+ }
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ oneHanded.stopOneHanded();
+ }
+ });
+
+ mScreenLifecycle.addObserver(new ScreenLifecycle.Observer() {
+ @Override
+ public void onScreenTurningOff() {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_SCREEN_OFF_OUT);
+ }
+ });
+
+ mCommandQueue.addCallback(new CommandQueue.Callbacks() {
+ @Override
+ public void onCameraLaunchGestureDetected(int source) {
+ oneHanded.stopOneHanded();
+ }
+
+ @Override
+ public void setImeWindowStatus(int displayId, IBinder token, int vis,
+ int backDisposition, boolean showImeSwitcher) {
+ if (displayId != DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) == 0) {
+ return;
+ }
+ oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT);
+ }
+ });
+
+ mActivityManagerWrapper.registerTaskStackListener(
+ new TaskStackChangeListener() {
+ @Override
+ public void onTaskCreated(int taskId, ComponentName componentName) {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
+ }
+
+ @Override
+ public void onTaskMovedToFront(int taskId) {
+ oneHanded.stopOneHanded(
+ OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
+ }
+ });
+ }
+
@Override
public void writeToProto(SystemUiTraceProto proto) {
if (proto.wmShell == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index cdf85fb549ab..adb9186d6705 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -18,22 +18,25 @@ package com.android.systemui.wmshell;
import android.content.Context;
import android.os.Handler;
+import android.util.DisplayMetrics;
import android.view.IWindowManager;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.onehanded.OneHanded;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipUiEventLogger;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.splitscreen.SplitScreen;
import dagger.BindsOptionalOf;
import dagger.Module;
@@ -99,9 +102,19 @@ public abstract class WMShellBaseModule {
return organizer;
}
+ @SysUISingleton
+ @Provides
+ static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
+ DisplayMetrics displayMetrics) {
+ return new FlingAnimationUtils.Builder(displayMetrics);
+ }
+
@BindsOptionalOf
abstract Pip optionalPip();
@BindsOptionalOf
abstract SplitScreen optionalSplitScreen();
+
+ @BindsOptionalOf
+ abstract OneHanded optionalOneHanded();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 1870b7605567..3a249d68d969 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -24,14 +24,14 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedController;
import com.android.systemui.pip.Pip;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSurfaceTransactionHelper;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.pip.PipUiEventLogger;
import com.android.systemui.pip.phone.PipController;
-import com.android.systemui.stackdivider.SplitScreen;
-import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
@@ -40,6 +40,8 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -109,4 +111,10 @@ public class WMShellModule {
pipUiEventLogger, shellTaskOrganizer);
}
+ @SysUISingleton
+ @Provides
+ static OneHanded provideOneHandedController(Context context,
+ DisplayController displayController) {
+ return OneHandedController.create(context, displayController);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 57dbac5bfb10..ad5f987b59e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -52,7 +52,6 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -60,6 +59,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.After;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 389c5a08b7c6..f308e9e479e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -68,7 +68,6 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -77,6 +76,7 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
+import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
index 02d587d90655..e42cf529373e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
@@ -22,21 +22,20 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Display;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -52,8 +51,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedTimeoutHandler mTimeoutHandler;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@@ -64,21 +61,20 @@ public class OneHandedControllerTest extends OneHandedTestCase {
@Mock
OneHandedGestureHandler mMockGestureHandler;
@Mock
- SysUiState mMockSysUiState;
+ OneHandedTimeoutHandler mMockTimeoutHandler;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDisplay = mContext.getDisplay();
- mOneHandedController = new OneHandedController(
- getContext(),
- mCommandQueue,
+ OneHandedController oneHandedController = new OneHandedController(
+ mContext,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
- mMockGestureHandler,
- mMockSysUiState);
+ mMockGestureHandler);
+ mOneHandedController = Mockito.spy(oneHandedController);
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
@@ -97,7 +93,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
@Test
public void testRegisterOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerOrganizer(anyInt());
+ verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerOrganizer(anyInt());
}
@Test
@@ -132,7 +128,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
final boolean enabled = true;
mOneHandedController.setOneHandedEnabled(enabled);
- verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
+ verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
}
@Test
@@ -140,6 +136,44 @@ public class OneHandedControllerTest extends OneHandedTestCase {
final boolean enabled = true;
mOneHandedController.setSwipeToNotificationEnabled(enabled);
- verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
+ verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateTapAppToExit() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.TAPS_APP_TO_EXIT, 1);
+
+ verify(mOneHandedController).setTaskChangeToExit(true);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateEnabled() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
+
+ verify(mOneHandedController).setOneHandedEnabled(true);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateTimeout() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
+ OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+
+ verify(mMockTimeoutHandler).setTimeout(
+ OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
+ }
+
+ @Ignore("b/161980408, fix it after migration finished")
+ @Test
+ public void tesSettingsObserver_updateSwipeToNotification() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
+
+ verify(mOneHandedController).setSwipeToNotificationEnabled(true);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
index 756382a6c630..41af53b1c522 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -16,12 +16,10 @@
package com.android.systemui.onehanded;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
-
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
@@ -29,9 +27,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -50,52 +45,55 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
- @Mock
- NavigationModeController mMockNavigationModeController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = new OneHandedTutorialHandler(mContext);
- mGestureHandler = Mockito.spy(new OneHandedGestureHandler(
- mContext, mMockDisplayController, mMockNavigationModeController));
+ mGestureHandler = Mockito.spy(
+ new OneHandedGestureHandler(mContext, mMockDisplayController));
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
+ mOneHandedController.setThreeButtonModeEnabled(true);
}
@Test
public void testOneHandedManager_registerForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mGestureHandler);
+ verify(mMockDisplayAreaOrganizer, atLeastOnce())
+ .registerTransitionCallback(mGestureHandler);
}
@Test
public void testOneHandedManager_setGestureEventListener() {
- verify(mGestureHandler).setGestureEventListener(any());
-
- assertThat(mGestureHandler.mGestureEventCallback).isNotNull();
+ OneHandedGestureHandler.OneHandedGestureEventCallback callback =
+ new OneHandedGestureHandler.OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {}
+
+ @Override
+ public void onStop() {}
+ };
+ mOneHandedController.registerGestureCallback(callback);
+
+ verify(mGestureHandler).setGestureEventListener(callback);
+ assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback);
}
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// 1st called at init
- verify(mGestureHandler).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
}
@Test
@@ -108,14 +106,14 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
}
@Test
- public void testChangeNavBarTo2Button_shouldDisposeInputChannel() {
+ public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() {
// 1st called at init
- verify(mGestureHandler).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
- verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
+ verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true);
- mGestureHandler.onNavigationModeChanged(NAV_BAR_MODE_2BUTTON);
+ mGestureHandler.onThreeButtonModeEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
index 04ebf25e1b49..f111c4896458 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
@@ -16,8 +16,12 @@
package com.android.systemui.onehanded;
+import static com.android.systemui.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
+import static org.junit.Assume.assumeTrue;
+
+import android.os.SystemProperties;
import android.provider.Settings;
import com.android.systemui.SysuiTestCase;
@@ -54,6 +58,11 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
}
+ @Before
+ public void assumeOneHandedModeSupported() {
+ assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false));
+ }
+
@After
public void restoreSettings() {
Settings.Secure.putInt(getContext().getContentResolver(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
index 3c3ace052e47..1e408313a36e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -19,7 +19,8 @@ package com.android.systemui.onehanded;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import android.testing.AndroidTestingRunner;
@@ -27,9 +28,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -48,31 +46,22 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
- NavigationModeController mMockNavigationModeController;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
- mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
- mMockNavigationModeController);
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
}
@Test
@@ -102,10 +91,10 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
@Test
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
- // 1st called at init
- verify(mTouchHandler).onOneHandedEnabled(true);
+ // Called at init
+ verify(mTouchHandler, atLeastOnce()).onOneHandedEnabled(true);
mOneHandedController.setOneHandedEnabled(true);
- // 2nd called by setOneHandedEnabled()
- verify(mTouchHandler, times(2)).onOneHandedEnabled(true);
+ // Called by setOneHandedEnabled()
+ verify(mTouchHandler, atLeast(2)).onOneHandedEnabled(true);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
index 1bffbf7eb8dd..8ea5524eb7e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -23,9 +23,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -44,32 +41,23 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
OneHandedGestureHandler mGestureHandler;
OneHandedController mOneHandedController;
@Mock
- CommandQueue mCommandQueue;
- @Mock
DisplayController mMockDisplayController;
@Mock
- NavigationModeController mMockNavigationModeController;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
- @Mock
- SysUiState mMockSysUiState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
- mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
- mMockNavigationModeController);
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
mOneHandedController = new OneHandedController(
getContext(),
- mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler,
- mMockSysUiState);
+ mGestureHandler);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
deleted file mode 100644
index ae3df5db30bc..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.onehanded;
-
-import static org.junit.Assume.assumeTrue;
-import static org.mockito.Mockito.verify;
-
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.statusbar.CommandQueue;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OneHandedUITest extends OneHandedTestCase {
- private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
-
- CommandQueue mCommandQueue;
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- OneHandedUI mOneHandedUI;
- ScreenLifecycle mScreenLifecycle;
- @Mock
- OneHandedController mOneHandedController;
- @Mock
- OneHandedTimeoutHandler mMockTimeoutHandler;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mCommandQueue = new CommandQueue(mContext);
- mScreenLifecycle = new ScreenLifecycle();
- mOneHandedUI = new OneHandedUI(mContext,
- mCommandQueue,
- mOneHandedController,
- mScreenLifecycle);
- mOneHandedUI.start();
- mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
- }
-
- @Before
- public void assumeOneHandedModeSupported() {
- assumeTrue(SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false));
- }
-
- @Test
- public void testStartOneHanded() {
- mOneHandedUI.startOneHanded();
-
- verify(mOneHandedController).startOneHanded();
- }
-
- @Test
- public void testStopOneHanded() {
- mOneHandedUI.stopOneHanded();
-
- verify(mOneHandedController).stopOneHanded();
- }
-
- @Test
- public void tesSettingsObserver_updateTapAppToExit() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.TAPS_APP_TO_EXIT, 1);
-
- verify(mOneHandedController).setTaskChangeToExit(true);
- }
-
- @Test
- public void tesSettingsObserver_updateEnabled() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
-
- verify(mOneHandedController).setOneHandedEnabled(true);
- }
-
- @Test
- public void tesSettingsObserver_updateTimeout() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
- OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
-
- verify(mMockTimeoutHandler).setTimeout(
- OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
- }
-
- @Test
- public void tesSettingsObserver_updateSwipeToNotification() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
-
- verify(mOneHandedController).setSwipeToNotificationEnabled(true);
- }
-
- @Ignore("Clarifying do not receive callback")
- @Test
- public void testKeyguardBouncerShowing_shouldStopOneHanded() {
- mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
-
- verify(mOneHandedController).stopOneHanded();
- }
-
- @Test
- public void testScreenTurningOff_shouldStopOneHanded() {
- mScreenLifecycle.dispatchScreenTurningOff();
-
- verify(mOneHandedController).stopOneHanded();
- }
-
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index cf64ff2f8cd6..7ee27c9a8aab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -62,7 +62,6 @@ import com.android.systemui.doze.DozeLog;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -81,6 +80,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.InjectionInflationController;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before;
import org.junit.Test;
@@ -192,8 +192,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
- private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
-
private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 5143596f0214..7d8a62607395 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -96,7 +96,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.stackdivider.SplitScreen;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationListener;
@@ -143,6 +142,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
+import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index d8aa29e9f766..68992179de59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -3,6 +3,8 @@ package com.android.systemui.statusbar.policy;
import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -10,6 +12,7 @@ import static org.mockito.Mockito.when;
import android.net.NetworkCapabilities;
import android.os.Looper;
import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -259,6 +262,25 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
assertDataNetworkNameEquals(newDataName);
}
+ @Test
+ public void testIsDataInService_true() {
+ setupDefaultSignal();
+ assertTrue(mNetworkController.isMobileDataNetworkInService());
+ }
+
+ @Test
+ public void testIsDataInService_noSignal_false() {
+ assertFalse(mNetworkController.isMobileDataNetworkInService());
+ }
+
+ @Test
+ public void testIsDataInService_notInService_false() {
+ setupDefaultSignal();
+ setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ assertFalse(mNetworkController.isMobileDataNetworkInService());
+ }
+
private void testDataActivity(int direction, boolean in, boolean out) {
updateDataActivity(direction);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
index d5ba381bfcac..e7acfae24f30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java
@@ -95,6 +95,11 @@ public class FakeNetworkController extends BaseLeakChecker<SignalCallback>
}
@Override
+ public boolean isMobileDataNetworkInService() {
+ return false;
+ }
+
+ @Override
public int getNumberSubscriptions() {
return 0;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 2f3c86dfc8ae..51cc5f175444 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -16,25 +16,30 @@
package com.android.systemui.wmshell;
-import static org.mockito.Mockito.times;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.Instrumentation;
-import android.content.Context;
import android.test.suitebuilder.annotation.SmallTest;
-import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.onehanded.OneHanded;
+import com.android.systemui.onehanded.OneHandedGestureHandler;
+import com.android.systemui.onehanded.OneHandedTransitionCallback;
import com.android.systemui.pip.Pip;
-import com.android.systemui.pip.tv.PipController;
-import com.android.systemui.stackdivider.SplitScreen;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.tracing.ProtoTracer;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
import org.junit.Test;
@@ -48,29 +53,66 @@ import java.util.Optional;
@RunWith(AndroidJUnit4.class)
public class WMShellTest extends SysuiTestCase {
- Instrumentation mInstrumentation;
WMShell mWMShell;
- @Mock Context mContext;
@Mock CommandQueue mCommandQueue;
@Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock ActivityManagerWrapper mActivityManagerWrapper;
@Mock DisplayImeController mDisplayImeController;
- @Mock Optional<Pip> mPipOptional;
- @Mock Optional<SplitScreen> mSplitScreenOptional;
- @Mock PipController mPipController;
+ @Mock NavigationModeController mNavigationModeController;
+ @Mock ScreenLifecycle mScreenLifecycle;
+ @Mock SysUiState mSysUiState;
+ @Mock Pip mPip;
+ @Mock SplitScreen mSplitScreen;
+ @Mock OneHanded mOneHanded;
@Mock ProtoTracer mProtoTracer;
@Before
- public void setUp() throws Exception {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ public void setUp() {
MockitoAnnotations.initMocks(this);
mWMShell = new WMShell(mContext, mCommandQueue, mKeyguardUpdateMonitor,
- mDisplayImeController, mPipOptional, mSplitScreenOptional, mProtoTracer);
+ mActivityManagerWrapper, mDisplayImeController, mNavigationModeController,
+ mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
+ Optional.of(mOneHanded), mProtoTracer);
+ }
+
+ @Test
+ public void start_startsMonitorDisplays() {
mWMShell.start();
- when(mPipOptional.get()).thenReturn(mPipController);
+
+ verify(mDisplayImeController).startMonitorDisplays();
+ }
+
+ @Test
+ public void initPip_registersCommandQueueCallback() {
+ mWMShell.initPip(mPip);
+
+ verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
}
@Test
- public void testWMShellRegisterCommandQueue() {
- verify(mCommandQueue, times(1)).addCallback(mWMShell);
+ public void initSplitScreen_registersCallbacks() {
+ mWMShell.initSplitScreen(mSplitScreen);
+
+ verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
+ verify(mActivityManagerWrapper).registerTaskStackListener(
+ any(TaskStackChangeListener.class));
+ }
+
+ @Test
+ public void initOneHanded_registersCallbacks() {
+ when(mOneHanded.hasOneHandedFeature()).thenReturn(true);
+ mWMShell.initOneHanded(mOneHanded);
+
+ verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
+ verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class));
+ verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class));
+ verify(mNavigationModeController).addListener(
+ any(NavigationModeController.ModeChangedListener.class));
+ verify(mActivityManagerWrapper).registerTaskStackListener(
+ any(TaskStackChangeListener.class));
+
+ verify(mOneHanded).registerGestureCallback(any(
+ OneHandedGestureHandler.OneHandedGestureEventCallback.class));
+ verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class));
}
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index b09b2605a791..500e768372f5 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -126,6 +126,16 @@ public class DynamicSystemService extends IDynamicSystemService.Stub {
}
@Override
+ public boolean closePartition() throws RemoteException {
+ IGsiService service = getGsiService();
+ if (service.closePartition() != 0) {
+ Slog.i(TAG, "Partition installation completes with error");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
public boolean finishInstallation() throws RemoteException {
IGsiService service = getGsiService();
if (service.closeInstall() != 0) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index eb8308b56f2e..e433fbd94d4f 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -64,6 +64,7 @@ import android.telephony.DisconnectCause;
import android.telephony.LocationAccessPolicy;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.PreciseDisconnectCause;
@@ -142,13 +143,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int callerUid;
int callerPid;
- int events;
+ long events;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
- boolean matchPhoneStateListenerEvent(int events) {
+ boolean matchPhoneStateListenerEvent(long events) {
return (callback != null) && ((events & this.events) != 0);
}
@@ -177,7 +178,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
- + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}";
+ + " phoneId=" + phoneId + " events=" + Long.toHexString(events) + "}";
}
}
@@ -306,6 +307,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private final LocalLog mListenLog = new LocalLog(00);
+ private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
+
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
* type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -318,19 +321,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// Starting in Q, almost all cellular location requires FINE location enforcement.
// Prior to Q, cellular was available with COARSE location enforcement. Bits in this
// list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later.
- static final int ENFORCE_LOCATION_PERMISSION_MASK =
+ static final long ENFORCE_LOCATION_PERMISSION_MASK =
PhoneStateListener.LISTEN_CELL_LOCATION
| PhoneStateListener.LISTEN_CELL_INFO
| PhoneStateListener.LISTEN_REGISTRATION_FAILURE
| PhoneStateListener.LISTEN_BARRING_INFO;
- static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
+ static final long ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
| PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
| PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED;
- static final int ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK =
+ static final long ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_PRECISE_CALL_STATE
| PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
@@ -339,11 +342,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
| PhoneStateListener.LISTEN_REGISTRATION_FAILURE
| PhoneStateListener.LISTEN_BARRING_INFO;
- static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
+ static final long READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
| PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS;
- static final int READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK =
+ static final long READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT
| PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED
| PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED
@@ -495,6 +498,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mImsReasonInfo, mNumPhones);
cutListToSize(mPreciseDataConnectionStates, mNumPhones);
cutListToSize(mBarringInfo, mNumPhones);
+ cutListToSize(mPhysicalChannelConfigs, mNumPhones);
return;
}
@@ -528,6 +532,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
+ PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
}
}
@@ -588,6 +594,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
mBarringInfo = new ArrayList<>();
mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones];
+ mPhysicalChannelConfigs = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -617,6 +624,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
+ PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -795,23 +804,23 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override
public void listenWithFeature(String callingPackage, String callingFeatureId,
- IPhoneStateListener callback, int events, boolean notifyNow) {
+ IPhoneStateListener callback, long events, boolean notifyNow) {
listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
callingFeatureId, callback, events, notifyNow);
}
@Override
public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
- IPhoneStateListener callback, int events, boolean notifyNow) {
+ IPhoneStateListener callback, long events, boolean notifyNow) {
listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
}
private void listen(String callingPackage, @Nullable String callingFeatureId,
- IPhoneStateListener callback, int events, boolean notifyNow, int subId) {
+ IPhoneStateListener callback, long events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid()
- + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId="
+ + " events=0x" + Long.toHexString(events) + " notifyNow=" + notifyNow + " subId="
+ subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId;
mListenLog.log(str);
if (VDBG) {
@@ -1098,6 +1107,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
+ if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
+ try {
+ r.callback.onPhysicalChannelConfigurationChanged(
+ mPhysicalChannelConfigs);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
} else {
@@ -2258,6 +2275,47 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /**
+ * Send a notification to registrants that the configs of physical channel has changed for
+ * a particular subscription.
+ *
+ * @param subId the subId
+ * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
+ */
+ public void notifyPhysicalChannelConfigurationForSubscriber(
+ int subId, List<PhysicalChannelConfig> configs) {
+ if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
+ return;
+ }
+
+ if (VDBG) {
+ log("notifyPhysicalChannelConfiguration: subId=" + subId + " configs=" + configs);
+ }
+
+ synchronized (mRecords) {
+ int phoneId = SubscriptionManager.getPhoneId(subId);
+ if (validatePhoneId(phoneId)) {
+ mPhysicalChannelConfigs.set(phoneId, configs.get(phoneId));
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ if (DBG_LOC) {
+ log("notifyPhysicalChannelConfiguration: "
+ + "mPhysicalChannelConfigs="
+ + configs + " r=" + r);
+ }
+ r.callback.onPhysicalChannelConfigurationChanged(configs);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -2310,6 +2368,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
pw.println("mDefaultSubId=" + mDefaultSubId);
+ pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs);
pw.decreaseIndent();
@@ -2536,7 +2595,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(int events, int subId, String callingPackage,
+ private boolean checkListenerPermission(long events, int subId, String callingPackage,
@Nullable String callingFeatureId, String message) {
LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
@@ -2742,7 +2801,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
private void checkPossibleMissNotify(Record r, int phoneId) {
- int events = r.events;
+ long events = r.events;
if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
try {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index cd3e21052efb..87898d80bd46 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1528,15 +1528,18 @@ public final class ProcessList {
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
&& proc.lastCachedPss >= 4000) {
// Turn this condition on to cause killing to happen regularly, for testing.
- if (proc.baseProcessTracker != null) {
- proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss);
- for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
- ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
- FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
- proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
- proc.lastCachedPss, holder.appVersion);
+ synchronized (mService.mProcessStats.mLock) {
+ if (proc.baseProcessTracker != null) {
+ proc.baseProcessTracker.reportCachedKill(
+ proc.pkgList.mPkgList, proc.lastCachedPss);
+ for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+ ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+ FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
+ proc.info.uid,
+ holder.state.getName(),
+ holder.state.getPackage(),
+ proc.lastCachedPss, holder.appVersion);
+ }
}
}
proc.kill(Long.toString(proc.lastCachedPss) + "k from cached",
@@ -1549,16 +1552,18 @@ public final class ProcessList {
if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc
.lastCachedPss);
if (proc.lastCachedPss >= getCachedRestoreThresholdKb()) {
- if (proc.baseProcessTracker != null) {
- proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList,
- proc.lastCachedPss);
- for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
- ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
- FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
- proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
- proc.lastCachedPss, holder.appVersion);
+ synchronized (mService.mProcessStats.mLock) {
+ if (proc.baseProcessTracker != null) {
+ proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList,
+ proc.lastCachedPss);
+ for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
+ ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
+ FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED,
+ proc.info.uid,
+ holder.state.getName(),
+ holder.state.getPackage(),
+ proc.lastCachedPss, holder.appVersion);
+ }
}
}
proc.kill(Long.toString(proc.lastCachedPss) + "k from cached",
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 5447605a36d1..1615998f7787 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -28,6 +28,7 @@ import android.media.AudioDeviceAttributes;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
+import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.MediaMetrics;
import android.os.Binder;
@@ -546,6 +547,25 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher);
}
+ /*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return mDeviceInventory.setPreferredDevicesForCapturePresetSync(capturePreset, devices);
+ }
+
+ /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
+ return mDeviceInventory.clearPreferredDevicesForCapturePresetSync(capturePreset);
+ }
+
+ /*package*/ void registerCapturePresetDevicesRoleDispatcher(
+ @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
+ mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher);
+ }
+
+ /*package*/ void unregisterCapturePresetDevicesRoleDispatcher(
+ @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
+ mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
+ }
+
//---------------------------------------------------------------------
// Communication with (to) AudioService
//TODO check whether the AudioService methods are candidates to move here
@@ -694,6 +714,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy);
}
+ /*package*/ void postSaveSetPreferredDevicesForCapturePreset(
+ int capturePreset, List<AudioDeviceAttributes> devices) {
+ sendILMsgNoDelay(
+ MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices);
+ }
+
+ /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
+ sendIMsgNoDelay(
+ MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset);
+ }
+
//---------------------------------------------------------------------
// Method forwarding between the helper classes (BtHelper, AudioDeviceInventory)
// only call from a "handle"* method or "on"* method
@@ -1098,6 +1129,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_CHECK_MUTE_MUSIC:
checkMessagesMuteMusic(0);
break;
+ case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: {
+ final int capturePreset = msg.arg1;
+ final List<AudioDeviceAttributes> devices =
+ (List<AudioDeviceAttributes>) msg.obj;
+ mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset(
+ capturePreset, devices);
+ } break;
+ case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: {
+ final int capturePreset = msg.arg1;
+ mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
+ } break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1174,6 +1216,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_CHECK_MUTE_MUSIC = 36;
private static final int MSG_REPORT_NEW_ROUTES_A2DP = 37;
+ private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
+ private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 39;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index fbf07cc591ff..33a8a30243de 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -31,6 +31,7 @@ import android.media.AudioPort;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
+import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.MediaMetrics;
import android.os.Binder;
@@ -140,6 +141,10 @@ public class AudioDeviceInventory {
private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevices =
new ArrayMap<>();
+ // List of preferred devices of capture preset
+ private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevicesForCapturePreset =
+ new ArrayMap<>();
+
// the wrapper for AudioSystem static methods, allows us to spy AudioSystem
private final @NonNull AudioSystemAdapter mAudioSystem;
@@ -154,6 +159,10 @@ public class AudioDeviceInventory {
final RemoteCallbackList<IStrategyPreferredDevicesDispatcher> mPrefDevDispatchers =
new RemoteCallbackList<IStrategyPreferredDevicesDispatcher>();
+ // Monitoring of devices for role and capture preset
+ final RemoteCallbackList<ICapturePresetDevicesRoleDispatcher> mDevRoleCapturePresetDispatchers =
+ new RemoteCallbackList<ICapturePresetDevicesRoleDispatcher>();
+
/*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
mDeviceBroker = broker;
mAudioSystem = AudioSystemAdapter.getDefaultAdapter();
@@ -243,6 +252,9 @@ public class AudioDeviceInventory {
pw.println(" " + prefix + " type:0x" + Integer.toHexString(keyType)
+ " (" + AudioSystem.getDeviceName(keyType)
+ ") addr:" + valueAddress); });
+ mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
+ pw.println(" " + prefix + "capturePreset:" + capturePreset
+ + " devices:" + devices); });
}
//------------------------------------------------------------
@@ -270,6 +282,9 @@ public class AudioDeviceInventory {
mAudioSystem.setDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices); });
}
+ synchronized (mPreferredDevicesForCapturePreset) {
+ // TODO: call audiosystem to restore
+ }
}
// only public for mocking/spying
@@ -613,6 +628,20 @@ public class AudioDeviceInventory {
dispatchPreferredDevice(strategy, new ArrayList<AudioDeviceAttributes>());
}
+ /*package*/ void onSaveSetPreferredDevicesForCapturePreset(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
+ mPreferredDevicesForCapturePreset.put(capturePreset, devices);
+ dispatchDevicesRoleForCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ }
+
+ /*package*/ void onSaveClearPreferredDevicesForCapturePreset(int capturePreset) {
+ mPreferredDevicesForCapturePreset.remove(capturePreset);
+ dispatchDevicesRoleForCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED,
+ new ArrayList<AudioDeviceAttributes>());
+ }
+
//------------------------------------------------------------
//
@@ -651,6 +680,41 @@ public class AudioDeviceInventory {
mPrefDevDispatchers.unregister(dispatcher);
}
+ /*package*/ int setPreferredDevicesForCapturePresetSync(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
+ final long identity = Binder.clearCallingIdentity();
+ final int status = mAudioSystem.setDevicesRoleForCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ Binder.restoreCallingIdentity(identity);
+
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ }
+ return status;
+ }
+
+ /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
+ final long identity = Binder.clearCallingIdentity();
+ final int status = mAudioSystem.clearDevicesRoleForCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED);
+ Binder.restoreCallingIdentity(identity);
+
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
+ }
+ return status;
+ }
+
+ /*package*/ void registerCapturePresetDevicesRoleDispatcher(
+ @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
+ mDevRoleCapturePresetDispatchers.register(dispatcher);
+ }
+
+ /*package*/ void unregisterCapturePresetDevicesRoleDispatcher(
+ @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
+ mDevRoleCapturePresetDispatchers.unregister(dispatcher);
+ }
+
/**
* Implements the communication with AudioSystem to (dis)connect a device in the native layers
* @param connect true if connection
@@ -1306,6 +1370,19 @@ public class AudioDeviceInventory {
mPrefDevDispatchers.finishBroadcast();
}
+ private void dispatchDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ final int nbDispatchers = mDevRoleCapturePresetDispatchers.beginBroadcast();
+ for (int i = 0; i < nbDispatchers; ++i) {
+ try {
+ mDevRoleCapturePresetDispatchers.getBroadcastItem(i).dispatchDevicesRoleChanged(
+ capturePreset, role, devices);
+ } catch (RemoteException e) {
+ }
+ }
+ mDevRoleCapturePresetDispatchers.finishBroadcast();
+ }
+
//----------------------------------------------------------
// For tests only
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4378490d19c5..5f6491093453 100755..100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -84,6 +84,7 @@ import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
import android.media.IAudioServerStateDispatcher;
import android.media.IAudioService;
+import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.IPlaybackConfigDispatcher;
import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
@@ -1987,6 +1988,94 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.unregisterStrategyPreferredDevicesDispatcher(dispatcher);
}
+ /**
+ * @see AudioManager#setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)
+ */
+ public int setPreferredDevicesForCapturePreset(
+ int capturePreset, List<AudioDeviceAttributes> devices) {
+ if (devices == null) {
+ return AudioSystem.ERROR;
+ }
+ enforceModifyAudioRoutingPermission();
+ final String logString = String.format(
+ "setPreferredDevicesForCapturePreset u/pid:%d/%d source:%d dev:%s",
+ Binder.getCallingUid(), Binder.getCallingPid(), capturePreset,
+ devices.stream().map(e -> e.toString()).collect(Collectors.joining(",")));
+ sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG));
+ if (devices.stream().anyMatch(device ->
+ device.getRole() == AudioDeviceAttributes.ROLE_OUTPUT)) {
+ Log.e(TAG, "Unsupported output routing in " + logString);
+ return AudioSystem.ERROR;
+ }
+
+ final int status = mDeviceBroker.setPreferredDevicesForCapturePresetSync(
+ capturePreset, devices);
+ if (status != AudioSystem.SUCCESS) {
+ Log.e(TAG, String.format("Error %d in %s)", status, logString));
+ }
+
+ return status;
+ }
+
+ /** @see AudioManager#clearPreferredDevicesForCapturePreset(int) */
+ public int clearPreferredDevicesForCapturePreset(int capturePreset) {
+ enforceModifyAudioRoutingPermission();
+ final String logString = String.format(
+ "removePreferredDeviceForCapturePreset source:%d", capturePreset);
+ sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG));
+
+ final int status = mDeviceBroker.clearPreferredDevicesForCapturePresetSync(capturePreset);
+ if (status != AudioSystem.SUCCESS) {
+ Log.e(TAG, String.format("Error %d in %s", status, logString));
+ }
+ return status;
+ }
+
+ /**
+ * @see AudioManager#getPreferredDevicesForCapturePreset(int)
+ */
+ public List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int capturePreset) {
+ enforceModifyAudioRoutingPermission();
+ List<AudioDeviceAttributes> devices = new ArrayList<>();
+ final long identity = Binder.clearCallingIdentity();
+ final int status = AudioSystem.getDevicesForRoleAndCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ Binder.restoreCallingIdentity(identity);
+ if (status != AudioSystem.SUCCESS) {
+ Log.e(TAG, String.format("Error %d in getPreferredDeviceForCapturePreset(%d)",
+ status, capturePreset));
+ return new ArrayList<AudioDeviceAttributes>();
+ } else {
+ return devices;
+ }
+ }
+
+ /**
+ * @see AudioManager#addOnPreferredDevicesForCapturePresetChangedListener(
+ * Executor, OnPreferredDevicesForCapturePresetChangedListener)
+ */
+ public void registerCapturePresetDevicesRoleDispatcher(
+ @Nullable ICapturePresetDevicesRoleDispatcher dispatcher) {
+ if (dispatcher == null) {
+ return;
+ }
+ enforceModifyAudioRoutingPermission();
+ mDeviceBroker.registerCapturePresetDevicesRoleDispatcher(dispatcher);
+ }
+
+ /**
+ * @see AudioManager#removeOnPreferredDevicesForCapturePresetChangedListener(
+ * AudioManager.OnPreferredDevicesForCapturePresetChangedListener)
+ */
+ public void unregisterCapturePresetDevicesRoleDispatcher(
+ @Nullable ICapturePresetDevicesRoleDispatcher dispatcher) {
+ if (dispatcher == null) {
+ return;
+ }
+ enforceModifyAudioRoutingPermission();
+ mDeviceBroker.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
+ }
+
/** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
@NonNull AudioAttributes attributes) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index a0e1ca78a5e7..ae64990fd8d0 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -101,6 +101,40 @@ public class AudioSystemAdapter {
}
/**
+ * Same as (@link AudioSystem#setDevicesRoleForCapturePreset(int, List))
+ * @param capturePreset
+ * @param role
+ * @param devices
+ * @return
+ */
+ public int setDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return AudioSystem.setDevicesRoleForCapturePreset(capturePreset, role, devices);
+ }
+
+ /**
+ * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int)}
+ * @param capturePreset
+ * @param role
+ * @param devicesToRemove
+ * @return
+ */
+ public int removeDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devicesToRemove) {
+ return AudioSystem.removeDevicesRoleForCapturePreset(capturePreset, role, devicesToRemove);
+ }
+
+ /**
+ * Same as {@link AudioSystem#}
+ * @param capturePreset
+ * @param role
+ * @return
+ */
+ public int clearDevicesRoleForCapturePreset(int capturePreset, int role) {
+ return AudioSystem.clearDevicesRoleForCapturePreset(capturePreset, role);
+ }
+
+ /**
* Same as {@link AudioSystem#setParameters(String)}
* @param keyValuePairs
* @return
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index bbc29b0bf89b..bbc29b0bf89b 100755..100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index d9c62df3f3ea..c134a3faca4f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -25,12 +25,14 @@ import android.app.UserSwitchObserver;
import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.IFaceServiceReceiver;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -109,6 +111,9 @@ class Face10 implements IHwBinder.DeathRecipient {
@Override
public void onUserSwitching(int newUserId) {
scheduleInternalCleanup(newUserId);
+ scheduleGetFeature(new Binder(), newUserId,
+ BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
+ null, mContext.getOpPackageName());
}
};
@@ -360,6 +365,9 @@ class Face10 implements IHwBinder.DeathRecipient {
if (halId != 0) {
scheduleLoadAuthenticatorIds();
scheduleInternalCleanup(ActivityManager.getCurrentUser());
+ scheduleGetFeature(new Binder(), ActivityManager.getCurrentUser(),
+ BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
+ null, mContext.getOpPackageName());
} else {
Slog.e(TAG, "Unable to set callback");
mDaemon = null;
@@ -450,7 +458,7 @@ class Face10 implements IHwBinder.DeathRecipient {
}
void scheduleGetFeature(@NonNull IBinder token, int userId, int feature,
- @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
+ @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
mHandler.post(() -> {
final List<Face> faces = getEnrolledFaces(userId);
if (faces.isEmpty()) {
@@ -461,10 +469,22 @@ class Face10 implements IHwBinder.DeathRecipient {
scheduleUpdateActiveUserWithoutHandler(userId);
final int faceId = faces.get(0).getBiometricId();
- final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext,
- mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
- opPackageName, mSensorId, feature, faceId);
- mScheduler.scheduleClientMonitor(client);
+ final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
+ token, listener, userId, opPackageName, mSensorId, feature, faceId);
+ mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ @Override
+ public void onClientFinished(
+ @NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
+ final int settingsValue = client.getValue() ? 1 : 0;
+ Slog.d(TAG, "Updating attention value for user: " + userId
+ + " to value: " + settingsValue);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ settingsValue, userId);
+ }
+ }
+ });
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java
index 8c7b99d6eb52..33b2b6ada24c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java
@@ -17,6 +17,7 @@
package com.android.server.biometrics.sensors.face;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
@@ -39,9 +40,10 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
private final int mFeature;
private final int mFaceId;
+ private boolean mValue;
FaceGetFeatureClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFace> lazyDaemon,
- @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int sensorId, int feature, int faceId) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
@@ -54,7 +56,9 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
@Override
public void unableToStart() {
try {
- getListener().onFeatureGet(false /* success */, mFeature, false /* value */);
+ if (getListener() != null) {
+ getListener().onFeatureGet(false /* success */, mFeature, false /* value */);
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send error", e);
}
@@ -70,11 +74,18 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
protected void startHalOperation() {
try {
final OptionalBool result = getFreshDaemon().getFeature(mFeature, mFaceId);
- getListener().onFeatureGet(result.status == Status.OK, mFeature, result.value);
+ mValue = result.value;
+ if (getListener() != null) {
+ getListener().onFeatureGet(result.status == Status.OK, mFeature, mValue);
+ }
mCallback.onClientFinished(this, true /* success */);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to getFeature", e);
mCallback.onClientFinished(this, false /* success */);
}
}
+
+ boolean getValue() {
+ return mValue;
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index b689106bbc44..c6664f4d96ff 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -25,9 +25,9 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceSensorProperties;
import android.hardware.face.IFaceService;
import android.hardware.face.IFaceServiceReceiver;
-import android.hardware.face.FaceSensorProperties;
import android.os.Binder;
import android.os.IBinder;
import android.os.NativeHandle;
@@ -303,7 +303,8 @@ public class FaceService extends SystemService {
public void getFeature(final IBinder token, int userId, int feature,
IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- mFace10.scheduleGetFeature(token, userId, feature, receiver, opPackageName);
+ mFace10.scheduleGetFeature(token, userId, feature,
+ new ClientMonitorCallbackConverter(receiver), opPackageName);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 2c632d96e738..4a12ee71adbe 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -83,6 +83,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
@@ -283,6 +284,7 @@ public final class DisplayManagerService extends SystemService {
// Temporary display info, used for comparing display configurations.
private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
+ private final DisplayInfo mTempNonOverrideDisplayInfo = new DisplayInfo();
// Temporary viewports, used when sending new viewport information to the
// input system. May be used outside of the lock but only on the handler thread.
@@ -507,7 +509,8 @@ public final class DisplayManagerService extends SystemService {
mDisplayTransactionListeners.remove(listener);
}
- private void setDisplayInfoOverrideFromWindowManagerInternal(
+ @VisibleForTesting
+ void setDisplayInfoOverrideFromWindowManagerInternal(
int displayId, DisplayInfo info) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
@@ -935,7 +938,8 @@ public final class DisplayManagerService extends SystemService {
adapter.registerLocked();
}
- private void handleDisplayDeviceAdded(DisplayDevice device) {
+ @VisibleForTesting
+ void handleDisplayDeviceAdded(DisplayDevice device) {
synchronized (mSyncRoot) {
handleDisplayDeviceAddedLocked(device);
}
@@ -947,7 +951,6 @@ public final class DisplayManagerService extends SystemService {
Slog.w(TAG, "Attempted to add already added display device: " + info);
return;
}
-
Slog.i(TAG, "Display device added: " + info);
device.mDebugLastLoggedDeviceInfo = info;
@@ -960,7 +963,8 @@ public final class DisplayManagerService extends SystemService {
scheduleTraversalLocked(false);
}
- private void handleDisplayDeviceChanged(DisplayDevice device) {
+ @VisibleForTesting
+ void handleDisplayDeviceChanged(DisplayDevice device) {
synchronized (mSyncRoot) {
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if (!mDisplayDevices.contains(device)) {
@@ -1234,6 +1238,7 @@ public final class DisplayManagerService extends SystemService {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
+ display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);
display.updateLocked(mDisplayDevices);
if (!display.isValidLocked()) {
mLogicalDisplays.removeAt(i);
@@ -1242,6 +1247,15 @@ public final class DisplayManagerService extends SystemService {
} else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
handleLogicalDisplayChanged(displayId, display);
changed = true;
+ } else {
+ // While applications shouldn't know nor care about the non-overridden info, we
+ // still need to let WindowManager know so it can update its own internal state for
+ // things like display cutouts.
+ display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo);
+ if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) {
+ handleLogicalDisplayChanged(displayId, display);
+ changed = true;
+ }
}
}
return changed;
@@ -2176,6 +2190,8 @@ public final class DisplayManagerService extends SystemService {
if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+ EventLog.writeEvent(0x534e4554, "162627132", callingUid,
+ "Attempt to create a trusted display without holding permission!");
throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ "create a trusted virtual display.");
}
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceAction.java b/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
index c90f297e1485..179602737985 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
@@ -51,7 +51,7 @@ public class ActiveSourceAction extends HdmiCecFeatureAction {
Constants.MENU_STATE_ACTIVATED));
}
- source().setActiveSource(logicalAddress, physicalAddress);
+ source().setActiveSource(logicalAddress, physicalAddress, "ActiveSourceAction");
mState = STATE_FINISHED;
finish();
return true;
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 01547c16e9b5..8405bbe38b12 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -17,9 +17,9 @@
package com.android.server.hdmi;
import android.annotation.Nullable;
-import android.hardware.hdmi.IHdmiControlCallback;
-import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.IHdmiControlCallback;
import android.os.RemoteException;
import android.util.Slog;
@@ -69,7 +69,7 @@ final class ActiveSourceHandler {
if (!tv.isProhibitMode()) {
ActiveSource old = ActiveSource.of(tv.getActiveSource());
- tv.updateActiveSource(newActive);
+ tv.updateActiveSource(newActive, "ActiveSourceHandler");
boolean notifyInputChange = (mCallback == null);
if (!old.equals(newActive)) {
tv.setPrevPortId(tv.getActivePortId());
@@ -85,7 +85,7 @@ final class ActiveSourceHandler {
HdmiCecMessage activeSourceCommand = HdmiCecMessageBuilder.buildActiveSource(
current.logicalAddress, current.physicalAddress);
mService.sendCecCommand(activeSourceCommand);
- tv.updateActiveSource(current);
+ tv.updateActiveSource(current, "ActiveSourceHandler");
invokeCallback(HdmiControlManager.RESULT_SUCCESS);
} else {
tv.startRoutingControl(newActive.physicalAddress, current.physicalAddress, true,
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 66652ca26e54..7b52ddef29bc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -688,16 +688,24 @@ final class HdmiCecController {
}
void dump(final IndentingPrintWriter pw) {
+ final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
for (int i = 0; i < mLocalDevices.size(); ++i) {
pw.println("HdmiCecLocalDevice #" + mLocalDevices.keyAt(i) + ":");
pw.increaseIndent();
mLocalDevices.valueAt(i).dump(pw);
+
+ pw.println("Active Source history:");
+ pw.increaseIndent();
+ for (Dumpable activeSourceEvent : mLocalDevices.valueAt(i).getActiveSourceHistory()) {
+ activeSourceEvent.dump(pw, sdf);
+ }
+ pw.decreaseIndent();
pw.decreaseIndent();
}
pw.println("CEC message history:");
pw.increaseIndent();
- final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (Dumpable record : mMessageHistory) {
record.dump(pw, sdf);
}
@@ -917,7 +925,7 @@ final class HdmiCecController {
}
}
- private abstract static class Dumpable {
+ public abstract static class Dumpable {
protected final long mTime;
Dumpable() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 86e6a3220507..b88a37e7b8b4 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -38,10 +38,13 @@ import com.android.server.hdmi.Constants.LocalActivePort;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
/**
* Class that models a logical CEC device hosted in this system. Handles initialization, CEC
@@ -50,6 +53,7 @@ import java.util.List;
abstract class HdmiCecLocalDevice {
private static final String TAG = "HdmiCecLocalDevice";
+ private static final int MAX_HDMI_ACTIVE_SOURCE_HISTORY = 10;
private static final int MSG_DISABLE_DEVICE_TIMEOUT = 1;
private static final int MSG_USER_CONTROL_RELEASE_TIMEOUT = 2;
// Timeout in millisecond for device clean up (5s).
@@ -68,6 +72,10 @@ abstract class HdmiCecLocalDevice {
protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
protected int mLastKeyRepeatCount = 0;
+ // Stores recent changes to the active source in the CEC network.
+ private final ArrayBlockingQueue<HdmiCecController.Dumpable> mActiveSourceHistory =
+ new ArrayBlockingQueue<>(MAX_HDMI_ACTIVE_SOURCE_HISTORY);
+
static class ActiveSource {
int logicalAddress;
int physicalAddress;
@@ -893,16 +901,16 @@ abstract class HdmiCecLocalDevice {
return mService.getLocalActiveSource();
}
- void setActiveSource(ActiveSource newActive) {
- setActiveSource(newActive.logicalAddress, newActive.physicalAddress);
+ void setActiveSource(ActiveSource newActive, String caller) {
+ setActiveSource(newActive.logicalAddress, newActive.physicalAddress, caller);
}
- void setActiveSource(HdmiDeviceInfo info) {
- setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress());
+ void setActiveSource(HdmiDeviceInfo info, String caller) {
+ setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress(), caller);
}
- void setActiveSource(int logicalAddress, int physicalAddress) {
- mService.setActiveSource(logicalAddress, physicalAddress);
+ void setActiveSource(int logicalAddress, int physicalAddress, String caller) {
+ mService.setActiveSource(logicalAddress, physicalAddress, caller);
mService.setLastInputForMhl(Constants.INVALID_PORT_ID);
}
@@ -1120,6 +1128,20 @@ abstract class HdmiCecLocalDevice {
HdmiCecMessageBuilder.buildUserControlReleased(mAddress, targetAddress));
}
+ void addActiveSourceHistoryItem(ActiveSource activeSource, boolean isActiveSource,
+ String caller) {
+ ActiveSourceHistoryRecord record = new ActiveSourceHistoryRecord(activeSource,
+ isActiveSource, caller);
+ if (!mActiveSourceHistory.offer(record)) {
+ mActiveSourceHistory.poll();
+ mActiveSourceHistory.offer(record);
+ }
+ }
+
+ public ArrayBlockingQueue<HdmiCecController.Dumpable> getActiveSourceHistory() {
+ return this.mActiveSourceHistory;
+ }
+
/** Dump internal status of HdmiCecLocalDevice object. */
protected void dump(final IndentingPrintWriter pw) {
pw.println("mDeviceType: " + mDeviceType);
@@ -1152,4 +1174,29 @@ abstract class HdmiCecLocalDevice {
}
return finalMask | myPhysicalAddress;
}
+
+ private static final class ActiveSourceHistoryRecord extends HdmiCecController.Dumpable {
+ private final ActiveSource mActiveSource;
+ private final boolean mIsActiveSource;
+ private final String mCaller;
+
+ private ActiveSourceHistoryRecord(ActiveSource mActiveSource, boolean mIsActiveSource,
+ String caller) {
+ this.mActiveSource = mActiveSource;
+ this.mIsActiveSource = mIsActiveSource;
+ this.mCaller = caller;
+ }
+
+ @Override
+ void dump(final IndentingPrintWriter pw, SimpleDateFormat sdf) {
+ pw.print("time=");
+ pw.print(sdf.format(new Date(mTime)));
+ pw.print(" active source=");
+ pw.print(mActiveSource);
+ pw.print(" isActiveSource=");
+ pw.print(mIsActiveSource);
+ pw.print(" from=");
+ pw.println(mCaller);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index af815973d3c3..68473c1830ae 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -361,7 +361,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
assertRunOnServiceThread();
// Invalidate the internal active source record when goes to standby
// This set will also update mIsActiveSource
- mService.setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS);
+ mService.setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS,
+ "HdmiCecLocalDeviceAudioSystem#onStandby()");
mTvSystemAudioModeSupport = null;
// Record the last state of System Audio Control before going to standby
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index d675b81629a4..f2f6dbe9bde5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -190,7 +190,8 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
boolean wasActiveSource = mIsActiveSource;
// Invalidate the internal active source record when goes to standby
// This set will also update mIsActiveSource
- mService.setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS);
+ mService.setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS,
+ "HdmiCecLocalDevicePlayback#onStandby()");
if (initiatedByCec || !mAutoTvOff || !wasActiveSource) {
return;
}
@@ -399,7 +400,8 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
assertRunOnServiceThread();
if (physicalAddress != mService.getPhysicalAddress()) {
- setActiveSource(physicalAddress);
+ setActiveSource(physicalAddress,
+ "HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()");
return;
}
switch (mPlaybackDeviceActionOnRoutingControl) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 44ad8eea65ca..4ff36c4b65db 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -119,11 +119,11 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
}
@ServiceThreadOnly
- protected void setActiveSource(int physicalAddress) {
+ protected void setActiveSource(int physicalAddress, String caller) {
assertRunOnServiceThread();
// Invalidate the internal active source record. This will also update mIsActiveSource.
ActiveSource activeSource = ActiveSource.of(Constants.ADDR_INVALID, physicalAddress);
- setActiveSource(activeSource);
+ setActiveSource(activeSource, caller);
}
@ServiceThreadOnly
@@ -133,7 +133,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
if (!getActiveSource().equals(activeSource)) {
- setActiveSource(activeSource);
+ setActiveSource(activeSource, "HdmiCecLocalDeviceSource#handleActiveSource()");
}
setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
updateDevicePowerStatus(logicalAddress, HdmiControlManager.POWER_STATUS_ON);
@@ -162,7 +162,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
setAndBroadcastActiveSource(message, physicalAddress);
}
if (physicalAddress != mService.getPhysicalAddress()) {
- setActiveSource(physicalAddress);
+ setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleSetStreamPath()");
}
switchInputOnReceivingNewActivePath(physicalAddress);
return true;
@@ -174,7 +174,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
assertRunOnServiceThread();
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams(), 2);
if (physicalAddress != mService.getPhysicalAddress()) {
- setActiveSource(physicalAddress);
+ setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleRoutingChange()");
}
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
@@ -196,7 +196,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
assertRunOnServiceThread();
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
if (physicalAddress != mService.getPhysicalAddress()) {
- setActiveSource(physicalAddress);
+ setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleRoutingInformation()");
}
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 804cc92cca08..0325ad929849 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -288,13 +288,14 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
if (targetAddress == Constants.ADDR_INTERNAL) {
handleSelectInternalSource();
// Switching to internal source is always successful even when CEC control is disabled.
- setActiveSource(targetAddress, mService.getPhysicalAddress());
+ setActiveSource(targetAddress, mService.getPhysicalAddress(),
+ "HdmiCecLocalDeviceTv#deviceSelect()");
setActivePath(mService.getPhysicalAddress());
invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
return;
}
if (!mService.isControlEnabled()) {
- setActiveSource(targetDevice);
+ setActiveSource(targetDevice, "HdmiCecLocalDeviceTv#deviceSelect()");
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
@@ -307,7 +308,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
// Seq #18
if (mService.isControlEnabled() && getActiveSource().logicalAddress != mAddress) {
- updateActiveSource(mAddress, mService.getPhysicalAddress());
+ updateActiveSource(mAddress, mService.getPhysicalAddress(),
+ "HdmiCecLocalDeviceTv#handleSelectInternalSource()");
if (mSkipRoutingControl) {
mSkipRoutingControl = false;
return;
@@ -319,19 +321,19 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
@ServiceThreadOnly
- void updateActiveSource(int logicalAddress, int physicalAddress) {
+ void updateActiveSource(int logicalAddress, int physicalAddress, String caller) {
assertRunOnServiceThread();
- updateActiveSource(ActiveSource.of(logicalAddress, physicalAddress));
+ updateActiveSource(ActiveSource.of(logicalAddress, physicalAddress), caller);
}
@ServiceThreadOnly
- void updateActiveSource(ActiveSource newActive) {
+ void updateActiveSource(ActiveSource newActive, String caller) {
assertRunOnServiceThread();
// Seq #14
if (getActiveSource().equals(newActive)) {
return;
}
- setActiveSource(newActive);
+ setActiveSource(newActive, caller);
int logicalAddress = newActive.logicalAddress;
if (getCecDeviceInfo(logicalAddress) != null && logicalAddress != mAddress) {
if (mService.pathToPortId(newActive.physicalAddress) == getActivePortId()) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 70ffaae1a9af..44b6a63faea1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -3228,7 +3228,7 @@ public class HdmiControlService extends SystemService {
}
}
- void setActiveSource(int logicalAddress, int physicalAddress) {
+ void setActiveSource(int logicalAddress, int physicalAddress, String caller) {
synchronized (mLock) {
mActiveSource.logicalAddress = logicalAddress;
mActiveSource.physicalAddress = physicalAddress;
@@ -3239,14 +3239,17 @@ public class HdmiControlService extends SystemService {
// mIsActiveSource only exists in source device, ignore this setting if the current
// device is not an HdmiCecLocalDeviceSource.
if (!(device instanceof HdmiCecLocalDeviceSource)) {
+ device.addActiveSourceHistoryItem(new ActiveSource(logicalAddress, physicalAddress),
+ false, caller);
continue;
}
- if (logicalAddress == device.getDeviceInfo().getLogicalAddress()
- && physicalAddress == getPhysicalAddress()) {
- ((HdmiCecLocalDeviceSource) device).setIsActiveSource(true);
- } else {
- ((HdmiCecLocalDeviceSource) device).setIsActiveSource(false);
- }
+ boolean deviceIsActiveSource =
+ logicalAddress == device.getDeviceInfo().getLogicalAddress()
+ && physicalAddress == getPhysicalAddress();
+
+ ((HdmiCecLocalDeviceSource) device).setIsActiveSource(deviceIsActiveSource);
+ device.addActiveSourceHistoryItem(new ActiveSource(logicalAddress, physicalAddress),
+ deviceIsActiveSource, caller);
}
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 817902d9d566..b61c6a7ca569 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -205,8 +205,13 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
}
if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(TAG, String.format("Successfully pushed rule set: %s", version));
+ Slog.i(
+ TAG,
+ String.format(
+ "Successfully pushed rule set to version '%s' from '%s'",
+ version, ruleProvider));
}
+
FrameworkStatsLog.write(
FrameworkStatsLog.INTEGRITY_RULES_PUSHED,
success,
@@ -324,13 +329,12 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
+ getAllowedInstallers(packageInfo));
}
IntegrityCheckResult result = mEvaluationEngine.evaluate(appInstallMetadata);
- if (DEBUG_INTEGRITY_COMPONENT) {
+ if (!result.getMatchedRules().isEmpty() || DEBUG_INTEGRITY_COMPONENT) {
Slog.i(
TAG,
- "Integrity check result: "
- + result.getEffect()
- + " due to "
- + result.getMatchedRules());
+ String.format(
+ "Integrity check of %s result: %s due to %s",
+ packageName, result.getEffect(), result.getMatchedRules()));
}
FrameworkStatsLog.write(
@@ -673,8 +677,10 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
// Obtain the system apps that are whitelisted in config_integrityRuleProviderPackages.
List<String> allowedRuleProviders = getAllowedRuleProviderSystemApps();
if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(TAG, String.format(
- "Rule provider system app list contains: %s", allowedRuleProviders));
+ Slog.i(
+ TAG,
+ String.format(
+ "Rule provider system app list contains: %s", allowedRuleProviders));
}
// Identify the package names in the caller list.
@@ -730,9 +736,9 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
private boolean integrityCheckIncludesRuleProvider() {
return Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
- 0)
+ mContext.getContentResolver(),
+ Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
+ 0)
== 1;
}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 534533f2fc97..f4d0a6254318 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -697,7 +697,8 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- Location location = manager.getLastLocation(request, identity, permissionLevel);
+ Location location = manager.getLastLocation(identity, permissionLevel,
+ request.isLocationSettingsIgnored());
// lastly - note app ops
if (!mInjector.getAppOpsHelper().noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel),
@@ -740,13 +741,9 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- // create a location request that works in almost all circumstances
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(GPS_PROVIDER, 0,
- 0, true);
-
- // use our own identity rather than the caller
- CallerIdentity identity = CallerIdentity.fromContext(mContext);
- Location location = gpsManager.getLastLocation(request, identity, PERMISSION_FINE);
+ // use fine permission level to avoid creating unnecessary coarse locations
+ Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
+ PERMISSION_FINE, false);
if (location == null) {
return null;
}
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index 66245a279666..1815a8554705 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -434,18 +434,17 @@ class LocationProviderManager extends
}
LocationRequest newRequest = calculateProviderLocationRequest();
- if (!mProviderLocationRequest.equals(newRequest)) {
- LocationRequest oldRequest = mProviderLocationRequest;
- mProviderLocationRequest = newRequest;
- onHighPowerUsageChanged();
- updateService();
-
- // if location settings ignored has changed then the active state may have changed
- return oldRequest.isLocationSettingsIgnored()
- != newRequest.isLocationSettingsIgnored();
+ if (mProviderLocationRequest.equals(newRequest)) {
+ return false;
}
- return false;
+ LocationRequest oldRequest = mProviderLocationRequest;
+ mProviderLocationRequest = newRequest;
+ onHighPowerUsageChanged();
+ updateService();
+
+ // if location settings ignored has changed then the active state may have changed
+ return oldRequest.isLocationSettingsIgnored() != newRequest.isLocationSettingsIgnored();
}
private LocationRequest calculateProviderLocationRequest() {
@@ -1229,10 +1228,8 @@ class LocationProviderManager extends
}
@Nullable
- public Location getLastLocation(LocationRequest request, CallerIdentity identity,
- @PermissionLevel int permissionLevel) {
- Preconditions.checkArgument(mName.equals(request.getProvider()));
-
+ public Location getLastLocation(CallerIdentity identity, @PermissionLevel int permissionLevel,
+ boolean ignoreLocationSettings) {
if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
identity.getPackageName())) {
return null;
@@ -1240,12 +1237,12 @@ class LocationProviderManager extends
if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
return null;
}
- if (!request.isLocationSettingsIgnored() && !isEnabled(identity.getUserId())) {
+ if (!ignoreLocationSettings && !isEnabled(identity.getUserId())) {
return null;
}
- Location location = getLastLocation(identity.getUserId(), permissionLevel,
- request.isLocationSettingsIgnored());
+ Location location = getLastLocationUnsafe(identity.getUserId(), permissionLevel,
+ ignoreLocationSettings);
// we don't note op here because we don't know what the client intends to do with the
// location, the client is responsible for noting if necessary
@@ -1259,9 +1256,30 @@ class LocationProviderManager extends
}
}
+ /**
+ * This function does not perform any permissions or safety checks, by calling it you are
+ * committing to performing all applicable checks yourself. Prefer
+ * {@link #getLastLocation(CallerIdentity, int, boolean)} where possible.
+ */
@Nullable
- private Location getLastLocation(int userId, @PermissionLevel int permissionLevel,
+ public Location getLastLocationUnsafe(int userId, @PermissionLevel int permissionLevel,
boolean ignoreLocationSettings) {
+ if (userId == UserHandle.USER_ALL) {
+ Location lastLocation = null;
+ final int[] runningUserIds = mUserInfoHelper.getRunningUserIds();
+ for (int i = 0; i < runningUserIds.length; i++) {
+ Location next = getLastLocationUnsafe(runningUserIds[i], permissionLevel,
+ ignoreLocationSettings);
+ if (lastLocation == null || (next != null && next.getElapsedRealtimeNanos()
+ > lastLocation.getElapsedRealtimeNanos())) {
+ lastLocation = next;
+ }
+ }
+ return lastLocation;
+ }
+
+ Preconditions.checkArgument(userId >= 0);
+
synchronized (mLock) {
LastLocation lastLocation = mLastLocations.get(userId);
if (lastLocation == null) {
@@ -1273,7 +1291,7 @@ class LocationProviderManager extends
public void injectLastLocation(Location location, int userId) {
synchronized (mLock) {
- if (getLastLocation(userId, PERMISSION_FINE, false) == null) {
+ if (getLastLocationUnsafe(userId, PERMISSION_FINE, false) == null) {
setLastLocation(location, userId);
}
}
@@ -1322,7 +1340,22 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Location lastLocation = getLastLocation(request, callerIdentity, permissionLevel);
+ if (mSettingsHelper.isLocationPackageBlacklisted(callerIdentity.getUserId(),
+ callerIdentity.getPackageName())) {
+ registration.deliverLocation(null);
+ return;
+ }
+ if (!mUserInfoHelper.isCurrentUserId(callerIdentity.getUserId())) {
+ registration.deliverLocation(null);
+ return;
+ }
+ if (!request.isLocationSettingsIgnored() && !isEnabled(callerIdentity.getUserId())) {
+ registration.deliverLocation(null);
+ return;
+ }
+
+ Location lastLocation = getLastLocationUnsafe(callerIdentity.getUserId(),
+ permissionLevel, request.isLocationSettingsIgnored());
if (lastLocation != null) {
long locationAgeMs = NANOSECONDS.toMillis(
SystemClock.elapsedRealtimeNanos()
@@ -1346,17 +1379,17 @@ class LocationProviderManager extends
} finally {
Binder.restoreCallingIdentity(identity);
}
+ }
- CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
- cancellationTransport);
- if (cancellationSignal != null) {
- cancellationSignal.setOnCancelListener(
- () -> {
- synchronized (mLock) {
- removeRegistration(callback.asBinder(), registration);
- }
- });
- }
+ CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
+ cancellationTransport);
+ if (cancellationSignal != null) {
+ cancellationSignal.setOnCancelListener(SingleUseCallback.wrap(
+ () -> {
+ synchronized (mLock) {
+ removeRegistration(callback.asBinder(), registration);
+ }
+ }));
}
}
@@ -1934,7 +1967,8 @@ class LocationProviderManager extends
ipw.println("user " + userId + ":");
ipw.increaseIndent();
}
- ipw.println("last location=" + getLastLocation(userId, PERMISSION_FINE, false));
+ ipw.println(
+ "last location=" + getLastLocationUnsafe(userId, PERMISSION_FINE, false));
ipw.println("enabled=" + isEnabled(userId));
if (userIds.length != 1) {
ipw.decreaseIndent();
@@ -2007,7 +2041,7 @@ class LocationProviderManager extends
}
// update last coarse interval only if enough time has passed
long timeDeltaMs = NANOSECONDS.toMillis(newCoarse.getElapsedRealtimeNanos())
- - NANOSECONDS.toMillis(oldCoarse.getElapsedRealtimeNanos());
+ - NANOSECONDS.toMillis(oldCoarse.getElapsedRealtimeNanos());
if (timeDeltaMs > FASTEST_COARSE_INTERVAL_MS) {
return newCoarse;
} else {
@@ -2016,10 +2050,11 @@ class LocationProviderManager extends
}
}
- private static class SingleUseCallback extends IRemoteCallback.Stub {
+ private static class SingleUseCallback extends IRemoteCallback.Stub implements Runnable,
+ CancellationSignal.OnCancelListener {
@Nullable
- public static IRemoteCallback wrap(@Nullable Runnable callback) {
+ public static SingleUseCallback wrap(@Nullable Runnable callback) {
return callback == null ? null : new SingleUseCallback(callback);
}
@@ -2032,6 +2067,16 @@ class LocationProviderManager extends
@Override
public void sendResult(Bundle data) {
+ run();
+ }
+
+ @Override
+ public void onCancel() {
+ run();
+ }
+
+ @Override
+ public void run() {
Runnable callback;
synchronized (this) {
callback = mCallback;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 12419a9fcafa..5bc6e237ef37 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6259,6 +6259,8 @@ public class NotificationManagerService extends SystemService {
for (NotificationRecord r : enqueued) {
if (r.mUpdateTimeMs > mWhen) {
// At least one enqueue was posted after the cancel, so we're invalid
+ Slog.i(TAG, "notification cancel ignored due to newer enqueued entry"
+ + "key=" + r.getSbn().getKey());
return;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c6269eba8120..9f78f0f08fd1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3344,6 +3344,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Remove disable package settings for updated system apps that were
// removed via an OTA. If the update is no longer present, remove the
// app completely. Otherwise, revoke their system privileges.
+ final int[] userIds = mUserManager.getUserIds();
for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
final AndroidPackage pkg = mPackages.get(packageName);
@@ -3386,7 +3387,7 @@ public class PackageManagerService extends IPackageManager.Stub
// partition], completely remove the package data.
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null && mPackages.get(packageName) == null) {
- removePackageDataLIF(ps, null, null, 0, false);
+ removePackageDataLIF(ps, userIds, null, 0, false);
}
logCriticalInfo(Log.WARN, msg);
@@ -3853,8 +3854,9 @@ public class PackageManagerService extends IPackageManager.Stub
// If we don't, installing the system package fails during scan
enableSystemPackageLPw(stubPkg);
}
- installPackageFromSystemLIF(stubPkg.getCodePath(), null /*allUserHandles*/,
- null /*origUserHandles*/, true /*writeSettings*/);
+ installPackageFromSystemLIF(stubPkg.getCodePath(),
+ mUserManager.getUserIds() /*allUserHandles*/, null /*origUserHandles*/,
+ true /*writeSettings*/);
} catch (PackageManagerException pme) {
// Serious WTF; we have to be able to install the stub
Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(),
@@ -9582,8 +9584,8 @@ public class PackageManagerService extends IPackageManager.Stub
try (@SuppressWarnings("unused") PackageFreezer freezer = freezePackage(
parsedPackage.getPackageName(),
"scanPackageInternalLI")) {
- deletePackageLIF(parsedPackage.getPackageName(), null, true, null, 0, null,
- false, null);
+ deletePackageLIF(parsedPackage.getPackageName(), null, true,
+ mUserManager.getUserIds(), 0, null, false, null);
}
pkgSetting = null;
} else if (newPkgVersionGreater) {
@@ -16388,9 +16390,11 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private static class CommitRequest {
final Map<String, ReconciledPackage> reconciledPackages;
+ @NonNull
final int[] mAllUsers;
- private CommitRequest(Map<String, ReconciledPackage> reconciledPackages, int[] allUsers) {
+ private CommitRequest(Map<String, ReconciledPackage> reconciledPackages,
+ @NonNull int[] allUsers) {
this.reconciledPackages = reconciledPackages;
this.mAllUsers = allUsers;
}
@@ -18903,7 +18907,7 @@ public class PackageManagerService extends IPackageManager.Stub
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
- private void removePackageDataLIF(final PackageSetting deletedPs, int[] allUserHandles,
+ private void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = deletedPs.name;
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
@@ -18991,7 +18995,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
// make sure to preserve per-user disabled state if this removal was just
// a downgrade of a system app to the factory package
- if (allUserHandles != null && outInfo != null && outInfo.origUsers != null) {
+ if (outInfo != null && outInfo.origUsers != null) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
@@ -19044,11 +19048,10 @@ public class PackageManagerService extends IPackageManager.Stub
* Tries to delete system package.
*/
private void deleteSystemPackageLIF(DeletePackageAction action, PackageSetting deletedPs,
- int[] allUserHandles, int flags, @Nullable PackageRemovedInfo outInfo,
+ @NonNull int[] allUserHandles, int flags, @Nullable PackageRemovedInfo outInfo,
boolean writeSettings)
throws SystemDeleteException {
- final boolean applyUserRestrictions =
- (allUserHandles != null) && outInfo != null && (outInfo.origUsers != null);
+ final boolean applyUserRestrictions = outInfo != null && (outInfo.origUsers != null);
final AndroidPackage deletedPkg = deletedPs.pkg;
// Confirm if the system package has been updated
// An updated system app can be deleted. This will also have to restore
@@ -19132,7 +19135,7 @@ public class PackageManagerService extends IPackageManager.Stub
* Installs a package that's already on the system partition.
*/
private AndroidPackage installPackageFromSystemLIF(@NonNull String codePathString,
- @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)
+ @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)
throws PackageManagerException {
final File codePath = new File(codePathString);
@ParseFlags int parseFlags =
@@ -19174,8 +19177,7 @@ public class PackageManagerService extends IPackageManager.Stub
// and granting install permissions.
mPermissionManager.updatePermissions(pkg.getPackageName(), pkg);
- final boolean applyUserRestrictions
- = (allUserHandles != null) && (origUserHandles != null);
+ final boolean applyUserRestrictions = origUserHandles != null;
if (applyUserRestrictions) {
boolean installedStateChanged = false;
if (DEBUG_REMOVE) {
@@ -19212,7 +19214,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private void deleteInstalledPackageLIF(PackageSetting ps,
- boolean deleteCodeAndResources, int flags, int[] allUserHandles,
+ boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings) {
synchronized (mLock) {
if (outInfo != null) {
@@ -19332,7 +19334,7 @@ public class PackageManagerService extends IPackageManager.Stub
* This method handles package deletion in general
*/
private boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
- boolean deleteCodeAndResources, int[] allUserHandles, int flags,
+ boolean deleteCodeAndResources, @NonNull int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings,
ParsedPackage replacingPackage) {
final DeletePackageAction action;
@@ -19369,7 +19371,7 @@ public class PackageManagerService extends IPackageManager.Stub
/** Deletes a package. Only throws when install of a disabled package fails. */
private void executeDeletePackageLIF(DeletePackageAction action,
String packageName, boolean deleteCodeAndResources,
- int[] allUserHandles, boolean writeSettings,
+ @NonNull int[] allUserHandles, boolean writeSettings,
ParsedPackage replacingPackage) throws SystemDeleteException {
final PackageSetting ps = action.deletingPs;
final PackageRemovedInfo outInfo = action.outInfo;
@@ -22784,6 +22786,7 @@ public class PackageManagerService extends IPackageManager.Stub
return;
}
+ final int[] userIds = mUserManager.getUserIds();
final ArrayList<AndroidPackage> unloaded = new ArrayList<>();
synchronized (mInstallLock) {
synchronized (mLock) {
@@ -22797,7 +22800,7 @@ public class PackageManagerService extends IPackageManager.Stub
try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags,
"unloadPrivatePackagesInner")) {
- if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo,
+ if (deletePackageLIF(ps.name, null, false, userIds, deleteFlags, outInfo,
false, null)) {
unloaded.add(pkg);
} else {
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 0b0bb7059f3b..53d51463295f 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -115,7 +115,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
private static final String TAG = "UriGrantsManagerService";
// Maximum number of persisted Uri grants a package is allowed
private static final int MAX_PERSISTED_URI_GRANTS = 512;
- private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
+ private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false;
private final Object mLock = new Object();
private final H mH;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9f68d627622c..6df46ed2532b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -133,6 +133,7 @@ import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
import static com.android.server.wm.ActivityRecordProto.NAME;
import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.ActivityRecordProto.PIP_AUTO_ENTER_ALLOWED;
import static com.android.server.wm.ActivityRecordProto.PROC_ID;
import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
@@ -4741,6 +4742,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// returns. Just need to confirm this reasoning makes sense.
final boolean deferHidingClient = canEnterPictureInPicture
&& !isState(STARTED, STOPPING, STOPPED, PAUSED);
+ if (deferHidingClient && pictureInPictureArgs.isAutoEnterAllowed()) {
+ // Go ahead and just put the activity in pip if it supports auto-pip.
+ mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs);
+ return;
+ }
setDeferHidingClient(deferHidingClient);
setVisibility(false);
@@ -7678,6 +7684,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (hasProcess()) {
proto.write(PROC_ID, app.getPid());
}
+ proto.write(PIP_AUTO_ENTER_ALLOWED, pictureInPictureArgs.isAutoEnterAllowed());
}
@Override
@@ -7786,42 +7793,40 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/** Gets the horizontal centered container bounds for size compatibility mode. */
void getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation,
boolean orientationRequested, boolean canChangeOrientation) {
+ getFrameByOrientation(outBounds, orientation);
if (mIsFloating) {
- getFrameByOrientation(outBounds, orientation);
outAppBounds.set(outBounds);
return;
}
- if (canChangeOrientation) {
- getBoundsByRotation(outBounds, rotation);
- if (orientationRequested) {
- getFrameByOrientation(outAppBounds, orientation);
- } else {
- outAppBounds.set(outBounds);
- }
- } else {
- if (orientationRequested) {
- getFrameByOrientation(outBounds, orientation);
- if ((outBounds.width() > outBounds.height()) != (mWidth > mHeight)) {
- // The orientation is mismatched but the display cannot rotate. The bounds
- // will fit to the short side of display.
- if (orientation == ORIENTATION_LANDSCAPE) {
- outBounds.bottom = (int) ((float) mWidth * mWidth / mHeight);
- outBounds.right = mWidth;
- } else {
- outBounds.bottom = mHeight;
- outBounds.right = (int) ((float) mHeight * mHeight / mWidth);
- }
- outBounds.offset(
- getHorizontalCenterOffset(mWidth, outBounds.width()), 0 /* dy */);
- }
+ getBoundsByRotation(outAppBounds, rotation);
+ final int dW = outAppBounds.width();
+ final int dH = outAppBounds.height();
+ final boolean isOrientationMismatched =
+ ((outBounds.width() > outBounds.height()) != (dW > dH));
+
+ if (isOrientationMismatched && !canChangeOrientation && orientationRequested) {
+ // The orientation is mismatched but the display cannot rotate. The bounds will fit
+ // to the short side of container.
+ if (orientation == ORIENTATION_LANDSCAPE) {
+ outBounds.bottom = (int) ((float) dW * dW / dH);
+ outBounds.right = dW;
} else {
- outBounds.set(0, 0, mWidth, mHeight);
+ outBounds.bottom = dH;
+ outBounds.right = (int) ((float) dH * dH / dW);
}
- outAppBounds.set(outBounds);
- }
-
- if (rotation != ROTATION_UNDEFINED) {
+ outBounds.offset(getHorizontalCenterOffset(mWidth, outBounds.width()), 0 /* dy */);
+ }
+ outAppBounds.set(outBounds);
+
+ if (isOrientationMismatched) {
+ // One side of container is smaller than the requested size, then it will be scaled
+ // and the final position will be calculated according to the parent container and
+ // scale, so the original size shouldn't be shrunk by insets.
+ final Rect insets = mNonDecorInsets[rotation];
+ outBounds.offset(insets.left, insets.top);
+ outAppBounds.offset(insets.left, insets.top);
+ } else if (rotation != ROTATION_UNDEFINED) {
// Ensure the app bounds won't overlap with insets.
Task.intersectWithInsetsIfFits(outAppBounds, outBounds, mNonDecorInsets[rotation]);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 505233cd8a4a..080a438df357 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -253,7 +253,6 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.SystemServiceManager;
import com.android.server.UiThread;
import com.android.server.Watchdog;
@@ -4059,6 +4058,60 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
&& r.getRootTask().isInTask(r) != null;
}
+ /**
+ * Puts the given activity in picture in picture mode if possible.
+ *
+ * @return true if the activity is now in picture-in-picture mode, or false if it could not
+ * enter picture-in-picture mode.
+ */
+ boolean enterPictureInPictureMode(ActivityRecord r, final PictureInPictureParams params) {
+ // If the activity is already in picture in picture mode, then just return early
+ if (isInPictureInPictureMode(r)) {
+ return true;
+ }
+
+ // Activity supports picture-in-picture, now check that we can enter PiP at this
+ // point, if it is
+ if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
+ false /* beforeStopping */)) {
+ return false;
+ }
+
+ final Runnable enterPipRunnable = () -> {
+ synchronized (mGlobalLock) {
+ if (r.getParent() == null) {
+ Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r);
+ return;
+ }
+ // Only update the saved args from the args that are set
+ r.setPictureInPictureParams(params);
+ final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
+ final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
+ mRootWindowContainer.moveActivityToPinnedStack(
+ r, "enterPictureInPictureMode");
+ final Task stack = r.getRootTask();
+ stack.setPictureInPictureAspectRatio(aspectRatio);
+ stack.setPictureInPictureActions(actions);
+ }
+ };
+
+ if (isKeyguardLocked()) {
+ // If the keyguard is showing or occluded, then try and dismiss it before
+ // entering picture-in-picture (this will prompt the user to authenticate if the
+ // device is currently locked).
+ dismissKeyguard(r.appToken, new KeyguardDismissCallback() {
+ @Override
+ public void onDismissSucceeded() {
+ mH.post(enterPipRunnable);
+ }
+ }, null /* message */);
+ } else {
+ // Enter picture in picture immediately otherwise
+ enterPipRunnable.run();
+ }
+ return true;
+ }
+
@Override
public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) {
final long origId = Binder.clearCallingIdentity();
@@ -4066,52 +4119,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked(
"enterPictureInPictureMode", token, params);
-
- // If the activity is already in picture in picture mode, then just return early
- if (isInPictureInPictureMode(r)) {
- return true;
- }
-
- // Activity supports picture-in-picture, now check that we can enter PiP at this
- // point, if it is
- if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
- false /* beforeStopping */)) {
- return false;
- }
-
- final Runnable enterPipRunnable = () -> {
- synchronized (mGlobalLock) {
- if (r.getParent() == null) {
- Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r);
- return;
- }
- // Only update the saved args from the args that are set
- r.setPictureInPictureParams(params);
- final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
- final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
- mRootWindowContainer.moveActivityToPinnedStack(
- r, "enterPictureInPictureMode");
- final Task stack = r.getRootTask();
- stack.setPictureInPictureAspectRatio(aspectRatio);
- stack.setPictureInPictureActions(actions);
- }
- };
-
- if (isKeyguardLocked()) {
- // If the keyguard is showing or occluded, then try and dismiss it before
- // entering picture-in-picture (this will prompt the user to authenticate if the
- // device is currently locked).
- dismissKeyguard(token, new KeyguardDismissCallback() {
- @Override
- public void onDismissSucceeded() {
- mH.post(enterPipRunnable);
- }
- }, null /* message */);
- } else {
- // Enter picture in picture immediately otherwise
- enterPipRunnable.run();
- }
- return true;
+ return enterPictureInPictureMode(r, params);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -4857,6 +4865,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
"Requested PIP on an activity that doesn't support it");
}
+ if (activity.pictureInPictureArgs.isAutoEnterAllowed()) {
+ enterPictureInPictureMode(activity, activity.pictureInPictureArgs);
+ return;
+ }
+
try {
final ClientTransaction transaction = ClientTransaction.obtain(
activity.app.getThread(),
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1c147c259f07..4998624b9097 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -29,6 +29,7 @@ import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -38,11 +39,6 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_TOP_GESTURES;
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
@@ -57,20 +53,18 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCRE
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -78,27 +72,21 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
-import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
@@ -171,7 +159,6 @@ import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
-import android.view.ViewRootImpl;
import android.view.WindowInsets.Side;
import android.view.WindowInsets.Side.InsetsSide;
import android.view.WindowInsets.Type;
@@ -1440,8 +1427,7 @@ public class DisplayPolicy {
DisplayCutout.ParcelableWrapper outDisplayCutout) {
final int fl = PolicyControl.getWindowFlags(null, attrs);
final int pfl = attrs.privateFlags;
- final int requestedSysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
- final int sysUiVis = requestedSysUiVis | getImpliedSysUiFlagsForLayout(attrs);
+ final int sysUiVis = PolicyControl.getSystemUiVisibility(null, attrs);
final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
final boolean layoutInScreenAndInsetDecor = layoutInScreen
@@ -1461,7 +1447,7 @@ public class DisplayPolicy {
: mDisplayContent.mDisplayFrames;
if (layoutInScreenAndInsetDecor && !screenDecor) {
- if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+ if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
|| (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) {
outFrame.set(displayFrames.mUnrestricted);
} else {
@@ -1492,7 +1478,6 @@ public class DisplayPolicy {
InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
.getDisplayCutout());
- return mForceShowSystemBars;
} else {
if (layoutInScreen) {
outFrame.set(displayFrames.mUnrestricted);
@@ -1506,22 +1491,8 @@ public class DisplayPolicy {
outContentInsets.setEmpty();
outStableInsets.setEmpty();
outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
- return mForceShowSystemBars;
}
- }
-
- // TODO(b/118118435): remove after migration
- private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
- int impliedFlags = 0;
- final boolean forceWindowDrawsBarBackgrounds =
- (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
- && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
- if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || forceWindowDrawsBarBackgrounds) {
- impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
- }
- return impliedFlags;
+ return mForceShowSystemBars;
}
private final Runnable mClearHideNavigationFlag = new Runnable() {
@@ -1668,11 +1639,8 @@ public class DisplayPolicy {
final int behavior = mLastBehavior;
final InsetsSourceProvider provider =
mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR);
- boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL
- ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
- : provider != null
- ? provider.isClientVisible()
- : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
+ boolean navVisible = provider != null ? provider.isClientVisible()
+ : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
boolean navTranslucent = (sysui
& (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0
@@ -2057,80 +2025,6 @@ public class DisplayPolicy {
return mNavigationBarController.checkHiddenLw();
}
- private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
- boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf,
- DisplayFrames displayFrames) {
- if (!win.isInputMethodTarget() && attached.isInputMethodTarget()) {
- // Here's a special case: if the child window is not the 'dock window'
- // or input method target, and the window it is attached to is below
- // the dock window, then the frames we computed for the window it is
- // attached to can not be used because the dock is effectively part
- // of the underlying window and the attached window is floating on top
- // of the whole thing. So, we ignore the attached window and explicitly
- // compute the frames that would be appropriate without the dock.
- vf.set(displayFrames.mDock);
- cf.set(displayFrames.mDock);
- df.set(displayFrames.mDock);
- } else {
-
- // In case we forced the window to draw behind the navigation bar, restrict df to
- // DF.Restricted to simulate old compat behavior.
- Rect parentDisplayFrame = attached.getDisplayFrame();
- final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
- if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
- && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
- && (attachedAttrs.systemUiVisibility
- & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
- parentDisplayFrame = new Rect(parentDisplayFrame);
- parentDisplayFrame.intersect(displayFrames.mRestricted);
- }
-
- // The effective display frame of the attached window depends on whether it is taking
- // care of insetting its content. If not, we need to use the parent's content frame so
- // that the entire window is positioned within that content. Otherwise we can use the
- // parent display frame and let the attached window take care of positioning its content
- // appropriately.
- if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- // Set the content frame of the attached window to the parent's decor frame
- // (same as content frame when IME isn't present) if specifically requested by
- // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
- // Otherwise, use the overscan frame.
- cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
- ? attached.getContentFrame() : parentDisplayFrame);
- } else {
- // If the window is resizing, then we want to base the content frame on our attached
- // content frame to resize...however, things can be tricky if the attached window is
- // NOT in resize mode, in which case its content frame will be larger.
- // Ungh. So to deal with that, make sure the content frame we end up using is not
- // covering the IM dock.
- cf.set(attached.getContentFrame());
- if (attached.isVoiceInteraction()) {
- cf.intersectUnchecked(displayFrames.mVoiceContent);
- } else if (win.isInputMethodTarget() || attached.isInputMethodTarget()) {
- cf.intersectUnchecked(displayFrames.mContent);
- }
- }
- df.set(insetDecors ? parentDisplayFrame : cf);
- vf.set(attached.getVisibleFrame());
- }
- // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
- // positioned relative to its parent or the entire screen.
- pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrame() : df);
- }
-
- private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) {
- if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) {
- return;
- }
- // If app is requesting a stable layout, don't let the content insets go below the stable
- // values.
- if ((fl & FLAG_FULLSCREEN) != 0) {
- r.intersectUnchecked(displayFrames.mStableFullscreen);
- } else {
- r.intersectUnchecked(displayFrames.mStable);
- }
- }
-
private boolean canReceiveInput(WindowState win) {
boolean notFocusable =
(win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
@@ -2165,8 +2059,6 @@ public class DisplayPolicy {
final int fl = PolicyControl.getWindowFlags(win, attrs);
final int pfl = attrs.privateFlags;
final int sim = attrs.softInputMode;
- final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
- final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);
displayFrames = win.getDisplayFrames(displayFrames);
final WindowFrames windowFrames = win.getWindowFrames();
@@ -2191,351 +2083,60 @@ public class DisplayPolicy {
sf.set(displayFrames.mStable);
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
- final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
- final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
- getRotatedWindowBounds(displayFrames, win, sTmpRect);
- final Rect dfu = sTmpRect;
- Insets insets = Insets.of(0, 0, 0, 0);
- for (int i = types.size() - 1; i >= 0; i--) {
- final InsetsSource source = mDisplayContent.getInsetsPolicy()
- .getInsetsForDispatch(win).peekSource(types.valueAt(i));
- if (source == null) {
- continue;
- }
- insets = Insets.max(insets, source.calculateInsets(
- dfu, attrs.isFitInsetsIgnoringVisibility()));
- }
- final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
- final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
- final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
- final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
- df.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
- if (attached == null) {
- pf.set(df);
- vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
- ? displayFrames.mCurrent : displayFrames.mDock);
- } else {
- pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrame() : df);
- vf.set(attached.getVisibleFrame());
- }
- cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE
- ? displayFrames.mDock : displayFrames.mContent);
- dcf.set(displayFrames.mSystem);
- } else if (type == TYPE_INPUT_METHOD) {
- vf.set(displayFrames.mDock);
- cf.set(displayFrames.mDock);
- df.set(displayFrames.mDock);
- pf.set(displayFrames.mDock);
- // IM dock windows layout below the nav bar...
- pf.bottom = df.bottom = displayFrames.mUnrestricted.bottom;
- // ...with content insets above the nav bar
- cf.bottom = vf.bottom = displayFrames.mStable.bottom;
- if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
- // The status bar forces the navigation bar while it's visible. Make sure the IME
- // avoids the navigation bar in that case.
- if (mNavigationBarPosition == NAV_BAR_RIGHT) {
- pf.right = df.right = cf.right = vf.right =
- displayFrames.mStable.right;
- } else if (mNavigationBarPosition == NAV_BAR_LEFT) {
- pf.left = df.left = cf.left = vf.left = displayFrames.mStable.left;
- }
- }
-
- // In case the navigation bar is on the bottom, we use the frame height instead of the
- // regular height for the insets we send to the IME as we need some space to show
- // additional buttons in SystemUI when the IME is up.
- if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
- final int rotation = displayFrames.mRotation;
- final int uimode = mService.mPolicy.getUiMode();
- final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
- - getNavigationBarHeight(rotation, uimode);
- if (navHeightOffset > 0) {
- cf.bottom -= navHeightOffset;
- sf.bottom -= navHeightOffset;
- vf.bottom -= navHeightOffset;
- dcf.bottom -= navHeightOffset;
- }
- }
-
- // IM dock windows always go to the bottom of the screen.
- attrs.gravity = Gravity.BOTTOM;
- } else if (type == TYPE_VOICE_INTERACTION) {
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(displayFrames.mDock);
- } else {
- cf.set(displayFrames.mContent);
- }
- if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
- vf.set(displayFrames.mCurrent);
- } else {
- vf.set(cf);
+ final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
+ final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
+ final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
+ getRotatedWindowBounds(displayFrames, win, sTmpRect);
+ final Rect dfu = sTmpRect;
+ Insets insets = Insets.of(0, 0, 0, 0);
+ for (int i = types.size() - 1; i >= 0; i--) {
+ final InsetsSource source = mDisplayContent.getInsetsPolicy()
+ .getInsetsForDispatch(win).peekSource(types.valueAt(i));
+ if (source == null) {
+ continue;
}
- } else if (type == TYPE_WALLPAPER) {
- layoutWallpaper(displayFrames, pf, df, cf);
- } else if (win == mStatusBar || type == TYPE_NOTIFICATION_SHADE) {
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- cf.set(displayFrames.mStable);
- vf.set(displayFrames.mStable);
-
- if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
- // cf.bottom should not be below the stable bottom, or the content might be obscured
- // by the navigation bar.
- if (cf.bottom > displayFrames.mContent.bottom) {
- cf.bottom = displayFrames.mContent.bottom;
- }
- } else {
- if (cf.bottom > displayFrames.mDock.bottom) {
- cf.bottom = displayFrames.mDock.bottom;
- }
- if (vf.bottom > displayFrames.mContent.bottom) {
- vf.bottom = displayFrames.mContent.bottom;
+ insets = Insets.max(insets, source.calculateInsets(
+ dfu, attrs.isFitInsetsIgnoringVisibility()));
+ }
+ final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
+ final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
+ final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
+ final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
+ df.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
+ if (attached == null) {
+ pf.set(df);
+ if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
+ final InsetsSource source = mDisplayContent.getInsetsPolicy()
+ .getInsetsForDispatch(win).peekSource(ITYPE_IME);
+ if (source != null) {
+ pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */));
}
}
+ vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
+ ? displayFrames.mCurrent : displayFrames.mDock);
} else {
- dcf.set(displayFrames.mSystem);
- final boolean isAppWindow =
- type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW;
- final boolean topAtRest =
- win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw();
- if (isAppWindow && !topAtRest) {
- if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0
- && (fl & FLAG_FULLSCREEN) == 0
- && (fl & FLAG_TRANSLUCENT_STATUS) == 0
- && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
- && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
- // Ensure policy decor includes status bar
- dcf.top = displayFrames.mStable.top;
- }
- if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
- && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
- && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
- && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
- // Ensure policy decor includes navigation bar
- dcf.bottom = displayFrames.mStable.bottom;
- dcf.right = displayFrames.mStable.right;
- }
- }
-
- if (layoutInScreen && layoutInsetDecor) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
- + "): IN_SCREEN, INSET_DECOR");
- // This is the case for a normal activity window: we want it to cover all of the
- // screen space, and it can take care of moving its contents to account for screen
- // decorations that intrude into that space.
- if (attached != null) {
- // If this window is attached to another, our display
- // frame is the same as the one we are attached to.
- setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf,
- displayFrames);
- } else {
- if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
- // Status bar panels are the only windows who can go on top of the status
- // bar. They are protected by the STATUS_BAR_SERVICE permission, so they
- // have the same privileges as the status bar itself.
- //
- // However, they should still dodge the navigation bar if it exists.
-
- pf.left = df.left = hasNavBar
- ? displayFrames.mDock.left : displayFrames.mUnrestricted.left;
- pf.top = df.top = displayFrames.mUnrestricted.top;
- pf.right = df.right = hasNavBar
- ? displayFrames.mRestricted.right
- : displayFrames.mUnrestricted.right;
- pf.bottom = df.bottom = hasNavBar
- ? displayFrames.mRestricted.bottom
- : displayFrames.mUnrestricted.bottom;
-
- if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out status bar window: " + pf);
- } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
- && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
- || type == TYPE_VOLUME_OVERLAY
- || type == TYPE_KEYGUARD_DIALOG)) {
- // Asking for layout as if the nav bar is hidden, lets the application
- // extend into the unrestricted overscan screen area. We only do this for
- // application windows and certain system windows to ensure no window that
- // can be above the nav bar can do this.
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- } else {
- df.set(displayFrames.mRestricted);
- pf.set(displayFrames.mRestricted);
- }
-
- if ((fl & FLAG_FULLSCREEN) == 0) {
- if (win.isVoiceInteraction()) {
- cf.set(displayFrames.mVoiceContent);
- } else {
- // IME Insets are handled on the client for ADJUST_RESIZE in the new
- // insets world
- if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
- || adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(displayFrames.mDock);
- } else {
- cf.set(displayFrames.mContent);
- }
- }
- } else {
- // Full screen windows are always given a layout that is as if the status
- // bar and other transient decors are gone. This is to avoid bad states when
- // moving from a window that is not hiding the status bar to one that is.
- cf.set(displayFrames.mRestricted);
- }
- applyStableConstraints(sysUiFl, fl, cf, displayFrames);
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
- && adjust != SOFT_INPUT_ADJUST_NOTHING) {
- vf.set(displayFrames.mCurrent);
- } else {
- vf.set(cf);
- }
- }
- } else if (layoutInScreen || (sysUiFl
- & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
- + "): IN_SCREEN");
- // A window that has requested to fill the entire screen just
- // gets everything, period.
- if (type == TYPE_STATUS_BAR_ADDITIONAL || type == TYPE_STATUS_BAR_SUB_PANEL) {
- cf.set(displayFrames.mUnrestricted);
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- if (hasNavBar) {
- pf.left = df.left = cf.left = displayFrames.mDock.left;
- pf.right = df.right = cf.right = displayFrames.mRestricted.right;
- pf.bottom = df.bottom = cf.bottom =
- displayFrames.mRestricted.bottom;
- }
- if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out IN_SCREEN status bar window: " + pf);
- } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) {
- // The navigation bar has Real Ultimate Power.
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- if (DEBUG_LAYOUT) Slog.v(TAG, "Laying out navigation bar window: " + pf);
- } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT)
- && ((fl & FLAG_FULLSCREEN) != 0)) {
- // Fullscreen secure system overlays get what they ask for. Screenshot region
- // selection overlay should also expand to full screen.
- cf.set(displayFrames.mUnrestricted);
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- } else if (type == TYPE_BOOT_PROGRESS) {
- // Boot progress screen always covers entire display.
- cf.set(displayFrames.mUnrestricted);
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
- && (type == TYPE_NOTIFICATION_SHADE
- || type == TYPE_TOAST
- || type == TYPE_DOCK_DIVIDER
- || type == TYPE_VOICE_INTERACTION_STARTING
- || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) {
- // Asking for layout as if the nav bar is hidden, lets the
- // application extend into the unrestricted screen area. We
- // only do this for application windows (or toasts) to ensure no window that
- // can be above the nav bar can do this.
- // XXX This assumes that an app asking for this will also
- // ask for layout in only content. We can't currently figure out
- // what the screen would be if only laying out to hide the nav bar.
- cf.set(displayFrames.mUnrestricted);
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) {
- df.set(displayFrames.mRestricted);
- pf.set(displayFrames.mRestricted);
-
- // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
- // world
- if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
- || adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(displayFrames.mDock);
- } else {
- cf.set(displayFrames.mContent);
- }
- } else {
- cf.set(displayFrames.mRestricted);
- df.set(displayFrames.mRestricted);
- pf.set(displayFrames.mRestricted);
- }
-
- applyStableConstraints(sysUiFl, fl, cf, displayFrames);
-
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
- && adjust != SOFT_INPUT_ADJUST_NOTHING) {
- vf.set(displayFrames.mCurrent);
- } else {
- vf.set(cf);
- }
- } else if (attached != null) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
- + "): attached to " + attached);
- // A child window should be placed inside of the same visible
- // frame that its parent had.
- setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf,
- displayFrames);
- } else {
- if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
- + "): normal window");
- // Otherwise, a normal window must be placed inside the content
- // of all screen decorations.
- if (type == TYPE_STATUS_BAR_ADDITIONAL) {
- // Status bar panels can go on
- // top of the status bar. They are protected by the STATUS_BAR_SERVICE
- // permission, so they have the same privileges as the status bar itself.
- cf.set(displayFrames.mRestricted);
- df.set(displayFrames.mRestricted);
- pf.set(displayFrames.mRestricted);
- } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
- // These dialogs are stable to interim decor changes.
- cf.set(displayFrames.mStable);
- df.set(displayFrames.mStable);
- pf.set(displayFrames.mStable);
- } else {
- pf.set(displayFrames.mContent);
- if (win.isVoiceInteraction()) {
- cf.set(displayFrames.mVoiceContent);
- df.set(displayFrames.mVoiceContent);
- } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(displayFrames.mDock);
- df.set(displayFrames.mDock);
- } else {
- cf.set(displayFrames.mContent);
- df.set(displayFrames.mContent);
- }
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE
- && adjust != SOFT_INPUT_ADJUST_NOTHING) {
- vf.set(displayFrames.mCurrent);
- } else {
- vf.set(cf);
- }
- }
- }
+ pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrame() : df);
+ vf.set(attached.getVisibleFrame());
}
+ cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE
+ ? displayFrames.mDock : displayFrames.mContent);
+ dcf.set(displayFrames.mSystem);
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
- final boolean attachedInParent = attached != null && !layoutInScreen;
- final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
- || (requestedSysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0
- || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
- && !win.getRequestedInsetsState().getSourceOrDefaultVisibility(
- ITYPE_STATUS_BAR));
- final boolean requestedHideNavigation =
- (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
- || (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
- && !win.getRequestedInsetsState().getSourceOrDefaultVisibility(
- ITYPE_NAVIGATION_BAR));
-
- // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
- // cropped / shifted to the displayFrame in WindowState.
- final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
- && type != TYPE_BASE_APPLICATION;
// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
// the cutout safe zone.
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
+ final boolean attachedInParent = attached != null && !layoutInScreen;
+ final InsetsState requestedInsetsState = win.getRequestedInsetsState();
+ final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
+ || !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR);
+ final boolean requestedHideNavigation =
+ !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+
+ // TYPE_BASE_APPLICATION windows are never considered floating here because they don't
+ // get cropped / shifted to the displayFrame in WindowState.
+ final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
+ && type != TYPE_BASE_APPLICATION;
final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect;
displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) {
@@ -2631,13 +2232,6 @@ public class DisplayPolicy {
}
}
- private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect cf) {
- // The wallpaper has Real Ultimate Power
- df.set(displayFrames.mUnrestricted);
- pf.set(displayFrames.mUnrestricted);
- cf.set(displayFrames.mUnrestricted);
- }
-
private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) {
final int rotation = displayFrames.mRotation;
final int navBarPosition = navigationBarPosition(displayFrames.mDisplayWidth,
@@ -3343,54 +2937,37 @@ public class DisplayPolicy {
// Swipe-up for navigation bar is disabled during setup
return;
}
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
- final InsetsControlTarget controlTarget = provider != null
- ? provider.getControlTarget() : null;
+ final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
+ final InsetsControlTarget controlTarget = provider != null
+ ? provider.getControlTarget() : null;
- if (controlTarget == null || controlTarget == getNotificationShade()) {
- // No transient mode on lockscreen (in notification shade window).
- return;
- }
+ if (controlTarget == null || controlTarget == getNotificationShade()) {
+ // No transient mode on lockscreen (in notification shade window).
+ return;
+ }
- final InsetsState requestedState = controlTarget.getRequestedInsetsState();
- final @InsetsType int restorePositionTypes =
- (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
- ? Type.navigationBars() : 0)
- | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
- ? Type.statusBars() : 0);
-
- if (swipeTarget == mNavigationBar
- && (restorePositionTypes & Type.navigationBars()) != 0) {
- // Don't show status bar when swiping on already visible navigation bar.
- // But restore the position of navigation bar if it has been moved by the control
- // target.
- controlTarget.showInsets(Type.navigationBars(), false);
- return;
- }
+ final InsetsState requestedState = controlTarget.getRequestedInsetsState();
+ final @InsetsType int restorePositionTypes = (requestedState.getSourceOrDefaultVisibility(
+ ITYPE_NAVIGATION_BAR) ? Type.navigationBars() : 0) | (
+ requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR) ? Type.statusBars()
+ : 0);
- if (controlTarget.canShowTransient()) {
- // Show transient bars if they are hidden; restore position if they are visible.
- mDisplayContent.getInsetsPolicy().showTransient(SHOW_TYPES_FOR_SWIPE);
- controlTarget.showInsets(restorePositionTypes, false);
- } else {
- // Restore visibilities and positions of system bars.
- controlTarget.showInsets(Type.statusBars() | Type.navigationBars(), false);
- }
+ if (swipeTarget == mNavigationBar
+ && (restorePositionTypes & Type.navigationBars()) != 0) {
+ // Don't show status bar when swiping on already visible navigation bar.
+ // But restore the position of navigation bar if it has been moved by the control
+ // target.
+ controlTarget.showInsets(Type.navigationBars(), false);
+ return;
+ }
+
+ if (controlTarget.canShowTransient()) {
+ // Show transient bars if they are hidden; restore position if they are visible.
+ mDisplayContent.getInsetsPolicy().showTransient(SHOW_TYPES_FOR_SWIPE);
+ controlTarget.showInsets(restorePositionTypes, false);
} else {
- boolean sb = mStatusBarController.checkShowTransientBarLw();
- boolean nb = mNavigationBarController.checkShowTransientBarLw()
- && !isNavBarEmpty(mLastSystemUiFlags);
- if (sb || nb) {
- // Don't show status bar when swiping on already visible navigation bar
- if (!nb && swipeTarget == mNavigationBar) {
- if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
- return;
- }
- if (sb) mStatusBarController.showTransient();
- if (nb) mNavigationBarController.showTransient();
- updateSystemUiVisibilityLw();
- }
+ // Restore visibilities and positions of system bars.
+ controlTarget.showInsets(Type.statusBars() | Type.navigationBars(), false);
}
mImmersiveModeConfirmation.confirmCurrentPrompt();
}
@@ -3479,11 +3056,10 @@ public class DisplayPolicy {
navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow;
final int opaqueAppearance = InsetsFlags.getAppearance(visibility)
& (APPEARANCE_OPAQUE_STATUS_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS);
- final int appearance = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL
- ? updateLightNavigationBarAppearanceLw(win.mAttrs.insetsFlags.appearance,
- mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState,
- mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance
- : InsetsFlags.getAppearance(visibility);
+ final int appearance = updateLightNavigationBarAppearanceLw(
+ win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState,
+ mTopFullscreenOpaqueOrDimmingWindowState,
+ mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance;
final int diff = visibility ^ mLastSystemUiFlags;
final InsetsPolicy insetsPolicy = getInsetsPolicy();
final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
@@ -3805,9 +3381,8 @@ public class DisplayPolicy {
vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
// update navigation bar
- boolean newInsetsMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL;
- boolean oldImmersiveMode = newInsetsMode ? mLastImmersiveMode : isImmersiveMode(oldVis);
- boolean newImmersiveMode = newInsetsMode ? isImmersiveMode(win) : isImmersiveMode(vis);
+ boolean oldImmersiveMode = mLastImmersiveMode;
+ boolean newImmersiveMode = isImmersiveMode(win);
if (oldImmersiveMode != newImmersiveMode) {
mLastImmersiveMode = newImmersiveMode;
final String pkg = win.getOwningPackage();
@@ -3911,15 +3486,6 @@ public class DisplayPolicy {
}
}
- // TODO(b/118118435): Remove this after migration
- private boolean isImmersiveMode(int vis) {
- final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
- return getNavigationBar() != null
- && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
- && (vis & flags) != 0
- && canHideNavigationBar();
- }
-
private boolean isImmersiveMode(WindowState win) {
if (win == null) {
return false;
@@ -4110,9 +3676,7 @@ public class DisplayPolicy {
mPointerLocationView = new PointerLocationView(mContext);
mPointerLocationView.setPrintCoords(false);
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT);
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 4be4c896cbff..1077736cebb5 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -11,3 +11,4 @@ erosky@google.com
riddlehsu@google.com
louischang@google.com
winsonc@google.com
+tigerhuang@google.com
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 70fd860f21f2..c35d73282442 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5428,6 +5428,7 @@ class Task extends WindowContainer<WindowContainer> {
mAtmService.updateCpuStats();
boolean pauseImmediately = false;
+ boolean shouldAutoPip = false;
if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
// activity to be paused, while at the same time resuming the new resume activity
@@ -5435,26 +5436,39 @@ class Task extends WindowContainer<WindowContainer> {
// activities a chance to enter Pip before resuming the next activity.
final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState(
"shouldResumeWhilePausing", userLeaving);
- if (!lastResumedCanPip) {
+ if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterAllowed()) {
+ shouldAutoPip = true;
+ } else if (!lastResumedCanPip) {
pauseImmediately = true;
+ } else {
+ // The previous activity may still enter PIP even though it did not allow auto-PIP.
}
}
+ boolean didAutoPip = false;
if (prev.attachedToProcess()) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
- try {
- EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
- prev.shortComponentName, "userLeaving=" + userLeaving);
-
- mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
- prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
- prev.configChangeFlags, pauseImmediately));
- } catch (Exception e) {
- // Ignore exception, if process died other code will cleanup.
- Slog.w(TAG, "Exception thrown during pause", e);
+ if (shouldAutoPip) {
+ if (DEBUG_PAUSE) {
+ Slog.d(TAG_PAUSE, "Auto-PIP allowed, entering PIP mode directly: " + prev);
+ }
+ didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
mPausingActivity = null;
- mLastPausedActivity = null;
- mLastNoHistoryActivity = null;
+ } else {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
+ try {
+ EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
+ prev.shortComponentName, "userLeaving=" + userLeaving);
+
+ mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
+ prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
+ prev.configChangeFlags, pauseImmediately));
+ } catch (Exception e) {
+ // Ignore exception, if process died other code will cleanup.
+ Slog.w(TAG, "Exception thrown during pause", e);
+ mPausingActivity = null;
+ mLastPausedActivity = null;
+ mLastNoHistoryActivity = null;
+ }
}
} else {
mPausingActivity = null;
@@ -5468,6 +5482,11 @@ class Task extends WindowContainer<WindowContainer> {
mStackSupervisor.acquireLaunchWakelock();
}
+ if (didAutoPip) {
+ // Already entered PIP mode, no need to keep pausing.
+ return true;
+ }
+
if (mPausingActivity != null) {
// Have the window manager pause its key dispatching until the new
// activity has started. If we're pausing the activity just because
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 19179a808d7c..017747f03ca0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1410,7 +1410,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (!displayContent.hasAccess(session.mUid)) {
ProtoLog.w(WM_ERROR,
"Attempted to add window to a display for which the application "
- + "does not have access: %d. Aborting.", displayId);
+ + "does not have access: %d. Aborting.",
+ displayContent.getDisplayId());
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 6cd083e11754..f4c6918c0e96 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -67,7 +67,6 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.IActivityManager;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
@@ -87,6 +86,7 @@ import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.SystemClock;
+import android.provider.DeviceConfig;
import androidx.test.runner.AndroidJUnit4;
@@ -99,6 +99,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoSession;
@@ -106,6 +107,8 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;
+import java.util.concurrent.Executor;
+
/**
* Tests for {@link com.android.server.DeviceIdleController}.
*/
@@ -124,8 +127,6 @@ public class DeviceIdleControllerTest {
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
- private ContentResolver mContentResolver;
- @Mock
private IActivityManager mIActivityManager;
@Mock
private LocationManager mLocationManager;
@@ -294,6 +295,7 @@ public class DeviceIdleControllerTest {
mMockingSession = mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
+ .spyStatic(DeviceConfig.class)
.spyStatic(LocalServices.class)
.startMocking();
spyOn(getContext());
@@ -310,6 +312,14 @@ public class DeviceIdleControllerTest {
.thenReturn(mock(PowerSaveState.class));
doReturn(mock(NetworkPolicyManagerInternal.class))
.when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class));
+ doAnswer((Answer<Void>) invocationOnMock -> null)
+ .when(() -> DeviceConfig.addOnPropertiesChangedListener(
+ anyString(), any(Executor.class),
+ any(DeviceConfig.OnPropertiesChangedListener.class)));
+ doAnswer((Answer<DeviceConfig.Properties>) invocationOnMock
+ -> mock(DeviceConfig.Properties.class))
+ .when(() -> DeviceConfig.getProperties(
+ anyString(), ArgumentMatchers.<String>any()));
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
doNothing().when(mWakeLock).acquire();
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
@@ -319,7 +329,6 @@ public class DeviceIdleControllerTest {
mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
mAnyMotionDetector = new AnyMotionDetectorForTest();
mInjector = new InjectorForTest(getContext());
- doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any());
mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
spyOn(mDeviceIdleController);
@@ -330,8 +339,7 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.setLightEnabledForTest(true);
// Get the same Constants object that mDeviceIdleController got.
- mConstants = mInjector.getConstants(mDeviceIdleController,
- mInjector.getHandler(mDeviceIdleController), mContentResolver);
+ mConstants = mInjector.getConstants(mDeviceIdleController);
}
@After
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
index d6894cf2a4e8..80ad0a838bbb 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -274,60 +274,55 @@ public class LocationProviderManagerTest {
@Test
public void testGetLastLocation_Fine() {
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
Location loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
}
@Test
public void testGetLastLocation_Coarse() {
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
Location loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- Location coarse = mManager.getLastLocation(request, IDENTITY, PERMISSION_COARSE);
+ Location coarse = mManager.getLastLocation(IDENTITY, PERMISSION_COARSE, false);
assertThat(coarse).isNotEqualTo(loc);
assertThat(coarse).isNearby(loc, 5000);
}
@Test
public void testGetLastLocation_Bypass() {
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
- LocationRequest bypassRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
- false).setLocationSettingsIgnored(true);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isNull();
Location loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
loc);
mProvider.setProviderAllowed(false);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
loc);
loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
loc);
mProvider.setProviderAllowed(true);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
loc);
loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
- assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, true)).isEqualTo(
loc);
}
@@ -337,13 +332,12 @@ public class LocationProviderManagerTest {
mockProvider.setAllowed(true);
mManager.setMockProvider(mockProvider);
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
Location loc = createLocation(NAME, mRandom);
mockProvider.setProviderLocation(loc);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
mManager.setMockProvider(null);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isNull();
}
@Test
@@ -351,13 +345,12 @@ public class LocationProviderManagerTest {
Location loc1 = createLocation(NAME, mRandom);
mManager.injectLastLocation(loc1, CURRENT_USER);
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc1);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1);
Location loc2 = createLocation(NAME, mRandom);
mManager.injectLastLocation(loc2, CURRENT_USER);
- assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc1);
+ assertThat(mManager.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc1);
}
@Test
@@ -381,9 +374,7 @@ public class LocationProviderManagerTest {
Location loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(PASSIVE_PROVIDER, 0,
- 0, false);
- assertThat(mPassive.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
+ assertThat(mPassive.getLastLocation(IDENTITY, PERMISSION_FINE, false)).isEqualTo(loc);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
index 609af8d5bf4d..8d706cb960e9 100644
--- a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
+++ b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java
@@ -79,6 +79,23 @@ public class NoOpAudioSystemAdapter extends AudioSystemAdapter {
}
@Override
+ public int setDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int removeDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devicesToRemove) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
+ public int clearDevicesRoleForCapturePreset(int capturePreset, int role) {
+ return AudioSystem.AUDIO_STATUS_OK;
+ }
+
+ @Override
public int setParameters(String keyValuePairs) {
return AudioSystem.AUDIO_STATUS_OK;
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index b1f3871274ac..73dda0736d2f 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -19,6 +19,7 @@ package com.android.server.display;
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -28,18 +29,23 @@ import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Rect;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.InputManagerInternal;
import android.os.Handler;
import android.os.IBinder;
import android.view.Display;
+import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -282,6 +288,68 @@ public class DisplayManagerServiceTest {
}
/**
+ * Tests that there should be a display change notification to WindowManager to update its own
+ * internal state for things like display cutout when nonOverrideDisplayInfo is changed.
+ */
+ @Test
+ public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+
+ // Add the FakeDisplayDevice
+ FakeDisplayDevice displayDevice = new FakeDisplayDevice();
+ DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
+ displayDeviceInfo.width = 100;
+ displayDeviceInfo.height = 200;
+ final Rect zeroRect = new Rect();
+ displayDeviceInfo.displayCutout = new DisplayCutout(
+ Insets.of(0, 10, 0, 0),
+ zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
+ displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY;
+ displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
+ displayManager.handleDisplayDeviceAdded(displayDevice);
+
+ // Find the display id of the added FakeDisplayDevice
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
+ final int[] displayIds = bs.getDisplayIds();
+ assertTrue(displayIds.length > 0);
+ int displayId = Display.INVALID_DISPLAY;
+ for (int i = 0; i < displayIds.length; i++) {
+ DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]);
+ if (displayDeviceInfo.equals(ddi)) {
+ displayId = displayIds[i];
+ break;
+ }
+ }
+ assertFalse(displayId == Display.INVALID_DISPLAY);
+
+ // Setup override DisplayInfo
+ DisplayInfo overrideInfo = bs.getDisplayInfo(displayId);
+ displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo);
+
+ Handler handler = displayManager.getDisplayHandler();
+ handler.runWithScissors(() -> {
+ }, 0 /* now */);
+
+ // register display listener callback
+ FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
+ bs.registerCallback(callback);
+
+ // Simulate DisplayDevice change
+ DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
+ displayDeviceInfo2.copyFrom(displayDeviceInfo);
+ displayDeviceInfo2.displayCutout = null;
+ displayDevice.setDisplayDeviceInfo(displayDeviceInfo2);
+ displayManager.handleDisplayDeviceChanged(displayDevice);
+
+ handler.runWithScissors(() -> {
+ }, 0 /* now */);
+ assertTrue(callback.mCalled);
+ }
+
+ /**
* Tests that we get a Runtime exception when we cannot initialize the default display.
*/
@Test
@@ -512,4 +580,42 @@ public class DisplayManagerServiceTest {
// flush the handler
handler.runWithScissors(() -> {}, 0 /* now */);
}
+
+ private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub {
+ int mDisplayId;
+ boolean mCalled = false;
+
+ FakeDisplayManagerCallback(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ @Override
+ public void onDisplayEvent(int displayId, int event) {
+ if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
+ mCalled = true;
+ }
+ }
+ }
+
+ private class FakeDisplayDevice extends DisplayDevice {
+ private DisplayDeviceInfo mDisplayDeviceInfo;
+
+ FakeDisplayDevice() {
+ super(null, null, "");
+ }
+
+ public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
+ mDisplayDeviceInfo = displayDeviceInfo;
+ }
+
+ @Override
+ public boolean hasStableUniqueId() {
+ return false;
+ }
+
+ @Override
+ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
+ return mDisplayDeviceInfo;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 3f324a279270..0c35797b38ea 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -697,7 +697,8 @@ public class HdmiCecLocalDevicePlaybackTest {
public void sendVolumeKeyEvent_toTv_activeSource() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiControlService.setSystemAudioActivated(false);
- mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress);
+ mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress,
+ "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
@@ -716,7 +717,8 @@ public class HdmiCecLocalDevicePlaybackTest {
public void sendVolumeKeyEvent_toAudio_activeSource() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiControlService.setSystemAudioActivated(true);
- mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress);
+ mHdmiControlService.setActiveSource(mPlaybackLogicalAddress, mPlaybackPhysicalAddress,
+ "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
@@ -735,7 +737,7 @@ public class HdmiCecLocalDevicePlaybackTest {
public void sendVolumeKeyEvent_toTv_inactiveSource() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiControlService.setSystemAudioActivated(false);
- mHdmiControlService.setActiveSource(ADDR_TV, 0x0000);
+ mHdmiControlService.setActiveSource(ADDR_TV, 0x0000, "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
@@ -754,7 +756,7 @@ public class HdmiCecLocalDevicePlaybackTest {
public void sendVolumeKeyEvent_toAudio_inactiveSource() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiControlService.setSystemAudioActivated(true);
- mHdmiControlService.setActiveSource(ADDR_TV, 0x0000);
+ mHdmiControlService.setActiveSource(ADDR_TV, 0x0000, "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 775e88750cef..31cf59ee7bde 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -63,7 +63,7 @@ import java.util.ArrayList;
@RunWith(JUnit4.class)
public class HdmiControlServiceTest {
- private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDevice {
+ private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDeviceSource {
private boolean mCanGoToStandby;
private boolean mIsStandby;
@@ -405,6 +405,83 @@ public class HdmiControlServiceTest {
assertThat(callback2.mVolumeControlEnabled).isTrue();
}
+ @Test
+ public void setActiveSource_localDevice_playback() {
+ int physicalAddress = 0x1000;
+ mNativeWrapper.setPhysicalAddress(physicalAddress);
+
+ mHdmiControlService.setActiveSource(mMyPlaybackDevice.mAddress, physicalAddress,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ mMyPlaybackDevice.mAddress);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ physicalAddress);
+ assertThat(mMyPlaybackDevice.mIsActiveSource).isTrue();
+ assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_localDevice_audio() {
+ int physicalAddress = 0x1000;
+ mNativeWrapper.setPhysicalAddress(physicalAddress);
+
+ mHdmiControlService.setActiveSource(mMyAudioSystemDevice.mAddress, physicalAddress,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ mMyAudioSystemDevice.mAddress);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ physicalAddress);
+ assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
+ assertThat(mMyAudioSystemDevice.mIsActiveSource).isTrue();
+ }
+
+ @Test
+ public void setActiveSource_remoteDevice() {
+ int physicalAddress = 0x1000;
+ mNativeWrapper.setPhysicalAddress(physicalAddress);
+
+ mHdmiControlService.setActiveSource(Constants.ADDR_TV, 0x0000, "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_TV);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x000);
+ assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
+ assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_nonCecDevice() {
+ int physicalAddress = 0x1000;
+ mNativeWrapper.setPhysicalAddress(physicalAddress);
+
+ mHdmiControlService.setActiveSource(Constants.ADDR_INVALID, 0x1234,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_INVALID);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x1234);
+ assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
+ assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_unknown() {
+ int physicalAddress = 0x1000;
+ mNativeWrapper.setPhysicalAddress(physicalAddress);
+
+ mHdmiControlService.setActiveSource(Constants.ADDR_INVALID,
+ Constants.INVALID_PHYSICAL_ADDRESS, "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_INVALID);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ Constants.INVALID_PHYSICAL_ADDRESS);
+ assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
+ assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
+ }
+
private static class VolumeControlFeatureCallback extends
IHdmiCecVolumeControlFeatureListener.Stub {
boolean mCallbackReceived = false;
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 7c7b1a296673..2aeab209162a 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -139,10 +139,13 @@ public class AppStandbyControllerTests {
private AppStandbyController mController;
private CountDownLatch mStateChangedLatch = new CountDownLatch(1);
+ private String mLatchPkgName = null;
private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() {
@Override
public void onAppIdleStateChanged(String packageName, int userId,
boolean idle, int bucket, int reason) {
+ // Ignore events not related to mLatchPkgName, if set.
+ if (mLatchPkgName != null && !mLatchPkgName.equals(packageName)) return;
mStateChangedLatch.countDown();
}
};
@@ -374,6 +377,7 @@ public class AppStandbyControllerTests {
mInjector.mElapsedRealtime, false));
controller.addListener(mListener);
+ mLatchPkgName = null;
return controller;
}
@@ -1377,7 +1381,7 @@ public class AppStandbyControllerTests {
@Test
public void testUnexemptedSyncScheduled() throws Exception {
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.addListener(mListener);
assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER,
getStandbyBucket(mController, PACKAGE_1));
@@ -1389,7 +1393,7 @@ public class AppStandbyControllerTests {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Unexempted sync scheduled should not elevate a non Never bucket",
@@ -1400,7 +1404,7 @@ public class AppStandbyControllerTests {
public void testExemptedSyncScheduled() throws Exception {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
mInjector.mDeviceIdleMode = true;
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled in doze should set bucket to working set",
@@ -1408,7 +1412,7 @@ public class AppStandbyControllerTests {
setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM);
mInjector.mDeviceIdleMode = false;
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(PACKAGE_1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled while not in doze should set bucket to active",
@@ -1558,10 +1562,19 @@ public class AppStandbyControllerTests {
}
private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception {
- mStateChangedLatch = new CountDownLatch(1);
+ rearmLatch(pkg);
mController.setAppStandbyBucket(pkg, user, bucket, reason);
mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
assertEquals("Failed to set package bucket", bucket,
getStandbyBucket(mController, PACKAGE_1));
}
+
+ private void rearmLatch(String pkgName) {
+ mLatchPkgName = pkgName;
+ mStateChangedLatch = new CountDownLatch(1);
+ }
+
+ private void rearmLatch() {
+ rearmLatch(null);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2d834ac57f51..94e40413f9f8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -26,8 +26,6 @@ import static android.view.InsetsState.ITYPE_TOP_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
-import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -36,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -371,6 +370,24 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
@Test
+ public void layoutWindowLw_insetParentFrameByIme() {
+ final InsetsState state =
+ mDisplayContent.getInsetsStateController().getRawInsetsState();
+ state.getSource(InsetsState.ITYPE_IME).setVisible(true);
+ state.getSource(InsetsState.ITYPE_IME).setFrame(
+ 0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+ mWindow.mBehindIme = true;
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, IME_HEIGHT);
+ }
+
+ @Test
public void layoutWindowLw_fitDisplayCutout() {
addDisplayCutout();
@@ -475,7 +492,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
mWindow.mAttrs.setFitInsetsTypes(
mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
addWindow(mWindow);
@@ -497,9 +513,9 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+ mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
addWindow(mWindow);
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -519,9 +535,9 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_FULLSCREEN;
mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
+ mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
addWindow(mWindow);
@@ -585,7 +601,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
mWindow.mAttrs.setFitInsetsTypes(
mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
addWindow(mWindow);
@@ -626,7 +641,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
mWindow.mAttrs.setFitInsetsTypes(
mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index b4e1c375993d..af8cb02a86fe 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -62,7 +62,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
static final int STATUS_BAR_HEIGHT = 10;
static final int NAV_BAR_HEIGHT = 15;
static final int DISPLAY_CUTOUT_HEIGHT = 8;
- static final int INPUT_METHOD_WINDOW_TOP = 585;
+ static final int IME_HEIGHT = 415;
DisplayPolicy mDisplayPolicy;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 6c648a894821..468b2c35ffc2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -35,7 +35,9 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -216,22 +218,50 @@ public class SizeCompatTests extends WindowTestsBase {
final Rect origBounds = new Rect(mActivity.getBounds());
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
+ final DisplayContent display = mActivity.mDisplayContent;
// Change the size of current display.
- resizeDisplay(mStack.mDisplayContent, 1000, 2000);
-
+ resizeDisplay(display, 1000, 2000);
+ // The bounds should be [100, 0 - 1100, 2500].
assertEquals(origBounds.width(), currentBounds.width());
assertEquals(origBounds.height(), currentBounds.height());
assertScaled();
+ // The scale is 2000/2500=0.8. The horizontal centered offset is (1000-(1000*0.8))/2=100.
+ final float scale = (float) display.mBaseDisplayHeight / currentBounds.height();
+ final int offsetX = (int) (display.mBaseDisplayWidth - (origBounds.width() * scale)) / 2;
+ assertEquals(offsetX, currentBounds.left);
+
// The position of configuration bounds should be the same as compat bounds.
assertEquals(mActivity.getBounds().left, currentBounds.left);
assertEquals(mActivity.getBounds().top, currentBounds.top);
// Change display size to a different orientation
- resizeDisplay(mStack.mDisplayContent, 2000, 1000);
+ resizeDisplay(display, 2000, 1000);
+ // The bounds should be [800, 0 - 1800, 2500].
assertEquals(origBounds.width(), currentBounds.width());
assertEquals(origBounds.height(), currentBounds.height());
+ assertEquals(Configuration.ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
+ assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
+
+ // The previous resize operation doesn't consider the rotation change after size changed.
+ // These setups apply the requested orientation to rotation as real case that the top fixed
+ // portrait activity will determine the display rotation.
+ final DisplayRotation displayRotation = display.getDisplayRotation();
+ doCallRealMethod().when(displayRotation).updateRotationUnchecked(anyBoolean());
+ // Skip unrelated layout procedures.
+ mAtm.deferWindowLayout();
+ display.reconfigureDisplayLocked();
+ displayRotation.updateOrientation(display.getOrientation(), true /* forceUpdate */);
+ display.sendNewConfiguration();
+
+ assertEquals(Configuration.ORIENTATION_PORTRAIT, display.getConfiguration().orientation);
+ assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
+ // The size should still be in portrait [100, 0 - 1100, 2500] = 1000x2500.
+ assertEquals(origBounds.width(), currentBounds.width());
+ assertEquals(origBounds.height(), currentBounds.height());
+ assertEquals(offsetX, currentBounds.left);
+ assertScaled();
}
@Test
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index 944edd542e40..72e11c867a2b 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -291,6 +291,22 @@ package android.telephony {
method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String);
}
+ public final class PhysicalChannelConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCellBandwidthDownlink();
+ method public int getChannelNumber();
+ method public int getConnectionStatus();
+ method public int getNetworkType();
+ method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
+ field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+ field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+ field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
+ }
+
public final class PreciseCallState implements android.os.Parcelable {
ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index af62ba4b93a1..8d49e15da934 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -17,6 +17,9 @@
package android.telephony;
import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
@@ -29,9 +32,11 @@ import java.util.Objects;
/**
* @hide
*/
+@SystemApi
public final class PhysicalChannelConfig implements Parcelable {
// TODO(b/72993578) consolidate these enums in a central location.
+ /** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
public @interface ConnectionStatus {}
@@ -47,7 +52,13 @@ public final class PhysicalChannelConfig implements Parcelable {
public static final int CONNECTION_SECONDARY_SERVING = 2;
/** Connection status is unknown. */
- public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
+ public static final int CONNECTION_UNKNOWN = -1;
+
+ /** Channel number is unknown. */
+ public static final int CHANNEL_NUMBER_UNKNOWN = -1;
+
+ /** Physical Cell Id is unknown. */
+ public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;
/**
* Connection status of the cell.
@@ -75,7 +86,7 @@ public final class PhysicalChannelConfig implements Parcelable {
private int mFrequencyRange;
/**
- * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown.
+ * The absolute radio frequency channel number, {@link CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
private int mChannelNumber;
@@ -86,7 +97,8 @@ public final class PhysicalChannelConfig implements Parcelable {
private int[] mContextIds;
/**
- * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known.
+ * The physical cell identifier for this cell - PCI, PSC, {@link PHYSICAL_CELL_ID_UNKNOWN}
+ * if unknown.
*/
private int mPhysicalCellId;
@@ -96,7 +108,7 @@ public final class PhysicalChannelConfig implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mCellConnectionStatus);
dest.writeInt(mCellBandwidthDownlinkKhz);
dest.writeInt(mRat);
@@ -120,6 +132,7 @@ public final class PhysicalChannelConfig implements Parcelable {
* physical channel has no data call mapped to it.
*
* @return an integer list indicates the data call ids.
+ * @hide
*/
public int[] getContextIds() {
return mContextIds;
@@ -131,6 +144,7 @@ public final class PhysicalChannelConfig implements Parcelable {
* @see {@link ServiceState#FREQUENCY_RANGE_MID}
* @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
* @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE}
+ * @hide
*/
@ServiceState.FrequencyRange
public int getFrequencyRange() {
@@ -139,7 +153,7 @@ public final class PhysicalChannelConfig implements Parcelable {
/**
* @return the absolute radio frequency channel number for this physical channel,
- * {@link Integer#MAX_VALUE} if unknown.
+ * {@link CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
public int getChannelNumber() {
return mChannelNumber;
@@ -152,18 +166,20 @@ public final class PhysicalChannelConfig implements Parcelable {
* In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
* Reference: 3GPP TS 36.211 section 6.11.
*
- * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008].
+ * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007].
* Reference: 3GPP TS 38.211 section 7.4.2.1.
*
- * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown.
+ * @return the physical cell identifier for this cell, {@link PHYSICAL_CELL_ID_UNKNOWN}
+ * if {@link android.telephony.CellInfo#UNAVAILABLE}.
*/
+ @IntRange(from = 0, to = 1007)
public int getPhysicalCellId() {
return mPhysicalCellId;
}
/**The radio technology for this physical channel. */
@NetworkType
- public int getRat() {
+ public int getNetworkType() {
return mRat;
}
@@ -181,7 +197,10 @@ public final class PhysicalChannelConfig implements Parcelable {
return mCellConnectionStatus;
}
- /** @return String representation of the connection status */
+ /**
+ * @return String representation of the connection status
+ * @hide
+ */
private String getConnectionStatusString() {
switch(mCellConnectionStatus) {
case CONNECTION_PRIMARY_SERVING:
@@ -254,6 +273,12 @@ public final class PhysicalChannelConfig implements Parcelable {
.toString();
}
+ /** @hide */
+ public PhysicalChannelConfig(int status, int bandwidth) {
+ mCellConnectionStatus = status;
+ mCellBandwidthDownlinkKhz = bandwidth;
+ }
+
private PhysicalChannelConfig(Parcel in) {
mCellConnectionStatus = in.readInt();
mCellBandwidthDownlinkKhz = in.readInt();
@@ -274,7 +299,10 @@ public final class PhysicalChannelConfig implements Parcelable {
mPhysicalCellId = builder.mPhysicalCellId;
}
- /** The builder of {@code PhysicalChannelConfig}. */
+ /**
+ * The builder of {@code PhysicalChannelConfig}.
+ * @hide
+ */
public static final class Builder {
private int mRat;
private int mFrequencyRange;
@@ -284,60 +312,51 @@ public final class PhysicalChannelConfig implements Parcelable {
private int[] mContextIds;
private int mPhysicalCellId;
- /** @hide */
public Builder() {
mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
- mChannelNumber = Integer.MAX_VALUE;
+ mChannelNumber = CHANNEL_NUMBER_UNKNOWN;
mCellBandwidthDownlinkKhz = 0;
mCellConnectionStatus = CONNECTION_UNKNOWN;
mContextIds = new int[0];
- mPhysicalCellId = Integer.MAX_VALUE;
+ mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
}
- /** @hide */
public PhysicalChannelConfig build() {
return new PhysicalChannelConfig(this);
}
- /** @hide */
public Builder setRat(int rat) {
this.mRat = rat;
return this;
}
- /** @hide */
public Builder setFrequencyRange(int frequencyRange) {
this.mFrequencyRange = frequencyRange;
return this;
}
- /** @hide */
public Builder setChannelNumber(int channelNumber) {
this.mChannelNumber = channelNumber;
return this;
}
- /** @hide */
public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
return this;
}
- /** @hide */
public Builder setCellConnectionStatus(int connectionStatus) {
this.mCellConnectionStatus = connectionStatus;
return this;
}
- /** @hide */
public Builder setContextIds(int[] contextIds) {
if (contextIds != null) Arrays.sort(contextIds);
this.mContextIds = contextIds;
return this;
}
- /** @hide */
public Builder setPhysicalCellId(int physicalCellId) {
this.mPhysicalCellId = physicalCellId;
return this;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 7a7792242c12..4ce9cb90b684 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5555,8 +5555,51 @@ public class TelephonyManager {
* @param events The telephony state(s) of interest to the listener,
* as a bitwise-OR combination of {@link PhoneStateListener}
* LISTEN_ flags.
+ * @deprecated use {@link #listen(long, PhoneStateListener) instead.
*/
+ @Deprecated
public void listen(PhoneStateListener listener, int events) {
+ listen(events, listener);
+ }
+
+ /**
+ * Since the limit of {@link PhoneStateListener} LISTEN_ flags is exceeded, use long type to
+ * extend it.
+ *
+ * Registers a listener object to receive notification of changes
+ * in specified telephony states.
+ * <p>
+ * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony
+ * state of interest in the events argument.
+ *
+ * At registration, and when a specified telephony state changes, the telephony manager invokes
+ * the appropriate callback method on the listener object and passes the current (updated)
+ * values.
+ * <p>
+ * To un-register a listener, pass the listener object and set the events argument to
+ * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
+ *
+ * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
+ * applies to the given subId. Otherwise, applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
+ * pass a separate listener object to each TelephonyManager object created with
+ * {@link #createForSubscriptionId}.
+ *
+ * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
+ * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
+ * {@link SecurityException} will be thrown otherwise.
+ *
+ * This API should be used sparingly -- large numbers of listeners will cause system
+ * instability. If a process has registered too many listeners without unregistering them, it
+ * may encounter an {@link IllegalStateException} when trying to register more listeners.
+ *
+ * @param events The telephony state(s) of interest to the listener,
+ * as a bitwise-OR combination of {@link PhoneStateListener}
+ * LISTEN_ flags.
+ * @param listener The {@link PhoneStateListener} object to register
+ * (or unregister)
+ */
+ public void listen(long events, @NonNull PhoneStateListener listener) {
if (mContext == null) return;
boolean notifyNow = (getITelephony() != null);
TelephonyRegistryManager telephonyRegistry =
diff --git a/tests/SilkFX/Android.bp b/tests/SilkFX/Android.bp
index ca0a091e65bb..92e3efa7fd55 100644
--- a/tests/SilkFX/Android.bp
+++ b/tests/SilkFX/Android.bp
@@ -19,4 +19,10 @@ android_test {
srcs: ["**/*.java", "**/*.kt"],
platform_apis: true,
certificate: "platform",
+ static_libs: [
+ "androidx.core_core",
+ "androidx.appcompat_appcompat",
+ "com.google.android.material_material",
+ "androidx-constraintlayout_constraintlayout",
+ ],
}
diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml
index ca9550a9eeab..050e9c33aeac 100644
--- a/tests/SilkFX/AndroidManifest.xml
+++ b/tests/SilkFX/AndroidManifest.xml
@@ -39,5 +39,8 @@
<activity android:name=".hdr.GlowActivity"
android:label="Glow Examples"/>
+ <activity android:name=".materials.GlassActivity"
+ android:label="Glass Examples"/>
+
</application>
</manifest>
diff --git a/tests/SilkFX/res/drawable-hdpi/background1.jpeg b/tests/SilkFX/res/drawable-hdpi/background1.jpeg
new file mode 100644
index 000000000000..dcdfa7b850bc
--- /dev/null
+++ b/tests/SilkFX/res/drawable-hdpi/background1.jpeg
Binary files differ
diff --git a/tests/SilkFX/res/drawable-hdpi/background2.jpeg b/tests/SilkFX/res/drawable-hdpi/background2.jpeg
new file mode 100644
index 000000000000..dc7ce84e6784
--- /dev/null
+++ b/tests/SilkFX/res/drawable-hdpi/background2.jpeg
Binary files differ
diff --git a/tests/SilkFX/res/drawable-hdpi/background3.jpeg b/tests/SilkFX/res/drawable-hdpi/background3.jpeg
new file mode 100644
index 000000000000..12b3429e3920
--- /dev/null
+++ b/tests/SilkFX/res/drawable-hdpi/background3.jpeg
Binary files differ
diff --git a/tests/SilkFX/res/drawable-hdpi/noise.png b/tests/SilkFX/res/drawable-hdpi/noise.png
new file mode 100644
index 000000000000..053995dad760
--- /dev/null
+++ b/tests/SilkFX/res/drawable-hdpi/noise.png
Binary files differ
diff --git a/tests/SilkFX/res/layout/activity_glass.xml b/tests/SilkFX/res/layout/activity_glass.xml
new file mode 100644
index 000000000000..a7b76bdeba09
--- /dev/null
+++ b/tests/SilkFX/res/layout/activity_glass.xml
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2012, 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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+
+ <ImageView
+ android:id="@+id/background"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:scaleType="matrix"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ tools:srcCompat="@drawable/background1" />
+
+ <com.android.test.silkfx.materials.GlassView
+ android:id="@+id/materialView"
+ android:layout_width="0dp"
+ android:layout_height="180dp"
+ android:layout_marginEnd="64dp"
+ android:layout_marginStart="64dp"
+ app:layout_constraintBottom_toTopOf="@+id/bottomPanel"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/bottomPanel"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorBackground"
+ android:paddingTop="24dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent">
+
+ <SeekBar
+ android:id="@+id/materialOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="16dp"
+ android:max="100"
+ android:progress="12"
+ app:layout_constraintBottom_toTopOf="@+id/scrimOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/zoom"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginStart="12dp"
+ android:min="-100"
+ android:max="100"
+ android:progress="-15"
+ app:layout_constraintBottom_toTopOf="@+id/blurRadiusTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/blurRadius"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginStart="12dp"
+ android:max="150"
+ android:progress="20"
+ app:layout_constraintBottom_toTopOf="@+id/materialOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/scrimOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="16dp"
+ android:max="100"
+ android:progress="50"
+ app:layout_constraintBottom_toTopOf="@+id/noiseOpacityTitle"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <SeekBar
+ android:id="@+id/noiseOpacity"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:layout_marginBottom="24dp"
+ android:max="100"
+ android:progress="5"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/scrimOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Scrim Opacity"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/scrimOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/materialOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Material Opacity"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/materialOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/zoomTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Zoom"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/zoom"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/blurRadiusTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Blur Radius"
+ android:textColor="@android:color/white"
+ app:layout_constraintBottom_toTopOf="@+id/blurRadius"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/noiseOpacityTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:textColor="@android:color/white"
+ android:text="Noise Opacity"
+ app:layout_constraintBottom_toTopOf="@+id/noiseOpacity"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <ImageView
+ android:id="@+id/background1"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="16dp"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ android:scaleType="centerCrop"
+ app:layout_constraintBottom_toTopOf="@+id/lightMaterialSwitch"
+ app:layout_constraintStart_toStartOf="parent"
+ android:src="@drawable/background1" />
+
+ <ImageView
+ android:id="@+id/background2"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ android:scaleType="centerCrop"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background1"
+ android:src="@drawable/background2" />
+
+ <ImageView
+ android:id="@+id/background3"
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:layout_marginStart="8dp"
+ android:scaleType="centerCrop"
+ android:foreground="?android:attr/selectableItemBackgroundBorderless"
+ android:clickable="true"
+ android:onClick="onBackgroundClick"
+ app:layout_constraintBottom_toBottomOf="@+id/background1"
+ app:layout_constraintStart_toEndOf="@+id/background2"
+ android:src="@drawable/background3" />
+
+ <Switch
+ android:id="@+id/lightMaterialSwitch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dp"
+ android:layout_marginBottom="8dp"
+ android:text="Light Material"
+ app:layout_constraintBottom_toTopOf="@+id/zoomTitle"
+ app:layout_constraintStart_toStartOf="parent" />
+
+ <TextView
+ android:id="@+id/blurRadiusValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/blurRadiusTitle"
+ app:layout_constraintStart_toEndOf="@+id/blurRadiusTitle" />
+
+ <TextView
+ android:id="@+id/zoomValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/zoomTitle"
+ app:layout_constraintStart_toEndOf="@+id/zoomTitle" />
+
+ <TextView
+ android:id="@+id/materialOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/materialOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/materialOpacityTitle" />
+
+ <TextView
+ android:id="@+id/noiseOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/noiseOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/noiseOpacityTitle" />
+
+
+ <TextView
+ android:id="@+id/scrimOpacityValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="TextView"
+ android:layout_marginLeft="8dp"
+ app:layout_constraintBottom_toBottomOf="@+id/scrimOpacityTitle"
+ app:layout_constraintStart_toEndOf="@+id/scrimOpacityTitle" />
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
index 76e62a6c8cff..9ed8d2f5edf7 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -29,6 +29,7 @@ import com.android.test.silkfx.app.CommonDemoActivity
import com.android.test.silkfx.app.EXTRA_LAYOUT
import com.android.test.silkfx.app.EXTRA_TITLE
import com.android.test.silkfx.hdr.GlowActivity
+import com.android.test.silkfx.materials.GlassActivity
import kotlin.reflect.KClass
class Demo(val name: String, val makeIntent: (Context) -> Intent) {
@@ -48,6 +49,9 @@ private val AllDemos = listOf(
DemoGroup("HDR", listOf(
Demo("Glow", GlowActivity::class),
Demo("Blingy Notifications", R.layout.bling_notifications)
+ )),
+ DemoGroup("Materials", listOf(
+ Demo("Glass", GlassActivity::class)
))
)
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt
new file mode 100644
index 000000000000..72b342c54d19
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.silkfx.materials
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.os.Bundle
+import android.util.TypedValue
+import android.view.View
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.Switch
+import android.widget.TextView
+import com.android.test.silkfx.R
+
+class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener {
+
+ lateinit var backgroundButton1: ImageView
+ lateinit var backgroundButton2: ImageView
+ lateinit var backgroundButton3: ImageView
+ lateinit var backgroundView: ImageView
+ lateinit var materialView: GlassView
+ lateinit var lightMaterialSwitch: Switch
+ lateinit var noiseOpacitySeekBar: SeekBar
+ lateinit var materialOpacitySeekBar: SeekBar
+ lateinit var scrimOpacitySeekBar: SeekBar
+ lateinit var zoomSeekBar: SeekBar
+ lateinit var blurRadiusSeekBar: SeekBar
+ lateinit var noiseOpacityValue: TextView
+ lateinit var materialOpacityValue: TextView
+ lateinit var scrimOpacityValue: TextView
+ lateinit var blurRadiusValue: TextView
+ lateinit var zoomValue: TextView
+
+ lateinit var background: Bitmap
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_glass)
+ backgroundButton1 = requireViewById(R.id.background1)
+ backgroundButton2 = requireViewById(R.id.background2)
+ backgroundButton3 = requireViewById(R.id.background3)
+ backgroundView = requireViewById(R.id.background)
+ lightMaterialSwitch = requireViewById(R.id.lightMaterialSwitch)
+ materialView = requireViewById(R.id.materialView)
+ materialOpacitySeekBar = requireViewById(R.id.materialOpacity)
+ blurRadiusSeekBar = requireViewById(R.id.blurRadius)
+ zoomSeekBar = requireViewById(R.id.zoom)
+ noiseOpacitySeekBar = requireViewById(R.id.noiseOpacity)
+ scrimOpacitySeekBar = requireViewById(R.id.scrimOpacity)
+ noiseOpacityValue = requireViewById(R.id.noiseOpacityValue)
+ materialOpacityValue = requireViewById(R.id.materialOpacityValue)
+ scrimOpacityValue = requireViewById(R.id.scrimOpacityValue)
+ blurRadiusValue = requireViewById(R.id.blurRadiusValue)
+ zoomValue = requireViewById(R.id.zoomValue)
+
+ background = BitmapFactory.decodeResource(resources, R.drawable.background1)
+ backgroundView.setImageBitmap(background)
+ materialView.backgroundBitmap = background
+
+ blurRadiusSeekBar.setOnSeekBarChangeListener(this)
+ materialOpacitySeekBar.setOnSeekBarChangeListener(this)
+ noiseOpacitySeekBar.setOnSeekBarChangeListener(this)
+ scrimOpacitySeekBar.setOnSeekBarChangeListener(this)
+
+ arrayOf(blurRadiusSeekBar, materialOpacitySeekBar, noiseOpacitySeekBar,
+ scrimOpacitySeekBar, zoomSeekBar).forEach {
+ it.setOnSeekBarChangeListener(this)
+ onProgressChanged(it, it.progress, fromUser = false)
+ }
+
+ lightMaterialSwitch.setOnCheckedChangeListener { _, isChecked ->
+ materialView.color = if (isChecked) Color.WHITE else Color.BLACK
+ }
+ }
+
+ override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+ when (seekBar) {
+ blurRadiusSeekBar -> {
+ materialView.blurRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ progress.toFloat(), resources.displayMetrics)
+ blurRadiusValue.text = progress.toString()
+ }
+ materialOpacitySeekBar -> {
+ materialView.materialOpacity = progress / seekBar.max.toFloat()
+ materialOpacityValue.text = progress.toString()
+ }
+ noiseOpacitySeekBar -> {
+ materialView.noiseOpacity = progress / seekBar.max.toFloat()
+ noiseOpacityValue.text = progress.toString()
+ }
+ scrimOpacitySeekBar -> {
+ materialView.scrimOpacity = progress / seekBar.max.toFloat()
+ scrimOpacityValue.text = progress.toString()
+ }
+ zoomSeekBar -> {
+ materialView.zoom = progress / seekBar.max.toFloat()
+ zoomValue.text = progress.toString()
+ }
+ else -> throw IllegalArgumentException("Unknown seek bar")
+ }
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar?) {}
+ override fun onStopTrackingTouch(seekBar: SeekBar?) {}
+
+ fun onBackgroundClick(view: View) {
+ val resource = when (view) {
+ backgroundButton1 -> R.drawable.background1
+ backgroundButton2 -> R.drawable.background2
+ backgroundButton3 -> R.drawable.background3
+ else -> throw IllegalArgumentException("Invalid button")
+ }
+
+ background = BitmapFactory.decodeResource(resources, resource)
+ backgroundView.setImageBitmap(background)
+ materialView.backgroundBitmap = background
+ }
+} \ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt
new file mode 100644
index 000000000000..60797680b79e
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.silkfx.materials
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.BitmapShader
+import android.graphics.BlendMode
+import android.graphics.BlurShader
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Outline
+import android.graphics.Paint
+import android.graphics.Rect
+import android.graphics.Shader
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewOutlineProvider
+import com.android.test.silkfx.R
+
+class GlassView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) {
+
+ var noise = BitmapFactory.decodeResource(resources, R.drawable.noise)
+ var materialPaint = Paint()
+ var scrimPaint = Paint()
+ var noisePaint = Paint()
+ var blurPaint = Paint()
+
+ val src = Rect()
+ val dst = Rect()
+
+ var backgroundBitmap: Bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+ set(value) {
+ field = value
+ invalidate()
+ }
+
+ var noiseOpacity = 0.0f
+ set(value) {
+ field = value
+ noisePaint.alpha = (value * 255).toInt()
+ invalidate()
+ }
+
+ var materialOpacity = 0.0f
+ set(value) {
+ field = value
+ materialPaint.alpha = (value * 255).toInt()
+ invalidate()
+ }
+
+ var scrimOpacity = 0.5f
+ set(value) {
+ field = value
+ scrimPaint.alpha = (value * 255).toInt()
+ invalidate()
+ }
+
+ var zoom = 0.0f
+ set(value) {
+ field = value
+ invalidate()
+ }
+
+ var color = Color.BLACK
+ set(value) {
+ field = value
+ var alpha = materialPaint.alpha
+ materialPaint.color = color
+ materialPaint.alpha = alpha
+
+ alpha = scrimPaint.alpha
+ scrimPaint.color = color
+ scrimPaint.alpha = alpha
+ invalidate()
+ }
+
+ var blurRadius = 150f
+ set(value) {
+ field = value
+ blurPaint.shader = BlurShader(value, value, null)
+ invalidate()
+ }
+
+ init {
+ materialPaint.blendMode = BlendMode.SOFT_LIGHT
+ noisePaint.blendMode = BlendMode.SOFT_LIGHT
+ noisePaint.shader = BitmapShader(noise, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
+ scrimPaint.alpha = (scrimOpacity * 255).toInt()
+ noisePaint.alpha = (noiseOpacity * 255).toInt()
+ materialPaint.alpha = (materialOpacity * 255).toInt()
+ blurPaint.shader = BlurShader(blurRadius, blurRadius, null)
+ outlineProvider = object : ViewOutlineProvider() {
+ override fun getOutline(view: View?, outline: Outline?) {
+ outline?.setRoundRect(Rect(0, 0, width, height), 100f)
+ }
+ }
+ clipToOutline = true
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ src.set(-width/2, -height/2, width/2, height/2)
+ src.scale(1.0f + zoom)
+ val centerX = left + width / 2
+ val centerY = top + height / 2
+ src.set(src.left + centerX, src.top + centerY, src.right + centerX, src.bottom + centerY)
+
+ dst.set(0, 0, width, height)
+ canvas?.drawBitmap(backgroundBitmap, src, dst, blurPaint)
+ canvas?.drawRect(dst, materialPaint)
+ canvas?.drawRect(dst, noisePaint)
+ canvas?.drawRect(dst, scrimPaint)
+ }
+} \ No newline at end of file
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index b104decab73c..ae9b5ab07851 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -579,6 +579,7 @@ package android.net.wifi.aware {
method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession);
method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int);
+ method public void onServiceLost(@NonNull android.net.wifi.aware.PeerHandle);
method public void onSessionConfigFailed();
method public void onSessionConfigUpdated();
method public void onSessionTerminated();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 77fa673f1960..90edc4523b7b 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -30,6 +30,9 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.ECParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1442,4 +1445,50 @@ public class WifiEnterpriseConfig implements Parcelable {
}
return TextUtils.isEmpty(getCaPath());
}
+
+ /**
+ * Check if a given certificate Get the Suite-B cipher from the certificate
+ *
+ * @param x509Certificate Certificate to process
+ * @return true if the certificate OID matches the Suite-B requirements for RSA or ECDSA
+ * certificates, or false otherwise.
+ * @hide
+ */
+ public static boolean isSuiteBCipherCert(@Nullable X509Certificate x509Certificate) {
+ if (x509Certificate == null) {
+ return false;
+ }
+ final String sigAlgOid = x509Certificate.getSigAlgOID();
+
+ // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
+ // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
+ // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
+ // Suite-B was already coined in the IEEE 802.11-2016 specification for
+ // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
+ // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
+ // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
+ // we are supporting both types here.
+ if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
+ // sha384WithRSAEncryption
+ if (x509Certificate.getPublicKey() instanceof RSAPublicKey) {
+ final RSAPublicKey rsaPublicKey = (RSAPublicKey) x509Certificate.getPublicKey();
+ if (rsaPublicKey.getModulus() != null
+ && rsaPublicKey.getModulus().bitLength() >= 3072) {
+ return true;
+ }
+ }
+ } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
+ // ecdsa-with-SHA384
+ if (x509Certificate.getPublicKey() instanceof ECPublicKey) {
+ final ECPublicKey ecPublicKey = (ECPublicKey) x509Certificate.getPublicKey();
+ final ECParameterSpec ecParameterSpec = ecPublicKey.getParams();
+
+ if (ecParameterSpec != null && ecParameterSpec.getOrder() != null
+ && ecParameterSpec.getOrder().bitLength() >= 384) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index b0213b0ef502..e12bb9178235 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -78,12 +78,12 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
private @Nullable String mWpa3SaePassphrase;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the WPA-EAP networks.
+ * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the SuiteB networks.
+ * certificates and other settings associated with the WPA3-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
@@ -243,7 +243,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA3-Enterprise networks (standard and 192-bit security). See
+ * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
+ * client and CA certificates must be provided, and must be of type of either
+ * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
+ * (OID 1.2.840.10045.4.3.3).
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -284,8 +288,25 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
} else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
- } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
+ if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getClientCertificate())
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getCaCertificate())) {
+ // WPA3-Enterprise in 192-bit security mode (Suite-B)
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else {
+ // WPA3-Enterprise
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ configuration.allowedPairwiseCiphers.set(
+ WifiConfiguration.PairwiseCipher.GCMP_256);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+ configuration.requirePmf = true;
+ }
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index e4e900ffe12a..aa699634dac4 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -72,12 +72,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
private @Nullable String mWpa3SaePassphrase;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the WPA-EAP networks.
+ * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the SuiteB networks.
+ * certificates and other settings associated with the WPA3-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
@@ -288,7 +288,11 @@ public final class WifiNetworkSuggestion implements Parcelable {
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA3 enterprise networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA3-Enterprise networks (standard and 192-bit security). See
+ * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
+ * client and CA certificates must be provided, and must be of type of either
+ * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
+ * (OID 1.2.840.10045.4.3.3).
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -570,8 +574,25 @@ public final class WifiNetworkSuggestion implements Parcelable {
} else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
- } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
+ if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getClientCertificate())
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getCaCertificate())) {
+ // WPA3-Enterprise in 192-bit security mode (Suite-B)
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else {
+ // WPA3-Enterprise
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ configuration.allowedPairwiseCiphers.set(
+ WifiConfiguration.PairwiseCipher.GCMP_256);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+ configuration.requirePmf = true;
+ }
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index bfb0462952b1..e3800ad6ef36 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -189,4 +189,16 @@ public class DiscoverySessionCallback {
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
/* empty */
}
+
+ /**
+ * Called when the discovered peer is no longer visible. All further operations on this
+ * discovery session will fail. If the peer is visible again,
+ * {@link #onServiceDiscovered(PeerHandle, byte[], List)} or
+ * {@link #onServiceDiscoveredWithinRange(PeerHandle, byte[], List, int)} will be called.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ */
+ public void onServiceLost(@NonNull PeerHandle peerHandle) {
+ /* empty */
+ }
}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
index 421a8af2073e..e3e7c8e6c747 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
@@ -35,4 +35,5 @@ oneway interface IWifiAwareDiscoverySessionCallback
void onMessageSendSuccess(int messageId);
void onMessageSendFail(int messageId, int reason);
void onMessageReceived(int peerId, in byte[] message);
+ void onMatchExpired(int peerId);
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index c2ae17c4bdeb..6352a2f4305c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -587,6 +587,7 @@ public class WifiAwareManager {
private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
private static final int CALLBACK_MESSAGE_RECEIVED = 7;
private static final int CALLBACK_MATCH_WITH_DISTANCE = 8;
+ private static final int CALLBACK_MATCH_EXPIRED = 9;
private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
@@ -676,6 +677,9 @@ public class WifiAwareManager {
mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
(byte[]) msg.obj);
break;
+ case CALLBACK_MATCH_EXPIRED:
+ mOriginalCallback
+ .onServiceLost(new PeerHandle(msg.arg1));
}
}
};
@@ -746,6 +750,15 @@ public class WifiAwareManager {
onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter,
distanceMm);
}
+ @Override
+ public void onMatchExpired(int peerId) {
+ if (VDBG) {
+ Log.v(TAG, "onMatchExpired: peerId=" + peerId);
+ }
+ Message msg = mHandler.obtainMessage(CALLBACK_MATCH_EXPIRED);
+ msg.arg1 = peerId;
+ mHandler.sendMessage(msg);
+ }
@Override
public void onMessageSendSuccess(int messageId) {
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
index 641b891a1f4d..8aa6add4a4e4 100644
--- a/wifi/tests/src/android/net/wifi/FakeKeys.java
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -212,7 +212,57 @@ public class FakeKeys {
(byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
(byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
};
- public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1);
+ public static final PrivateKey RSA_KEY1 = loadPrivateKey("RSA", FAKE_RSA_KEY_1);
+
+ private static final String CA_SUITE_B_RSA3072_CERT_STRING =
+ "-----BEGIN CERTIFICATE-----\n"
+ + "MIIEnTCCAwWgAwIBAgIUD87Y8fFLzLr1HQ/64aEnjNq2R/4wDQYJKoZIhvcNAQEM\n"
+ + "BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAO\n"
+ + "BgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0\n"
+ + "Q0EwHhcNMjAwNzIxMDIxNzU0WhcNMzAwNTMwMDIxNzU0WjBeMQswCQYDVQQGEwJV\n"
+ + "UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEO\n"
+ + "MAwGA1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTCCAaIwDQYJKoZIhvcN\n"
+ + "AQEBBQADggGPADCCAYoCggGBAMtrsT0otlxh0QS079KpRRbU1PQjCihSoltXnrxF\n"
+ + "sTWZs2weVEeYVyYU5LaauCDDgISCMtjtfbfylMBeYjpWB5hYzYQOiTzo0anWhMyb\n"
+ + "Ngb7gpMVZuIl6lwMYRyVRKwHWnTo2EUg1ZzW5rGe5fs/KHj6//hoNFm+3Oju0TQd\n"
+ + "nraQULpoERPF5B7p85Cssk8uNbviBfZXvtCuJ4N6w7PNceOY/9bbwc1mC+pPZmzV\n"
+ + "SOAg0vvbIQRzChm63C3jBC3xmxSOOZVrKN4zKDG2s8P0oCNGt0NlgRMrgbPRekzg\n"
+ + "4avkbA0vTuc2AyriTEYkdea/Mt4EpRg9XuOb43U/GJ/d/vQv2/9fsxhXmsZrn8kr\n"
+ + "Qo5MMHJFUd96GgHmvYSU3Mf/5r8gF626lvqHioGuTAuHUSnr02ri1WUxZ15LDRgY\n"
+ + "quMjDCFZfucjJPDAdtiHcFSej/4SLJlN39z8oKKNPn3aL9Gv49oAKs9S8tfDVzMk\n"
+ + "fDLROQFHFuW715GnnMgEAoOpRwIDAQABo1MwUTAdBgNVHQ4EFgQUeVuGmSVN4ARs\n"
+ + "mesUMWSJ2qWLbxUwHwYDVR0jBBgwFoAUeVuGmSVN4ARsmesUMWSJ2qWLbxUwDwYD\n"
+ + "VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEAit1Lo/hegZpPuT9dlWZJ\n"
+ + "bC8JvAf95O8lnn6LFb69pgYOHCLgCIlvYXu9rdBUJgZo+V1MzJJljiO6RxWRfKbQ\n"
+ + "8WBYkoqR1EqriR3Kn8q/SjIZCdFSaznTyU1wQMveBQ6RJWXSUhYVfE9RjyFTp7B4\n"
+ + "UyH2uCluR/0T06HQNGfH5XpIYQqCk1Zgng5lmEmheLDPoJpa92lKeQFJMC6eYz9g\n"
+ + "lF1GHxPxkPfbMJ6ZDp5X6Yopu6Q6uEXhVKM/iQVcgzRkx9rid+xTYl+nOKyK/XfC\n"
+ + "z8P0/TFIoPTW02DLge5wKagdoCpy1B7HdrAXyUjoH4B8MsUkq3kYPFSjPzScuTtV\n"
+ + "kUuDw5ipCNeXCRnhbYqRDk6PX5GUu2cmN9jtaH3tbgm3fKNOsd/BO1fLIl7qjXlR\n"
+ + "27HHbC0JXjNvlm2DLp23v4NTxS7WZGYsxyUj5DZrxBxqCsTXu/01w1BrQKWKh9FM\n"
+ + "aVrlA8omfVODK2CSuw+KhEMHepRv/AUgsLl4L4+RMoa+\n"
+ + "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CA_SUITE_B_RSA3072_CERT =
+ loadCertificate(CA_SUITE_B_RSA3072_CERT_STRING);
+
+ private static final String CA_SUITE_B_ECDSA_CERT_STRING =
+ "-----BEGIN CERTIFICATE-----\n"
+ + "MIICTzCCAdSgAwIBAgIUdnLttwNPnQzFufplGOr9bTrGCqMwCgYIKoZIzj0EAwMw\n"
+ + "XjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNV\n"
+ + "BAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0Q0Ew\n"
+ + "HhcNMjAwNzIxMDIyNDA1WhcNMzAwNTMwMDIyNDA1WjBeMQswCQYDVQQGEwJVUzEL\n"
+ + "MAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEOMAwG\n"
+ + "A1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTB2MBAGByqGSM49AgEGBSuB\n"
+ + "BAAiA2IABFmntXwk9icqhDQFUP1xy04WyEpaGW4q6Q+8pujlSl/X3iotPZ++GZfp\n"
+ + "Mfv3YDHDBl6sELPQ2BEjyPXmpsKjOUdiUe69e88oGEdeqT2xXiQ6uzpTfJD4170i\n"
+ + "O/TwLrQGKKNTMFEwHQYDVR0OBBYEFCjptsX3g4g5W0L4oEP6N3gfyiZXMB8GA1Ud\n"
+ + "IwQYMBaAFCjptsX3g4g5W0L4oEP6N3gfyiZXMA8GA1UdEwEB/wQFMAMBAf8wCgYI\n"
+ + "KoZIzj0EAwMDaQAwZgIxAK61brUYRbLmQKiaEboZgrHtnPAcGo7Yzx3MwHecx3Dm\n"
+ + "5soIeLVYc8bPYN1pbhXW1gIxALdEe2sh03nBHyQH4adYoZungoCwt8mp/7sJFxou\n"
+ + "9UnRegyBgGzf74ROWdpZHzh+Pg==\n"
+ + "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CA_SUITE_B_ECDSA_CERT =
+ loadCertificate(CA_SUITE_B_ECDSA_CERT_STRING);
private static final String CLIENT_SUITE_B_RSA3072_CERT_STRING =
"-----BEGIN CERTIFICATE-----\n"
@@ -243,6 +293,363 @@ public class FakeKeys {
public static final X509Certificate CLIENT_SUITE_B_RSA3072_CERT =
loadCertificate(CLIENT_SUITE_B_RSA3072_CERT_STRING);
+ private static final byte[] CLIENT_SUITE_B_RSA3072_KEY_DATA = new byte[]{
+ (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xfe, (byte) 0x02, (byte) 0x01,
+ (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+ (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+ (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+ (byte) 0x06, (byte) 0xe8, (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xe4,
+ (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x82, (byte) 0x01,
+ (byte) 0x81, (byte) 0x00, (byte) 0xc1, (byte) 0x22, (byte) 0xb7, (byte) 0x0b,
+ (byte) 0x92, (byte) 0xb9, (byte) 0xb9, (byte) 0xdb, (byte) 0x42, (byte) 0x29,
+ (byte) 0x39, (byte) 0xc4, (byte) 0xd7, (byte) 0x87, (byte) 0xbc, (byte) 0xcf,
+ (byte) 0x67, (byte) 0x19, (byte) 0xbf, (byte) 0x09, (byte) 0x81, (byte) 0xe1,
+ (byte) 0x77, (byte) 0xbe, (byte) 0x6b, (byte) 0xcf, (byte) 0xbb, (byte) 0x40,
+ (byte) 0xbb, (byte) 0x9d, (byte) 0x1e, (byte) 0x8a, (byte) 0x1c, (byte) 0xfe,
+ (byte) 0x54, (byte) 0x33, (byte) 0x0a, (byte) 0x58, (byte) 0x0a, (byte) 0xe0,
+ (byte) 0xc6, (byte) 0xd5, (byte) 0x50, (byte) 0x2d, (byte) 0x03, (byte) 0xdc,
+ (byte) 0x51, (byte) 0x3e, (byte) 0x53, (byte) 0x7d, (byte) 0x82, (byte) 0xef,
+ (byte) 0xc4, (byte) 0xb1, (byte) 0x2a, (byte) 0x84, (byte) 0xda, (byte) 0x45,
+ (byte) 0x6b, (byte) 0x6f, (byte) 0x3e, (byte) 0x63, (byte) 0x66, (byte) 0xf9,
+ (byte) 0x46, (byte) 0x85, (byte) 0x4f, (byte) 0xc2, (byte) 0xa4, (byte) 0xc3,
+ (byte) 0x25, (byte) 0x27, (byte) 0xa3, (byte) 0xf7, (byte) 0x6f, (byte) 0xfb,
+ (byte) 0x65, (byte) 0xc3, (byte) 0xa5, (byte) 0xdf, (byte) 0xf3, (byte) 0x01,
+ (byte) 0x14, (byte) 0x3e, (byte) 0xdc, (byte) 0x5c, (byte) 0x00, (byte) 0x7d,
+ (byte) 0x6a, (byte) 0x29, (byte) 0x02, (byte) 0x11, (byte) 0x32, (byte) 0x09,
+ (byte) 0x54, (byte) 0xb1, (byte) 0xc2, (byte) 0xc0, (byte) 0x9a, (byte) 0xfa,
+ (byte) 0xc9, (byte) 0x50, (byte) 0xe2, (byte) 0x3b, (byte) 0x91, (byte) 0x20,
+ (byte) 0xc2, (byte) 0x2e, (byte) 0x50, (byte) 0x2d, (byte) 0x4c, (byte) 0x9b,
+ (byte) 0x43, (byte) 0x5a, (byte) 0xa6, (byte) 0xd6, (byte) 0x72, (byte) 0x33,
+ (byte) 0x74, (byte) 0xe3, (byte) 0xfc, (byte) 0x80, (byte) 0x90, (byte) 0x11,
+ (byte) 0xfa, (byte) 0x64, (byte) 0xa3, (byte) 0xda, (byte) 0x95, (byte) 0x21,
+ (byte) 0xb8, (byte) 0x8a, (byte) 0xe9, (byte) 0xea, (byte) 0x09, (byte) 0x31,
+ (byte) 0x39, (byte) 0x18, (byte) 0xf0, (byte) 0x45, (byte) 0x9f, (byte) 0x02,
+ (byte) 0x7e, (byte) 0xd1, (byte) 0x4c, (byte) 0x57, (byte) 0x5f, (byte) 0x47,
+ (byte) 0x53, (byte) 0x8b, (byte) 0xb8, (byte) 0xed, (byte) 0x26, (byte) 0x54,
+ (byte) 0xe8, (byte) 0xe0, (byte) 0x2d, (byte) 0x6f, (byte) 0x7f, (byte) 0xfa,
+ (byte) 0xea, (byte) 0x58, (byte) 0xbf, (byte) 0xa8, (byte) 0x59, (byte) 0xd7,
+ (byte) 0xd9, (byte) 0xc0, (byte) 0x30, (byte) 0x0c, (byte) 0x70, (byte) 0xe1,
+ (byte) 0x04, (byte) 0xc9, (byte) 0xc7, (byte) 0xb9, (byte) 0x4b, (byte) 0xc0,
+ (byte) 0x02, (byte) 0xd7, (byte) 0xec, (byte) 0x1f, (byte) 0xad, (byte) 0x0d,
+ (byte) 0x83, (byte) 0x44, (byte) 0x64, (byte) 0x70, (byte) 0xea, (byte) 0x60,
+ (byte) 0xbd, (byte) 0xb3, (byte) 0xca, (byte) 0xf4, (byte) 0x16, (byte) 0x02,
+ (byte) 0x3d, (byte) 0x87, (byte) 0x0a, (byte) 0x57, (byte) 0xab, (byte) 0x7b,
+ (byte) 0xc4, (byte) 0x18, (byte) 0x20, (byte) 0xbc, (byte) 0x64, (byte) 0xbe,
+ (byte) 0x4b, (byte) 0x60, (byte) 0x06, (byte) 0x0d, (byte) 0x9c, (byte) 0xac,
+ (byte) 0x42, (byte) 0x49, (byte) 0x7b, (byte) 0x85, (byte) 0xdb, (byte) 0x0c,
+ (byte) 0x7e, (byte) 0xcb, (byte) 0x03, (byte) 0x7a, (byte) 0xeb, (byte) 0x5e,
+ (byte) 0x6b, (byte) 0x22, (byte) 0xa9, (byte) 0xfd, (byte) 0x59, (byte) 0x6d,
+ (byte) 0xf1, (byte) 0x45, (byte) 0x13, (byte) 0x32, (byte) 0xbd, (byte) 0x34,
+ (byte) 0x5a, (byte) 0xa8, (byte) 0xbc, (byte) 0xbf, (byte) 0xaa, (byte) 0x1a,
+ (byte) 0x1f, (byte) 0xb3, (byte) 0x20, (byte) 0xff, (byte) 0xb9, (byte) 0xf3,
+ (byte) 0xc4, (byte) 0xa1, (byte) 0x24, (byte) 0x53, (byte) 0xbd, (byte) 0x1f,
+ (byte) 0xf4, (byte) 0x43, (byte) 0x9c, (byte) 0x3a, (byte) 0x62, (byte) 0x4e,
+ (byte) 0x70, (byte) 0x05, (byte) 0x4d, (byte) 0x65, (byte) 0xd0, (byte) 0x75,
+ (byte) 0x3c, (byte) 0x20, (byte) 0xb3, (byte) 0x34, (byte) 0x92, (byte) 0xd1,
+ (byte) 0x5c, (byte) 0x36, (byte) 0x3c, (byte) 0x1f, (byte) 0x89, (byte) 0xa8,
+ (byte) 0x40, (byte) 0x01, (byte) 0x01, (byte) 0xaf, (byte) 0x43, (byte) 0x78,
+ (byte) 0xcb, (byte) 0xd7, (byte) 0x4f, (byte) 0x53, (byte) 0xb2, (byte) 0xf8,
+ (byte) 0xd6, (byte) 0x37, (byte) 0x22, (byte) 0xd3, (byte) 0xc7, (byte) 0xcb,
+ (byte) 0x2e, (byte) 0xb7, (byte) 0x9d, (byte) 0x06, (byte) 0x55, (byte) 0x23,
+ (byte) 0x6a, (byte) 0xd7, (byte) 0x00, (byte) 0xdc, (byte) 0x38, (byte) 0x36,
+ (byte) 0x1c, (byte) 0x12, (byte) 0xd1, (byte) 0x9e, (byte) 0x83, (byte) 0x17,
+ (byte) 0xe4, (byte) 0x2c, (byte) 0x4c, (byte) 0xda, (byte) 0xe3, (byte) 0xf8,
+ (byte) 0x65, (byte) 0x3b, (byte) 0x7b, (byte) 0x84, (byte) 0x86, (byte) 0xfc,
+ (byte) 0x41, (byte) 0x91, (byte) 0xf1, (byte) 0x2b, (byte) 0xe5, (byte) 0x76,
+ (byte) 0x36, (byte) 0x1f, (byte) 0x41, (byte) 0x35, (byte) 0x85, (byte) 0x2e,
+ (byte) 0x0d, (byte) 0x65, (byte) 0xfd, (byte) 0x44, (byte) 0xf5, (byte) 0x84,
+ (byte) 0xe3, (byte) 0xa4, (byte) 0x41, (byte) 0x9c, (byte) 0x1d, (byte) 0xb1,
+ (byte) 0xa5, (byte) 0xb5, (byte) 0xce, (byte) 0x02, (byte) 0xb2, (byte) 0x7a,
+ (byte) 0xe8, (byte) 0x85, (byte) 0x07, (byte) 0x62, (byte) 0x9d, (byte) 0x32,
+ (byte) 0x66, (byte) 0xc0, (byte) 0x4a, (byte) 0xaf, (byte) 0x94, (byte) 0xc7,
+ (byte) 0x52, (byte) 0xf5, (byte) 0x28, (byte) 0x80, (byte) 0xa8, (byte) 0xd0,
+ (byte) 0x88, (byte) 0x25, (byte) 0xc1, (byte) 0x67, (byte) 0x01, (byte) 0xff,
+ (byte) 0xc9, (byte) 0xe7, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00,
+ (byte) 0x01, (byte) 0x02, (byte) 0x82, (byte) 0x01, (byte) 0x80, (byte) 0x04,
+ (byte) 0xb1, (byte) 0xcc, (byte) 0x53, (byte) 0x3a, (byte) 0xb0, (byte) 0xcb,
+ (byte) 0x04, (byte) 0xba, (byte) 0x59, (byte) 0xf8, (byte) 0x2e, (byte) 0x81,
+ (byte) 0xb2, (byte) 0xa9, (byte) 0xf3, (byte) 0x3c, (byte) 0xa5, (byte) 0x52,
+ (byte) 0x90, (byte) 0x6f, (byte) 0x98, (byte) 0xc4, (byte) 0x69, (byte) 0x5b,
+ (byte) 0x83, (byte) 0x84, (byte) 0x20, (byte) 0xb1, (byte) 0xae, (byte) 0xc3,
+ (byte) 0x04, (byte) 0x46, (byte) 0x6a, (byte) 0x24, (byte) 0x2f, (byte) 0xcd,
+ (byte) 0x6b, (byte) 0x90, (byte) 0x70, (byte) 0x20, (byte) 0x45, (byte) 0x25,
+ (byte) 0x1a, (byte) 0xc3, (byte) 0x02, (byte) 0x42, (byte) 0xf3, (byte) 0x49,
+ (byte) 0xe2, (byte) 0x3e, (byte) 0x21, (byte) 0x87, (byte) 0xdd, (byte) 0x6a,
+ (byte) 0x94, (byte) 0x2a, (byte) 0x1e, (byte) 0x0f, (byte) 0xdb, (byte) 0x77,
+ (byte) 0x5f, (byte) 0xc1, (byte) 0x2c, (byte) 0x03, (byte) 0xfb, (byte) 0xcf,
+ (byte) 0x91, (byte) 0x82, (byte) 0xa1, (byte) 0xbf, (byte) 0xb0, (byte) 0x73,
+ (byte) 0xfa, (byte) 0xda, (byte) 0xbc, (byte) 0xf8, (byte) 0x9f, (byte) 0x45,
+ (byte) 0xd3, (byte) 0xe8, (byte) 0xbb, (byte) 0x38, (byte) 0xfb, (byte) 0xc2,
+ (byte) 0x2d, (byte) 0x76, (byte) 0x51, (byte) 0x96, (byte) 0x18, (byte) 0x03,
+ (byte) 0x15, (byte) 0xd9, (byte) 0xea, (byte) 0x82, (byte) 0x25, (byte) 0x83,
+ (byte) 0xff, (byte) 0x5c, (byte) 0x85, (byte) 0x06, (byte) 0x09, (byte) 0xb2,
+ (byte) 0x46, (byte) 0x12, (byte) 0x64, (byte) 0x02, (byte) 0x74, (byte) 0x4f,
+ (byte) 0xbc, (byte) 0x9a, (byte) 0x25, (byte) 0x18, (byte) 0x01, (byte) 0x07,
+ (byte) 0x17, (byte) 0x25, (byte) 0x55, (byte) 0x7c, (byte) 0xdc, (byte) 0xe1,
+ (byte) 0xd1, (byte) 0x5a, (byte) 0x2f, (byte) 0x25, (byte) 0xaf, (byte) 0xf6,
+ (byte) 0x8f, (byte) 0xa4, (byte) 0x9a, (byte) 0x5a, (byte) 0x3a, (byte) 0xfe,
+ (byte) 0x2e, (byte) 0x93, (byte) 0x24, (byte) 0xa0, (byte) 0x27, (byte) 0xac,
+ (byte) 0x07, (byte) 0x75, (byte) 0x33, (byte) 0x01, (byte) 0x54, (byte) 0x23,
+ (byte) 0x0f, (byte) 0xe8, (byte) 0x9f, (byte) 0xfa, (byte) 0x36, (byte) 0xe6,
+ (byte) 0x3a, (byte) 0xd5, (byte) 0x78, (byte) 0xb0, (byte) 0xe4, (byte) 0x6a,
+ (byte) 0x16, (byte) 0x50, (byte) 0xbd, (byte) 0x0f, (byte) 0x9f, (byte) 0x32,
+ (byte) 0xa1, (byte) 0x6b, (byte) 0xf5, (byte) 0xa4, (byte) 0x34, (byte) 0x58,
+ (byte) 0xb6, (byte) 0xa4, (byte) 0xb3, (byte) 0xc3, (byte) 0x83, (byte) 0x08,
+ (byte) 0x18, (byte) 0xc7, (byte) 0xef, (byte) 0x95, (byte) 0xe2, (byte) 0x1b,
+ (byte) 0xba, (byte) 0x35, (byte) 0x61, (byte) 0xa3, (byte) 0xb4, (byte) 0x30,
+ (byte) 0xe0, (byte) 0xd1, (byte) 0xc1, (byte) 0xa2, (byte) 0x3a, (byte) 0xc6,
+ (byte) 0xb4, (byte) 0xd2, (byte) 0x80, (byte) 0x5a, (byte) 0xaf, (byte) 0xa4,
+ (byte) 0x54, (byte) 0x3c, (byte) 0x66, (byte) 0x5a, (byte) 0x1c, (byte) 0x4d,
+ (byte) 0xe1, (byte) 0xd9, (byte) 0x98, (byte) 0x44, (byte) 0x01, (byte) 0x1b,
+ (byte) 0x8c, (byte) 0xe9, (byte) 0x80, (byte) 0x54, (byte) 0x83, (byte) 0x3d,
+ (byte) 0x96, (byte) 0x25, (byte) 0x41, (byte) 0x1c, (byte) 0xad, (byte) 0xae,
+ (byte) 0x3b, (byte) 0x7a, (byte) 0xd7, (byte) 0x9d, (byte) 0x10, (byte) 0x7c,
+ (byte) 0xd1, (byte) 0xa7, (byte) 0x96, (byte) 0x39, (byte) 0xa5, (byte) 0x2f,
+ (byte) 0xbe, (byte) 0xc3, (byte) 0x2c, (byte) 0x64, (byte) 0x01, (byte) 0xfe,
+ (byte) 0xa2, (byte) 0xd1, (byte) 0x6a, (byte) 0xcf, (byte) 0x4c, (byte) 0x76,
+ (byte) 0x3b, (byte) 0xc8, (byte) 0x35, (byte) 0x21, (byte) 0xda, (byte) 0x98,
+ (byte) 0xcf, (byte) 0xf9, (byte) 0x29, (byte) 0xff, (byte) 0x30, (byte) 0x59,
+ (byte) 0x36, (byte) 0x53, (byte) 0x0b, (byte) 0xbb, (byte) 0xfa, (byte) 0xba,
+ (byte) 0xc4, (byte) 0x03, (byte) 0x23, (byte) 0xe0, (byte) 0xd3, (byte) 0x33,
+ (byte) 0xff, (byte) 0x32, (byte) 0xdb, (byte) 0x30, (byte) 0x64, (byte) 0xc7,
+ (byte) 0x56, (byte) 0xca, (byte) 0x55, (byte) 0x14, (byte) 0xee, (byte) 0x58,
+ (byte) 0xfe, (byte) 0x96, (byte) 0x7e, (byte) 0x1c, (byte) 0x34, (byte) 0x16,
+ (byte) 0xeb, (byte) 0x76, (byte) 0x26, (byte) 0x48, (byte) 0xe2, (byte) 0xe5,
+ (byte) 0x5c, (byte) 0xd5, (byte) 0x83, (byte) 0x37, (byte) 0xd9, (byte) 0x09,
+ (byte) 0x71, (byte) 0xbc, (byte) 0x54, (byte) 0x25, (byte) 0xca, (byte) 0x2e,
+ (byte) 0xdb, (byte) 0x36, (byte) 0x39, (byte) 0xcc, (byte) 0x3a, (byte) 0x81,
+ (byte) 0x95, (byte) 0x9e, (byte) 0xf4, (byte) 0x01, (byte) 0xa7, (byte) 0xc0,
+ (byte) 0x20, (byte) 0xce, (byte) 0x70, (byte) 0x55, (byte) 0x2c, (byte) 0xe0,
+ (byte) 0x93, (byte) 0x72, (byte) 0xa6, (byte) 0x25, (byte) 0xda, (byte) 0x64,
+ (byte) 0x19, (byte) 0x18, (byte) 0xd2, (byte) 0x31, (byte) 0xe2, (byte) 0x7c,
+ (byte) 0xf2, (byte) 0x30, (byte) 0x9e, (byte) 0x8d, (byte) 0xc6, (byte) 0x14,
+ (byte) 0x8a, (byte) 0x38, (byte) 0xf0, (byte) 0x94, (byte) 0xeb, (byte) 0xf4,
+ (byte) 0x64, (byte) 0x92, (byte) 0x3d, (byte) 0x67, (byte) 0xa6, (byte) 0x2c,
+ (byte) 0x52, (byte) 0xfc, (byte) 0x60, (byte) 0xca, (byte) 0x2a, (byte) 0xcf,
+ (byte) 0x24, (byte) 0xd5, (byte) 0x42, (byte) 0x5f, (byte) 0xc7, (byte) 0x9f,
+ (byte) 0xf3, (byte) 0xb4, (byte) 0xdf, (byte) 0x76, (byte) 0x6e, (byte) 0x53,
+ (byte) 0xa1, (byte) 0x7b, (byte) 0xae, (byte) 0xa5, (byte) 0x84, (byte) 0x1f,
+ (byte) 0xfa, (byte) 0xc0, (byte) 0xb4, (byte) 0x6c, (byte) 0xc9, (byte) 0x02,
+ (byte) 0x81, (byte) 0xc1, (byte) 0x00, (byte) 0xf3, (byte) 0x17, (byte) 0xd9,
+ (byte) 0x48, (byte) 0x17, (byte) 0x87, (byte) 0x84, (byte) 0x16, (byte) 0xea,
+ (byte) 0x2d, (byte) 0x31, (byte) 0x1b, (byte) 0xce, (byte) 0xec, (byte) 0xaf,
+ (byte) 0xdc, (byte) 0x6b, (byte) 0xaf, (byte) 0xc8, (byte) 0xf1, (byte) 0x40,
+ (byte) 0xa7, (byte) 0x4f, (byte) 0xef, (byte) 0x48, (byte) 0x08, (byte) 0x5e,
+ (byte) 0x9a, (byte) 0xd1, (byte) 0xc0, (byte) 0xb1, (byte) 0xfe, (byte) 0xe7,
+ (byte) 0x03, (byte) 0xd5, (byte) 0x96, (byte) 0x01, (byte) 0xe8, (byte) 0x40,
+ (byte) 0xca, (byte) 0x78, (byte) 0xcb, (byte) 0xb3, (byte) 0x28, (byte) 0x1a,
+ (byte) 0xf0, (byte) 0xe5, (byte) 0xf6, (byte) 0x46, (byte) 0xef, (byte) 0xcd,
+ (byte) 0x1a, (byte) 0x0f, (byte) 0x13, (byte) 0x2d, (byte) 0x38, (byte) 0xf8,
+ (byte) 0xf7, (byte) 0x88, (byte) 0x21, (byte) 0x15, (byte) 0xce, (byte) 0x48,
+ (byte) 0xf4, (byte) 0x92, (byte) 0x7e, (byte) 0x9b, (byte) 0x2e, (byte) 0x2f,
+ (byte) 0x22, (byte) 0x3e, (byte) 0x5c, (byte) 0x67, (byte) 0xd7, (byte) 0x58,
+ (byte) 0xf6, (byte) 0xef, (byte) 0x1f, (byte) 0xb4, (byte) 0x04, (byte) 0xc7,
+ (byte) 0xfd, (byte) 0x8c, (byte) 0x4e, (byte) 0x27, (byte) 0x9e, (byte) 0xb9,
+ (byte) 0xef, (byte) 0x0f, (byte) 0xf7, (byte) 0x4a, (byte) 0xc2, (byte) 0xf4,
+ (byte) 0x64, (byte) 0x6b, (byte) 0xe0, (byte) 0xfb, (byte) 0xe3, (byte) 0x45,
+ (byte) 0xd5, (byte) 0x37, (byte) 0xa0, (byte) 0x2a, (byte) 0xc6, (byte) 0xf3,
+ (byte) 0xf6, (byte) 0xcc, (byte) 0xb5, (byte) 0x94, (byte) 0xbf, (byte) 0x56,
+ (byte) 0xa0, (byte) 0x61, (byte) 0x36, (byte) 0x88, (byte) 0x35, (byte) 0xd5,
+ (byte) 0xa5, (byte) 0xad, (byte) 0x20, (byte) 0x48, (byte) 0xda, (byte) 0x70,
+ (byte) 0x35, (byte) 0xd9, (byte) 0x75, (byte) 0x66, (byte) 0xa5, (byte) 0xac,
+ (byte) 0x86, (byte) 0x7a, (byte) 0x75, (byte) 0x49, (byte) 0x88, (byte) 0x40,
+ (byte) 0xce, (byte) 0xb0, (byte) 0x6f, (byte) 0x57, (byte) 0x15, (byte) 0x54,
+ (byte) 0xd3, (byte) 0x2f, (byte) 0x11, (byte) 0x9b, (byte) 0xe3, (byte) 0x87,
+ (byte) 0xc8, (byte) 0x8d, (byte) 0x98, (byte) 0xc6, (byte) 0xe0, (byte) 0xbc,
+ (byte) 0x85, (byte) 0xb9, (byte) 0x04, (byte) 0x43, (byte) 0xa9, (byte) 0x41,
+ (byte) 0xce, (byte) 0x42, (byte) 0x1a, (byte) 0x57, (byte) 0x10, (byte) 0xd8,
+ (byte) 0xe4, (byte) 0x6a, (byte) 0x51, (byte) 0x10, (byte) 0x0a, (byte) 0xec,
+ (byte) 0xe4, (byte) 0x57, (byte) 0xc7, (byte) 0xee, (byte) 0xe9, (byte) 0xd6,
+ (byte) 0xcb, (byte) 0x3e, (byte) 0xba, (byte) 0xfa, (byte) 0xe9, (byte) 0x0e,
+ (byte) 0xed, (byte) 0x87, (byte) 0x04, (byte) 0x9a, (byte) 0x48, (byte) 0xba,
+ (byte) 0xaf, (byte) 0x08, (byte) 0xf5, (byte) 0x02, (byte) 0x81, (byte) 0xc1,
+ (byte) 0x00, (byte) 0xcb, (byte) 0x63, (byte) 0xd6, (byte) 0x54, (byte) 0xb6,
+ (byte) 0xf3, (byte) 0xf3, (byte) 0x8c, (byte) 0xf8, (byte) 0xd0, (byte) 0xd2,
+ (byte) 0x84, (byte) 0xc1, (byte) 0xf5, (byte) 0x12, (byte) 0xe0, (byte) 0x02,
+ (byte) 0x80, (byte) 0x42, (byte) 0x92, (byte) 0x4e, (byte) 0xa4, (byte) 0x5c,
+ (byte) 0xa5, (byte) 0x64, (byte) 0xec, (byte) 0xb7, (byte) 0xdc, (byte) 0xe0,
+ (byte) 0x2d, (byte) 0x5d, (byte) 0xac, (byte) 0x0e, (byte) 0x24, (byte) 0x48,
+ (byte) 0x13, (byte) 0x05, (byte) 0xe8, (byte) 0xff, (byte) 0x96, (byte) 0x93,
+ (byte) 0xba, (byte) 0x3c, (byte) 0x88, (byte) 0xcc, (byte) 0x80, (byte) 0xf9,
+ (byte) 0xdb, (byte) 0xa8, (byte) 0x4d, (byte) 0x86, (byte) 0x47, (byte) 0xc8,
+ (byte) 0xbf, (byte) 0x34, (byte) 0x2d, (byte) 0xda, (byte) 0xb6, (byte) 0x28,
+ (byte) 0xf0, (byte) 0x1e, (byte) 0xd2, (byte) 0x46, (byte) 0x0d, (byte) 0x6f,
+ (byte) 0x36, (byte) 0x8e, (byte) 0x84, (byte) 0xd8, (byte) 0xaf, (byte) 0xf7,
+ (byte) 0x69, (byte) 0x23, (byte) 0x77, (byte) 0xfb, (byte) 0xc5, (byte) 0x04,
+ (byte) 0x08, (byte) 0x18, (byte) 0xac, (byte) 0x85, (byte) 0x80, (byte) 0x87,
+ (byte) 0x1c, (byte) 0xfe, (byte) 0x8e, (byte) 0x5d, (byte) 0x00, (byte) 0x7f,
+ (byte) 0x5b, (byte) 0x33, (byte) 0xf5, (byte) 0xdf, (byte) 0x70, (byte) 0x81,
+ (byte) 0xad, (byte) 0x81, (byte) 0xf4, (byte) 0x5a, (byte) 0x37, (byte) 0x8a,
+ (byte) 0x79, (byte) 0x09, (byte) 0xc5, (byte) 0x55, (byte) 0xab, (byte) 0x58,
+ (byte) 0x7c, (byte) 0x47, (byte) 0xca, (byte) 0xa5, (byte) 0x80, (byte) 0x49,
+ (byte) 0x5f, (byte) 0x71, (byte) 0x83, (byte) 0xfb, (byte) 0x3b, (byte) 0x06,
+ (byte) 0xec, (byte) 0x75, (byte) 0x23, (byte) 0xc4, (byte) 0x32, (byte) 0xc7,
+ (byte) 0x18, (byte) 0xf6, (byte) 0x82, (byte) 0x95, (byte) 0x98, (byte) 0x39,
+ (byte) 0xf7, (byte) 0x92, (byte) 0x31, (byte) 0xc0, (byte) 0x89, (byte) 0xba,
+ (byte) 0xd4, (byte) 0xd4, (byte) 0x58, (byte) 0x4e, (byte) 0x38, (byte) 0x35,
+ (byte) 0x10, (byte) 0xb9, (byte) 0xf1, (byte) 0x27, (byte) 0xdc, (byte) 0xff,
+ (byte) 0xc7, (byte) 0xb2, (byte) 0xba, (byte) 0x1f, (byte) 0x27, (byte) 0xaf,
+ (byte) 0x99, (byte) 0xd5, (byte) 0xb0, (byte) 0x39, (byte) 0xe7, (byte) 0x43,
+ (byte) 0x88, (byte) 0xd3, (byte) 0xce, (byte) 0x38, (byte) 0xc2, (byte) 0x99,
+ (byte) 0x43, (byte) 0xfc, (byte) 0x8a, (byte) 0xe3, (byte) 0x60, (byte) 0x0d,
+ (byte) 0x0a, (byte) 0xb8, (byte) 0xc4, (byte) 0x29, (byte) 0xca, (byte) 0x0d,
+ (byte) 0x30, (byte) 0xaf, (byte) 0xca, (byte) 0xd0, (byte) 0xaa, (byte) 0x67,
+ (byte) 0xb1, (byte) 0xdd, (byte) 0xdb, (byte) 0x7a, (byte) 0x11, (byte) 0xad,
+ (byte) 0xeb, (byte) 0x02, (byte) 0x81, (byte) 0xc0, (byte) 0x71, (byte) 0xb8,
+ (byte) 0xcf, (byte) 0x72, (byte) 0x35, (byte) 0x67, (byte) 0xb5, (byte) 0x38,
+ (byte) 0x8f, (byte) 0x16, (byte) 0xd3, (byte) 0x29, (byte) 0x82, (byte) 0x35,
+ (byte) 0x21, (byte) 0xd4, (byte) 0x49, (byte) 0x20, (byte) 0x74, (byte) 0x2d,
+ (byte) 0xc0, (byte) 0xa4, (byte) 0x44, (byte) 0xf5, (byte) 0xd8, (byte) 0xc9,
+ (byte) 0xe9, (byte) 0x90, (byte) 0x1d, (byte) 0xde, (byte) 0x3a, (byte) 0xa6,
+ (byte) 0xd7, (byte) 0xe5, (byte) 0xe8, (byte) 0x4e, (byte) 0x83, (byte) 0xd7,
+ (byte) 0xe6, (byte) 0x2f, (byte) 0x92, (byte) 0x31, (byte) 0x21, (byte) 0x3f,
+ (byte) 0xfa, (byte) 0xd2, (byte) 0x85, (byte) 0x92, (byte) 0x1f, (byte) 0xff,
+ (byte) 0x61, (byte) 0x00, (byte) 0xf6, (byte) 0xda, (byte) 0x6e, (byte) 0xc6,
+ (byte) 0x7f, (byte) 0x5a, (byte) 0x35, (byte) 0x79, (byte) 0xdc, (byte) 0xdc,
+ (byte) 0xa3, (byte) 0x2e, (byte) 0x9f, (byte) 0x35, (byte) 0xd1, (byte) 0x5c,
+ (byte) 0xda, (byte) 0xb9, (byte) 0xf7, (byte) 0x58, (byte) 0x7d, (byte) 0x4f,
+ (byte) 0xb6, (byte) 0x13, (byte) 0xd7, (byte) 0x2c, (byte) 0x0a, (byte) 0xa8,
+ (byte) 0x4d, (byte) 0xf2, (byte) 0xe4, (byte) 0x67, (byte) 0x4f, (byte) 0x8b,
+ (byte) 0xa6, (byte) 0xca, (byte) 0x1a, (byte) 0xbb, (byte) 0x02, (byte) 0x63,
+ (byte) 0x8f, (byte) 0xb7, (byte) 0x46, (byte) 0xec, (byte) 0x7a, (byte) 0x8a,
+ (byte) 0x09, (byte) 0x0a, (byte) 0x45, (byte) 0x3a, (byte) 0x8d, (byte) 0xa8,
+ (byte) 0x83, (byte) 0x4b, (byte) 0x0a, (byte) 0xdb, (byte) 0x4b, (byte) 0x99,
+ (byte) 0xf3, (byte) 0x69, (byte) 0x95, (byte) 0xf0, (byte) 0xcf, (byte) 0xe9,
+ (byte) 0xf7, (byte) 0x67, (byte) 0xc9, (byte) 0x45, (byte) 0x18, (byte) 0x2f,
+ (byte) 0xf0, (byte) 0x5c, (byte) 0x90, (byte) 0xbd, (byte) 0xa6, (byte) 0x66,
+ (byte) 0x8c, (byte) 0xfe, (byte) 0x60, (byte) 0x5d, (byte) 0x6c, (byte) 0x27,
+ (byte) 0xec, (byte) 0xc1, (byte) 0x84, (byte) 0xb2, (byte) 0xa1, (byte) 0x97,
+ (byte) 0x9e, (byte) 0x16, (byte) 0x29, (byte) 0xa7, (byte) 0xe0, (byte) 0x38,
+ (byte) 0xa2, (byte) 0x36, (byte) 0x05, (byte) 0x5f, (byte) 0xda, (byte) 0x72,
+ (byte) 0x1a, (byte) 0x5f, (byte) 0xa8, (byte) 0x7d, (byte) 0x41, (byte) 0x35,
+ (byte) 0xf6, (byte) 0x4e, (byte) 0x0a, (byte) 0x88, (byte) 0x8e, (byte) 0x00,
+ (byte) 0x98, (byte) 0xa6, (byte) 0xca, (byte) 0xc1, (byte) 0xdf, (byte) 0x72,
+ (byte) 0x6c, (byte) 0xfe, (byte) 0x29, (byte) 0xbe, (byte) 0xa3, (byte) 0x9b,
+ (byte) 0x0b, (byte) 0x5c, (byte) 0x0b, (byte) 0x9d, (byte) 0xa7, (byte) 0x71,
+ (byte) 0xce, (byte) 0x04, (byte) 0xfa, (byte) 0xac, (byte) 0x01, (byte) 0x8d,
+ (byte) 0x52, (byte) 0xa0, (byte) 0x3d, (byte) 0xdd, (byte) 0x02, (byte) 0x81,
+ (byte) 0xc1, (byte) 0x00, (byte) 0xc1, (byte) 0xc0, (byte) 0x2e, (byte) 0xa9,
+ (byte) 0xee, (byte) 0xca, (byte) 0xff, (byte) 0xe4, (byte) 0xf8, (byte) 0x15,
+ (byte) 0xfd, (byte) 0xa5, (byte) 0x68, (byte) 0x1b, (byte) 0x2d, (byte) 0x4a,
+ (byte) 0xe6, (byte) 0x37, (byte) 0x06, (byte) 0xb3, (byte) 0xd7, (byte) 0x64,
+ (byte) 0xad, (byte) 0xb9, (byte) 0x05, (byte) 0x26, (byte) 0x97, (byte) 0x94,
+ (byte) 0x3a, (byte) 0x9e, (byte) 0x1c, (byte) 0xd0, (byte) 0xcd, (byte) 0x7b,
+ (byte) 0xf4, (byte) 0x88, (byte) 0xe2, (byte) 0xa5, (byte) 0x6d, (byte) 0xed,
+ (byte) 0x24, (byte) 0x77, (byte) 0x52, (byte) 0x39, (byte) 0x43, (byte) 0x0f,
+ (byte) 0x4e, (byte) 0x75, (byte) 0xd8, (byte) 0xa3, (byte) 0x59, (byte) 0x5a,
+ (byte) 0xc2, (byte) 0xba, (byte) 0x9a, (byte) 0x5b, (byte) 0x60, (byte) 0x31,
+ (byte) 0x0d, (byte) 0x58, (byte) 0x89, (byte) 0x13, (byte) 0xe8, (byte) 0x95,
+ (byte) 0xdd, (byte) 0xae, (byte) 0xcc, (byte) 0x1f, (byte) 0x73, (byte) 0x48,
+ (byte) 0x55, (byte) 0xd8, (byte) 0xfb, (byte) 0x67, (byte) 0xce, (byte) 0x18,
+ (byte) 0x85, (byte) 0x59, (byte) 0xad, (byte) 0x1f, (byte) 0x93, (byte) 0xe1,
+ (byte) 0xb7, (byte) 0x54, (byte) 0x80, (byte) 0x8e, (byte) 0x5f, (byte) 0xbc,
+ (byte) 0x1c, (byte) 0x96, (byte) 0x66, (byte) 0x2e, (byte) 0x40, (byte) 0x17,
+ (byte) 0x2e, (byte) 0x01, (byte) 0x7a, (byte) 0x7d, (byte) 0xaa, (byte) 0xff,
+ (byte) 0xa3, (byte) 0xd2, (byte) 0xdf, (byte) 0xe2, (byte) 0xf3, (byte) 0x54,
+ (byte) 0x51, (byte) 0xeb, (byte) 0xba, (byte) 0x7c, (byte) 0x2a, (byte) 0x22,
+ (byte) 0xc6, (byte) 0x42, (byte) 0xbc, (byte) 0xa1, (byte) 0x6c, (byte) 0xcf,
+ (byte) 0x73, (byte) 0x2e, (byte) 0x07, (byte) 0xfc, (byte) 0xf5, (byte) 0x67,
+ (byte) 0x25, (byte) 0xd0, (byte) 0xfa, (byte) 0xeb, (byte) 0xb4, (byte) 0xd4,
+ (byte) 0x19, (byte) 0xcc, (byte) 0x64, (byte) 0xa1, (byte) 0x2e, (byte) 0x78,
+ (byte) 0x45, (byte) 0xd9, (byte) 0x7f, (byte) 0x1b, (byte) 0x4c, (byte) 0x10,
+ (byte) 0x31, (byte) 0x44, (byte) 0xe8, (byte) 0xcc, (byte) 0xf9, (byte) 0x1b,
+ (byte) 0x87, (byte) 0x31, (byte) 0xd6, (byte) 0x69, (byte) 0x85, (byte) 0x4a,
+ (byte) 0x49, (byte) 0xf6, (byte) 0xb2, (byte) 0xe0, (byte) 0xb8, (byte) 0x98,
+ (byte) 0x3c, (byte) 0xf6, (byte) 0x78, (byte) 0x46, (byte) 0xc8, (byte) 0x3d,
+ (byte) 0x60, (byte) 0xc1, (byte) 0xaa, (byte) 0x2f, (byte) 0x28, (byte) 0xa1,
+ (byte) 0x14, (byte) 0x6b, (byte) 0x75, (byte) 0x4d, (byte) 0xb1, (byte) 0x3d,
+ (byte) 0x80, (byte) 0x49, (byte) 0x33, (byte) 0xfd, (byte) 0x71, (byte) 0xc0,
+ (byte) 0x13, (byte) 0x1e, (byte) 0x16, (byte) 0x69, (byte) 0x80, (byte) 0xa4,
+ (byte) 0x9c, (byte) 0xd7, (byte) 0x02, (byte) 0x81, (byte) 0xc1, (byte) 0x00,
+ (byte) 0x8c, (byte) 0x33, (byte) 0x2d, (byte) 0xd9, (byte) 0xf3, (byte) 0x42,
+ (byte) 0x4d, (byte) 0xca, (byte) 0x5e, (byte) 0x60, (byte) 0x14, (byte) 0x10,
+ (byte) 0xf6, (byte) 0xf3, (byte) 0x71, (byte) 0x15, (byte) 0x88, (byte) 0x54,
+ (byte) 0x84, (byte) 0x21, (byte) 0x04, (byte) 0xb1, (byte) 0xaf, (byte) 0x02,
+ (byte) 0x11, (byte) 0x7f, (byte) 0x42, (byte) 0x3e, (byte) 0x86, (byte) 0xcb,
+ (byte) 0x6c, (byte) 0xf5, (byte) 0x57, (byte) 0x78, (byte) 0x4a, (byte) 0x03,
+ (byte) 0x9b, (byte) 0x80, (byte) 0xc2, (byte) 0x04, (byte) 0x3a, (byte) 0x6b,
+ (byte) 0xb3, (byte) 0x30, (byte) 0x31, (byte) 0x7e, (byte) 0xc3, (byte) 0x89,
+ (byte) 0x09, (byte) 0x4e, (byte) 0x86, (byte) 0x59, (byte) 0x41, (byte) 0xb5,
+ (byte) 0xae, (byte) 0xd5, (byte) 0xc6, (byte) 0x38, (byte) 0xbc, (byte) 0xd7,
+ (byte) 0xd7, (byte) 0x8e, (byte) 0xa3, (byte) 0x1a, (byte) 0xde, (byte) 0x32,
+ (byte) 0xad, (byte) 0x8d, (byte) 0x15, (byte) 0x81, (byte) 0xfe, (byte) 0xac,
+ (byte) 0xbd, (byte) 0xd0, (byte) 0xca, (byte) 0xbc, (byte) 0xd8, (byte) 0x6a,
+ (byte) 0xe1, (byte) 0xfe, (byte) 0xda, (byte) 0xc4, (byte) 0xd8, (byte) 0x62,
+ (byte) 0x71, (byte) 0x20, (byte) 0xa3, (byte) 0xd3, (byte) 0x06, (byte) 0x11,
+ (byte) 0xa9, (byte) 0x53, (byte) 0x7a, (byte) 0x44, (byte) 0x89, (byte) 0x3d,
+ (byte) 0x28, (byte) 0x5e, (byte) 0x7d, (byte) 0xf0, (byte) 0x60, (byte) 0xeb,
+ (byte) 0xb5, (byte) 0xdf, (byte) 0xed, (byte) 0x4f, (byte) 0x6d, (byte) 0x05,
+ (byte) 0x59, (byte) 0x06, (byte) 0xb0, (byte) 0x62, (byte) 0x50, (byte) 0x1c,
+ (byte) 0xb7, (byte) 0x2c, (byte) 0x44, (byte) 0xa4, (byte) 0x49, (byte) 0xf8,
+ (byte) 0x4f, (byte) 0x4b, (byte) 0xab, (byte) 0x71, (byte) 0x5b, (byte) 0xcb,
+ (byte) 0x31, (byte) 0x10, (byte) 0x41, (byte) 0xe0, (byte) 0x1a, (byte) 0x15,
+ (byte) 0xdc, (byte) 0x4c, (byte) 0x5d, (byte) 0x4f, (byte) 0x62, (byte) 0x83,
+ (byte) 0xa4, (byte) 0x80, (byte) 0x06, (byte) 0x36, (byte) 0xba, (byte) 0xc9,
+ (byte) 0xe2, (byte) 0xa4, (byte) 0x11, (byte) 0x98, (byte) 0x6b, (byte) 0x4c,
+ (byte) 0xe9, (byte) 0x90, (byte) 0x55, (byte) 0x18, (byte) 0xde, (byte) 0xe1,
+ (byte) 0x42, (byte) 0x38, (byte) 0x28, (byte) 0xa3, (byte) 0x54, (byte) 0x56,
+ (byte) 0x31, (byte) 0xaf, (byte) 0x5a, (byte) 0xd6, (byte) 0xf0, (byte) 0x26,
+ (byte) 0xe0, (byte) 0x7a, (byte) 0xd9, (byte) 0x6c, (byte) 0x64, (byte) 0xca,
+ (byte) 0x5d, (byte) 0x6d, (byte) 0x3d, (byte) 0x9a, (byte) 0xfe, (byte) 0x36,
+ (byte) 0x93, (byte) 0x9e, (byte) 0x62, (byte) 0x94, (byte) 0xc6, (byte) 0x07,
+ (byte) 0x83, (byte) 0x96, (byte) 0xd6, (byte) 0x27, (byte) 0xa6, (byte) 0xd8
+ };
+ public static final PrivateKey CLIENT_SUITE_B_RSA3072_KEY =
+ loadPrivateKey("RSA", CLIENT_SUITE_B_RSA3072_KEY_DATA);
+
+ private static final String CLIENT_SUITE_B_ECDSA_CERT_STRING =
+ "-----BEGIN CERTIFICATE-----\n"
+ + "MIIB9zCCAX4CFDpfSZh3AH07BEfGWuMDa7Ynz6y+MAoGCCqGSM49BAMDMF4xCzAJ\n"
+ + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQKDAdB\n"
+ + "bmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4XDTIw\n"
+ + "MDcyMTAyMjk1MFoXDTMwMDUzMDAyMjk1MFowYjELMAkGA1UEBhMCVVMxCzAJBgNV\n"
+ + "BAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsM\n"
+ + "BVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MHYwEAYHKoZIzj0CAQYFK4EE\n"
+ + "ACIDYgAEhxhVJ7dcSqrto0X+dgRxtd8BWG8cWmPjBji3MIxDLfpcMDoIB84ae1Ew\n"
+ + "gJn4YUYHrWsUDiVNihv8j7a/Ol1qcIY2ybH7tbezefLmagqA4vXEUXZXoUyL4ZNC\n"
+ + "DWcdw6LrMAoGCCqGSM49BAMDA2cAMGQCMH4aP73HrriRUJRguiuRic+X4Cqj/7YQ\n"
+ + "ueJmP87KF92/thhoQ9OrRo8uJITPmNDswwIwP2Q1AZCSL4BI9dYrqu07Ar+pSkXE\n"
+ + "R7oOqGdZR+d/MvXcFSrbIaLKEoHXmQamIHLe\n"
+ + "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CLIENT_SUITE_B_ECDSA_CERT =
+ loadCertificate(CLIENT_SUITE_B_ECDSA_CERT_STRING);
+
+ private static final byte[] CLIENT_SUITE_B_ECC_KEY_DATA = new byte[]{
+ (byte) 0x30, (byte) 0x81, (byte) 0xb6, (byte) 0x02, (byte) 0x01, (byte) 0x00,
+ (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x07, (byte) 0x2a, (byte) 0x86,
+ (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x02, (byte) 0x01, (byte) 0x06,
+ (byte) 0x05, (byte) 0x2b, (byte) 0x81, (byte) 0x04, (byte) 0x00, (byte) 0x22,
+ (byte) 0x04, (byte) 0x81, (byte) 0x9e, (byte) 0x30, (byte) 0x81, (byte) 0x9b,
+ (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x04, (byte) 0x30, (byte) 0xea,
+ (byte) 0x6c, (byte) 0x4b, (byte) 0x6d, (byte) 0x43, (byte) 0xf9, (byte) 0x6c,
+ (byte) 0x91, (byte) 0xdc, (byte) 0x2d, (byte) 0x6e, (byte) 0x87, (byte) 0x4f,
+ (byte) 0x0a, (byte) 0x0b, (byte) 0x97, (byte) 0x25, (byte) 0x1c, (byte) 0x79,
+ (byte) 0xa2, (byte) 0x07, (byte) 0xdc, (byte) 0x94, (byte) 0xc2, (byte) 0xee,
+ (byte) 0x64, (byte) 0x51, (byte) 0x6d, (byte) 0x4e, (byte) 0x35, (byte) 0x1c,
+ (byte) 0x22, (byte) 0x2f, (byte) 0xc0, (byte) 0xea, (byte) 0x09, (byte) 0x47,
+ (byte) 0x3e, (byte) 0xb9, (byte) 0xb6, (byte) 0xb8, (byte) 0x83, (byte) 0x9e,
+ (byte) 0xed, (byte) 0x59, (byte) 0xe5, (byte) 0xe7, (byte) 0x0f, (byte) 0xa1,
+ (byte) 0x64, (byte) 0x03, (byte) 0x62, (byte) 0x00, (byte) 0x04, (byte) 0x87,
+ (byte) 0x18, (byte) 0x55, (byte) 0x27, (byte) 0xb7, (byte) 0x5c, (byte) 0x4a,
+ (byte) 0xaa, (byte) 0xed, (byte) 0xa3, (byte) 0x45, (byte) 0xfe, (byte) 0x76,
+ (byte) 0x04, (byte) 0x71, (byte) 0xb5, (byte) 0xdf, (byte) 0x01, (byte) 0x58,
+ (byte) 0x6f, (byte) 0x1c, (byte) 0x5a, (byte) 0x63, (byte) 0xe3, (byte) 0x06,
+ (byte) 0x38, (byte) 0xb7, (byte) 0x30, (byte) 0x8c, (byte) 0x43, (byte) 0x2d,
+ (byte) 0xfa, (byte) 0x5c, (byte) 0x30, (byte) 0x3a, (byte) 0x08, (byte) 0x07,
+ (byte) 0xce, (byte) 0x1a, (byte) 0x7b, (byte) 0x51, (byte) 0x30, (byte) 0x80,
+ (byte) 0x99, (byte) 0xf8, (byte) 0x61, (byte) 0x46, (byte) 0x07, (byte) 0xad,
+ (byte) 0x6b, (byte) 0x14, (byte) 0x0e, (byte) 0x25, (byte) 0x4d, (byte) 0x8a,
+ (byte) 0x1b, (byte) 0xfc, (byte) 0x8f, (byte) 0xb6, (byte) 0xbf, (byte) 0x3a,
+ (byte) 0x5d, (byte) 0x6a, (byte) 0x70, (byte) 0x86, (byte) 0x36, (byte) 0xc9,
+ (byte) 0xb1, (byte) 0xfb, (byte) 0xb5, (byte) 0xb7, (byte) 0xb3, (byte) 0x79,
+ (byte) 0xf2, (byte) 0xe6, (byte) 0x6a, (byte) 0x0a, (byte) 0x80, (byte) 0xe2,
+ (byte) 0xf5, (byte) 0xc4, (byte) 0x51, (byte) 0x76, (byte) 0x57, (byte) 0xa1,
+ (byte) 0x4c, (byte) 0x8b, (byte) 0xe1, (byte) 0x93, (byte) 0x42, (byte) 0x0d,
+ (byte) 0x67, (byte) 0x1d, (byte) 0xc3, (byte) 0xa2, (byte) 0xeb
+ };
+ public static final PrivateKey CLIENT_SUITE_B_ECC_KEY =
+ loadPrivateKey("EC", CLIENT_SUITE_B_ECC_KEY_DATA);
+
private static X509Certificate loadCertificate(String blob) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
@@ -255,9 +662,9 @@ public class FakeKeys {
}
}
- private static PrivateKey loadPrivateRSAKey(byte[] fakeKey) {
+ private static PrivateKey loadPrivateKey(String algorithm, byte[] fakeKey) {
try {
- KeyFactory kf = KeyFactory.getInstance("RSA");
+ KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePrivate(new PKCS8EncodedKeySpec(fakeKey));
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
return null;
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index fc0ef469ad80..6f47f3da710f 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -22,6 +22,8 @@ import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
@@ -35,6 +37,8 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
+import java.security.cert.X509Certificate;
+
/**
* Unit tests for {@link android.net.wifi.WifiNetworkSpecifier}.
*/
@@ -45,6 +49,7 @@ public class WifiNetworkSpecifierTest {
private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
private static final String TEST_BSSID = "12:12:12:12:12:12";
private static final String TEST_PRESHARED_KEY = "\"Test123\"";
+ private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";
/**
* Validate correctness of WifiNetworkSpecifier object created by
@@ -135,6 +140,106 @@ public class WifiNetworkSpecifierTest {
wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method());
}
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertTrue(specifier instanceof WifiNetworkSpecifier);
+ WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+ assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID);
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf);
+ assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+ assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig);
+ }
/**
* Ensure {@link WifiNetworkSpecifier.Builder#setSsid(String)} throws an exception
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 7d5a45216fc4..abb9ce676262 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -32,6 +32,8 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
+import java.security.cert.X509Certificate;
+
/**
* Unit tests for {@link android.net.wifi.WifiNetworkSuggestion}.
*/
@@ -212,16 +214,14 @@ public class WifiNetworkSuggestionTest {
assertNull(suggestion.getEnterpriseConfig());
}
-
/**
* Validate correctness of WifiNetworkSuggestion object created by
- * {@link WifiNetworkSuggestion.Builder#build()} for SuiteB network.
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network.
*/
@Test
public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
- enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
@@ -232,6 +232,78 @@ public class WifiNetworkSuggestionTest {
assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertFalse(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.CCMP));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+ .get(WifiConfiguration.GroupCipher.GCMP_256));
+ assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers
+ .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested
+ // here.
+ assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+ enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY,
+ new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT});
+
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
.get(WifiConfiguration.KeyMgmt.SUITE_B_192));
assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
.get(WifiConfiguration.GroupCipher.GCMP_256));
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 43d728bf593e..3e5ee14be898 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -360,12 +360,18 @@ public class WifiAwareManagerTest {
eq(publishConfig));
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
- // (5) terminate
+ // (5) discovery session is no longer visible
+ sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture());
+ assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId);
+
+ // (6) terminate
publishSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
- // (6) try an update (nothing)
+ // (7) try an update (nothing)
publishSession.getValue().updatePublish(publishConfig);
mMockLooper.dispatchAll();
@@ -502,12 +508,18 @@ public class WifiAwareManagerTest {
eq(subscribeConfig));
inOrder.verify(mockSessionCallback).onSessionConfigFailed();
- // (5) terminate
+ // (5) discovery session is no longer visible
+ sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId);
+ mMockLooper.dispatchAll();
+ inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture());
+ assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId);
+
+ // (6) terminate
subscribeSession.getValue().close();
mMockLooper.dispatchAll();
inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
- // (6) try an update (nothing)
+ // (7) try an update (nothing)
subscribeSession.getValue().updateSubscribe(subscribeConfig);
mMockLooper.dispatchAll();