summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp27
-rw-r--r--api/current.txt2
-rw-r--r--api/module-lib-current.txt1
-rwxr-xr-xapi/system-current.txt2
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp4
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h3
-rw-r--r--core/java/android/app/ActivityThread.java18
-rw-r--r--core/java/android/app/AppOpsManager.java6
-rw-r--r--core/java/android/app/ContextImpl.java5
-rw-r--r--core/java/android/app/IActivityManager.aidl4
-rw-r--r--core/java/android/app/IUiAutomationConnection.aidl2
-rw-r--r--core/java/android/app/ResourcesManager.java276
-rw-r--r--core/java/android/app/UiAutomation.java2
-rw-r--r--core/java/android/app/UiAutomationConnection.java12
-rw-r--r--core/java/android/content/LocusId.java2
-rw-r--r--core/java/android/content/res/XmlBlock.java7
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java7
-rw-r--r--core/java/android/hardware/face/FaceManager.java6
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java37
-rw-r--r--core/java/android/os/INetworkManagementService.aidl4
-rw-r--r--core/java/android/os/Parcelable.java1
-rw-r--r--core/java/android/os/PowerManagerInternal.java4
-rw-r--r--core/java/android/os/SystemClock.java9
-rw-r--r--core/java/android/view/SurfaceControl.java167
-rw-r--r--core/java/android/view/textclassifier/TextClassificationSession.java90
-rw-r--r--core/java/android/widget/Editor.java82
-rw-r--r--core/java/android/widget/Magnifier.java53
-rw-r--r--core/java/com/android/internal/BrightnessSynchronizer.java70
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java22
-rw-r--r--core/java/com/android/internal/app/ChooserActivityLogger.java6
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java205
-rw-r--r--core/java/com/android/internal/os/BinderInternal.java3
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogGroup.java (renamed from services/core/java/com/android/server/wm/ProtoLogGroup.java)18
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogImpl.java (renamed from services/core/java/com/android/server/protolog/ProtoLogImpl.java)41
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java (renamed from services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java)17
-rw-r--r--core/java/com/android/internal/protolog/common/BitmaskConversionException.java (renamed from services/core/java/com/android/server/protolog/common/BitmaskConversionException.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/IProtoLogGroup.java (renamed from services/core/java/com/android/server/protolog/common/IProtoLogGroup.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/InvalidFormatStringException.java (renamed from services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/LogDataType.java (renamed from services/core/java/com/android/server/protolog/common/LogDataType.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/ProtoLog.java (renamed from services/core/java/com/android/server/protolog/common/ProtoLog.java)4
-rw-r--r--core/java/com/android/internal/util/StatLogger.java2
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl5
-rw-r--r--core/java/com/android/internal/widget/LockPatternChecker.java53
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java86
-rw-r--r--core/java/com/android/internal/widget/LockscreenCredential.java2
-rw-r--r--core/java/com/android/internal/widget/VerifyCredentialResponse.java166
-rw-r--r--core/jni/android_os_SystemClock.cpp7
-rw-r--r--core/jni/android_view_DisplayEventReceiver.cpp1
-rw-r--r--core/jni/android_view_SurfaceControl.cpp5
-rw-r--r--core/jni/core_jni_helpers.h25
-rw-r--r--core/proto/android/app/settings_enums.proto5
-rw-r--r--core/proto/android/internal/protolog.proto (renamed from core/proto/android/server/protolog.proto)2
-rw-r--r--core/res/res/values-ca/strings.xml8
-rw-r--r--core/res/res/values-ne/strings.xml2
-rw-r--r--core/res/res/values/donottranslate.xml2
-rw-r--r--core/res/res/values/ids.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/app/WindowContextTest.java2
-rw-r--r--core/tests/coretests/src/android/view/WindowMetricsTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java48
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java13
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java59
-rw-r--r--data/keyboards/Generic.kl8
-rw-r--r--framework-jarjar-rules.txt4
-rw-r--r--graphics/java/android/graphics/HardwareRenderer.java15
-rw-r--r--libs/hwui/OWNERS7
-rw-r--r--libs/hwui/Properties.cpp1
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp6
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp1
-rw-r--r--libs/hwui/utils/Color.cpp7
-rw-r--r--libs/input/Android.bp3
-rw-r--r--libs/input/MouseCursorController.cpp460
-rw-r--r--libs/input/MouseCursorController.h111
-rw-r--r--libs/input/PointerController.cpp758
-rw-r--r--libs/input/PointerController.h165
-rw-r--r--libs/input/PointerControllerContext.cpp179
-rw-r--r--libs/input/PointerControllerContext.h154
-rw-r--r--libs/input/TouchSpotController.cpp236
-rw-r--r--libs/input/TouchSpotController.h91
-rw-r--r--libs/input/tests/PointerController_test.cpp6
-rw-r--r--media/java/android/media/AudioDeviceInfo.java33
-rw-r--r--media/java/android/media/AudioDevicePort.java4
-rwxr-xr-xmedia/java/android/media/AudioManager.java20
-rw-r--r--media/java/android/media/AudioSystem.java30
-rw-r--r--media/java/android/media/MediaTranscodeManager.java41
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java28
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java59
-rw-r--r--non-updatable-api/current.txt2
-rw-r--r--non-updatable-api/module-lib-current.txt1
-rw-r--r--non-updatable-api/system-current.txt2
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/Android.bp27
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml24
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/res/values/config.xml47
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml33
-rw-r--r--packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java35
-rw-r--r--packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java8
-rw-r--r--packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java10
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java45
-rw-r--r--packages/Shell/src/com/android/shell/Screenshooter.java28
-rw-r--r--packages/SystemUI/res-keyguard/values/styles.xml1
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media.xml26
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media_low.xml26
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml27
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_low.xml18
-rw-r--r--packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml (renamed from packages/SystemUI/res/drawable/tv_ring_white.xml)8
-rw-r--r--packages/SystemUI/res/drawable/tv_volume_dialog_background.xml (renamed from packages/SystemUI/res/drawable/tv_circle_dark.xml)10
-rw-r--r--packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml (renamed from packages/SystemUI/res/drawable/tv_circle_white_translucent.xml)8
-rw-r--r--packages/SystemUI/res/layout-land-television/volume_dialog.xml10
-rw-r--r--packages/SystemUI/res/layout-land-television/volume_dialog_row.xml18
-rw-r--r--packages/SystemUI/res/layout-land/volume_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/tv_audio_recording_indicator.xml40
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_row.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml3
-rw-r--r--packages/SystemUI/res/values-as/strings.xml3
-rw-r--r--packages/SystemUI/res/values-az/strings.xml3
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-be/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml3
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml3
-rw-r--r--packages/SystemUI/res/values-da/strings.xml3
-rw-r--r--packages/SystemUI/res/values-de/strings.xml9
-rw-r--r--packages/SystemUI/res/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es/strings.xml3
-rw-r--r--packages/SystemUI/res/values-et/strings.xml3
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml3
-rw-r--r--packages/SystemUI/res/values-in/strings.xml3
-rw-r--r--packages/SystemUI/res/values-is/strings.xml3
-rw-r--r--packages/SystemUI/res/values-it/strings.xml3
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-km/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml3
-rw-r--r--packages/SystemUI/res/values-land-television/dimens.xml5
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml17
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-or/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml3
-rw-r--r--packages/SystemUI/res/values-si/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml3
-rw-r--r--packages/SystemUI/res/values-te/strings.xml3
-rw-r--r--packages/SystemUI/res/values-television/config.xml3
-rw-r--r--packages/SystemUI/res/values-television/styles.xml4
-rw-r--r--packages/SystemUI/res/values-th/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml4
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml3
-rw-r--r--packages/SystemUI/res/values/colors_tv.xml6
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/res/values/donottranslate.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperEngineCompat.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java122
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java6
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt93
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java28
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java9
-rw-r--r--services/core/Android.bp40
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java142
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java32
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java36
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java7
-rw-r--r--services/core/java/com/android/server/VibratorService.java91
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java10
-rw-r--r--services/core/java/com/android/server/am/BroadcastFilter.java6
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java20
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java100
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java48
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java82
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java20
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java36
-rw-r--r--services/core/java/com/android/server/lights/LightsService.java3
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java18
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java101
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java37
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java18
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java264
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/notification/toast/CustomToastRecord.java7
-rw-r--r--services/core/java/com/android/server/notification/toast/ToastRecord.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java225
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java6
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java5
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java12
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java64
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java74
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java6
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java6
-rw-r--r--services/core/java/com/android/server/wm/BlackFrame.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java29
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java4
-rw-r--r--services/core/java/com/android/server/wm/DragState.java6
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java4
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java8
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java4
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java12
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/SurfaceFreezer.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java12
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java4
-rw-r--r--services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowContainerThumbnail.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowTracing.java2
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp58
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp8
-rw-r--r--services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp27
-rw-r--r--services/core/jni/onload.cpp4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java1116
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java566
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java1613
-rw-r--r--services/incremental/IncrementalService.cpp3
-rw-r--r--services/tests/PackageManagerServiceTests/host/Android.bp1
-rw-r--r--services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt71
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp33
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/AndroidManifest.xml27
-rw-r--r--services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/src/com/android/server/pm/cts/test/deviceside/DeviceSide.kt42
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java16
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml)0
-rw-r--r--services/tests/servicestests/src/com/android/server/VibratorServiceTest.java130
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java164
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java146
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java64
-rw-r--r--services/tests/wmtests/Android.bp32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java68
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java16
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java134
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java117
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java7
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java3
-rw-r--r--tests/Internal/Android.bp1
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java)6
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java)2
-rw-r--r--tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java)2
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt30
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt6
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java3
-rw-r--r--tools/aapt2/cmd/Link.cpp7
-rw-r--r--tools/protologtool/Android.bp2
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/LogParser.kt9
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt2
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt8
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt2
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt20
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt4
395 files changed, 7886 insertions, 5034 deletions
diff --git a/Android.bp b/Android.bp
index 0780f88df7c6..e756b3428164 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1415,3 +1415,30 @@ filegroup {
name: "framework-telephony-jarjar-rules",
srcs: ["telephony/framework-telephony-jarjar-rules.txt"],
}
+
+// protolog start
+filegroup {
+ name: "protolog-common-src",
+ srcs: [
+ "core/java/com/android/internal/protolog/common/**/*.java",
+ ],
+}
+
+java_library {
+ name: "protolog-lib",
+ platform_apis: true,
+ srcs: [
+ "core/java/com/android/internal/protolog/ProtoLogImpl.java",
+ "core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java",
+ ":protolog-common-src",
+ ],
+}
+
+java_library {
+ name: "protolog-groups",
+ srcs: [
+ "core/java/com/android/internal/protolog/ProtoLogGroup.java",
+ ":protolog-common-src",
+ ],
+}
+// protolog end
diff --git a/api/current.txt b/api/current.txt
index b70103b931d4..17fbb55d2f91 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24065,6 +24065,8 @@ package android.media {
method public boolean isSink();
method public boolean isSource();
field public static final int TYPE_AUX_LINE = 19; // 0x13
+ field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+ field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index f53ac8c895ce..b587ea1f3b74 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -94,6 +94,7 @@ package android.os {
}
public interface Parcelable {
+ method public default int getStability();
field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
diff --git a/api/system-current.txt b/api/system-current.txt
index c15c2a817adb..b011e9af40a0 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10491,7 +10491,7 @@ package android.telecom {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
method @Deprecated public android.content.ComponentName getDefaultPhoneApp();
- method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
+ method @Deprecated public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index a6c402ccc075..15e22a3410cf 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -166,7 +166,7 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
- aidl::nullable<std::string>* _aidl_return) {
+ std::optional<std::string>* _aidl_return) {
assert(_aidl_return);
SYSTRACE << "Idmap2Service::createIdmap " << target_apk_path << " " << overlay_apk_path;
_aidl_return->reset();
@@ -214,7 +214,7 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
return error("failed to write to idmap path " + idmap_path);
}
- *_aidl_return = aidl::make_nullable<std::string>(idmap_path);
+ *_aidl_return = idmap_path;
return ok();
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index ea931c936b0e..1a445192aff8 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -21,7 +21,6 @@
#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
-#include <binder/Nullable.h>
#include "android/os/BnIdmap2.h"
@@ -47,7 +46,7 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
binder::Status createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id,
- aidl::nullable<std::string>* _aidl_return) override;
+ std::optional<std::string>* _aidl_return) override;
private:
// Cache the crc of the android framework package since the crc cannot change without a reboot.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7a4f11d0de4d..7cec717f96e0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5128,6 +5128,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
r.setState(ON_DESTROY);
+ mLastReportedWindowingMode.remove(r.activity.getActivityToken());
}
schedulePurgeIdler();
// updatePendingActivityConfiguration() reads from mActivities to update
@@ -5370,16 +5371,8 @@ public final class ActivityThread extends ClientTransactionHandler {
throw e.rethrowFromSystemServer();
}
- // Save the current windowing mode to be restored and compared to the new configuration's
- // windowing mode (needed because we update the last reported windowing mode when launching
- // an activity and we can't tell inside performLaunchActivity whether we are relaunching)
- final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(
- r.activity.getActivityToken(), WINDOWING_MODE_UNDEFINED);
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
- mLastReportedWindowingMode.put(r.activity.getActivityToken(), oldWindowingMode);
- handleWindowingModeChangeIfNeeded(r.activity, r.activity.mCurrentConfig);
-
if (pendingActions != null) {
// Only report a successful relaunch to WindowManager.
pendingActions.setReportRelaunchToWindowManager(true);
@@ -5645,10 +5638,6 @@ public final class ActivityThread extends ClientTransactionHandler {
throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
}
- // multi-window / pip mode changes, if any, should be sent before the configuration change
- // callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
- handleWindowingModeChangeIfNeeded(activity, newConfig);
-
final boolean movedToDifferentDisplay = isDifferentDisplay(activity, displayId);
boolean shouldReportChange = false;
if (activity.mCurrentConfig == null) {
@@ -5702,6 +5691,11 @@ public final class ActivityThread extends ClientTransactionHandler {
}
if (shouldReportChange) {
+ // multi-window / pip mode changes, if any, should be sent before the configuration
+ // change callback, see also
+ // PinnedStackTests#testConfigurationChangeOrderDuringTransition
+ handleWindowingModeChangeIfNeeded(activity, newConfig);
+
activity.mCalled = false;
activity.onConfigurationChanged(configToReport);
if (!activity.mCalled) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b40dd0053846..95136bb46339 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2657,8 +2657,10 @@ public class AppOpsManager {
* @hide
*/
// TODO: this should probably be @SystemApi as well
- public static @NonNull String toReceiverId(@NonNull Object obj) {
- if (obj instanceof PendingIntent) {
+ public static @NonNull String toReceiverId(@Nullable Object obj) {
+ if (obj == null) {
+ return "null";
+ } else if (obj instanceof PendingIntent) {
return toReceiverId((PendingIntent) obj);
} else {
return obj.getClass().getName() + "@" + System.identityHashCode(obj);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9613e58fb943..f6b533434ac2 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1624,8 +1624,9 @@ class ContextImpl extends Context {
}
try {
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
- mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
- filter, broadcastPermission, userId, flags);
+ mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(),
+ AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId,
+ flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 99640118ccdf..93dfc79109a6 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -123,8 +123,8 @@ interface IActivityManager {
in IIntentReceiver receiver, in IntentFilter filter,
in String requiredPermission, int userId, int flags);
Intent registerReceiverWithFeature(in IApplicationThread caller, in String callerPackage,
- in String callingFeatureId, in IIntentReceiver receiver, in IntentFilter filter,
- in String requiredPermission, int userId, int flags);
+ in String callingFeatureId, in String receiverId, in IIntentReceiver receiver,
+ in IntentFilter filter, in String requiredPermission, int userId, int flags);
@UnsupportedAppUsage
void unregisterReceiver(in IIntentReceiver receiver);
/** @deprecated Use {@link #broadcastIntentWithFeature} instead */
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 8c3180b400ef..4c9e400681ee 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -39,7 +39,7 @@ interface IUiAutomationConnection {
boolean injectInputEvent(in InputEvent event, boolean sync);
void syncInputTransactions();
boolean setRotation(int rotation);
- Bitmap takeScreenshot(in Rect crop, int rotation);
+ Bitmap takeScreenshot(in Rect crop);
boolean clearWindowContentFrameStats(int windowId);
WindowContentFrameStats getWindowContentFrameStats(int windowId);
void clearWindowAnimationFrameStats();
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 747789901b9d..fb2120e5a35b 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -39,7 +39,6 @@ import android.os.Trace;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.LruCache;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
@@ -62,7 +61,6 @@ import java.util.List;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.function.Consumer;
-import java.util.function.Predicate;
/** @hide */
public class ResourcesManager {
@@ -129,17 +127,30 @@ public class ResourcesManager {
}
}
- private static final boolean ENABLE_APK_ASSETS_CACHE = false;
-
/**
- * The ApkAssets we are caching and intend to hold strong references to.
+ * Loads {@link ApkAssets} and caches them to prevent their garbage collection while the
+ * instance is alive and reachable.
*/
- private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets =
- (ENABLE_APK_ASSETS_CACHE) ? new LruCache<>(3) : null;
+ private class ApkAssetsSupplier {
+ final ArrayMap<ApkKey, ApkAssets> mLocalCache = new ArrayMap<>();
+
+ /**
+ * Retrieves the {@link ApkAssets} corresponding to the specified key, caches the ApkAssets
+ * within this instance, and inserts the loaded ApkAssets into the {@link #mCachedApkAssets}
+ * cache.
+ */
+ ApkAssets load(final ApkKey apkKey) throws IOException {
+ ApkAssets apkAssets = mLocalCache.get(apkKey);
+ if (apkAssets == null) {
+ apkAssets = loadApkAssets(apkKey);
+ mLocalCache.put(apkKey, apkAssets);
+ }
+ return apkAssets;
+ }
+ }
/**
- * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't
- * in our LRU cache. Bonus resources :)
+ * The ApkAssets that are being referenced in the wild that we can reuse.
*/
private final ArrayMap<ApkKey, WeakReference<ApkAssets>> mCachedApkAssets = new ArrayMap<>();
@@ -228,7 +239,8 @@ public class ResourcesManager {
}
}
- DisplayMetrics getDisplayMetrics() {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public DisplayMetrics getDisplayMetrics() {
return getDisplayMetrics(Display.DEFAULT_DISPLAY,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
@@ -337,113 +349,116 @@ public class ResourcesManager {
return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
}
- private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay)
- throws IOException {
- final ApkKey newKey = new ApkKey(path, sharedLib, overlay);
- ApkAssets apkAssets = null;
- if (mLoadedApkAssets != null) {
- apkAssets = mLoadedApkAssets.get(newKey);
- if (apkAssets != null && apkAssets.isUpToDate()) {
- return apkAssets;
- }
- }
+ private @NonNull ApkAssets loadApkAssets(@NonNull final ApkKey key) throws IOException {
+ ApkAssets apkAssets;
// Optimistically check if this ApkAssets exists somewhere else.
- final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(newKey);
- if (apkAssetsRef != null) {
- apkAssets = apkAssetsRef.get();
- if (apkAssets != null && apkAssets.isUpToDate()) {
- if (mLoadedApkAssets != null) {
- mLoadedApkAssets.put(newKey, apkAssets);
+ synchronized (this) {
+ final WeakReference<ApkAssets> apkAssetsRef = mCachedApkAssets.get(key);
+ if (apkAssetsRef != null) {
+ apkAssets = apkAssetsRef.get();
+ if (apkAssets != null && apkAssets.isUpToDate()) {
+ return apkAssets;
+ } else {
+ // Clean up the reference.
+ mCachedApkAssets.remove(key);
}
-
- return apkAssets;
- } else {
- // Clean up the reference.
- mCachedApkAssets.remove(newKey);
}
}
// We must load this from disk.
- if (overlay) {
- apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(path), 0 /*flags*/);
+ if (key.overlay) {
+ apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(key.path),
+ 0 /*flags*/);
} else {
- apkAssets = ApkAssets.loadFromPath(path, sharedLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
+ apkAssets = ApkAssets.loadFromPath(key.path,
+ key.sharedLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
}
- if (mLoadedApkAssets != null) {
- mLoadedApkAssets.put(newKey, apkAssets);
+ synchronized (this) {
+ mCachedApkAssets.put(key, new WeakReference<>(apkAssets));
}
- mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets));
return apkAssets;
}
/**
- * Creates an AssetManager from the paths within the ResourcesKey.
- *
- * This can be overridden in tests so as to avoid creating a real AssetManager with
- * real APK paths.
- * @param key The key containing the resource paths to add to the AssetManager.
- * @return a new AssetManager.
- */
- @VisibleForTesting
- @UnsupportedAppUsage
- protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
- final AssetManager.Builder builder = new AssetManager.Builder();
+ * Retrieves a list of apk keys representing the ApkAssets that should be loaded for
+ * AssetManagers mapped to the {@param key}.
+ */
+ private static @NonNull ArrayList<ApkKey> extractApkKeys(@NonNull final ResourcesKey key) {
+ final ArrayList<ApkKey> apkKeys = new ArrayList<>();
// resDir can be null if the 'android' package is creating a new Resources object.
// This is fine, since each AssetManager automatically loads the 'android' package
// already.
if (key.mResDir != null) {
- try {
- builder.addApkAssets(loadApkAssets(key.mResDir, false /*sharedLib*/,
- false /*overlay*/));
- } catch (IOException e) {
- Log.e(TAG, "failed to add asset path " + key.mResDir);
- return null;
- }
+ apkKeys.add(new ApkKey(key.mResDir, false /*sharedLib*/, false /*overlay*/));
}
if (key.mSplitResDirs != null) {
for (final String splitResDir : key.mSplitResDirs) {
- try {
- builder.addApkAssets(loadApkAssets(splitResDir, false /*sharedLib*/,
- false /*overlay*/));
- } catch (IOException e) {
- Log.e(TAG, "failed to add split asset path " + splitResDir);
- return null;
- }
+ apkKeys.add(new ApkKey(splitResDir, false /*sharedLib*/, false /*overlay*/));
}
}
if (key.mLibDirs != null) {
for (final String libDir : key.mLibDirs) {
+ // Avoid opening files we know do not have resources, like code-only .jar files.
if (libDir.endsWith(".apk")) {
- // Avoid opening files we know do not have resources,
- // like code-only .jar files.
- try {
- builder.addApkAssets(loadApkAssets(libDir, true /*sharedLib*/,
- false /*overlay*/));
- } catch (IOException e) {
- Log.w(TAG, "Asset path '" + libDir +
- "' does not exist or contains no resources.");
-
- // continue.
- }
+ apkKeys.add(new ApkKey(libDir, true /*sharedLib*/, false /*overlay*/));
}
}
}
if (key.mOverlayDirs != null) {
for (final String idmapPath : key.mOverlayDirs) {
- try {
- builder.addApkAssets(loadApkAssets(idmapPath, false /*sharedLib*/,
- true /*overlay*/));
- } catch (IOException e) {
- Log.w(TAG, "failed to add overlay path " + idmapPath);
+ apkKeys.add(new ApkKey(idmapPath, false /*sharedLib*/, true /*overlay*/));
+ }
+ }
+
+ return apkKeys;
+ }
+
+ /**
+ * Creates an AssetManager from the paths within the ResourcesKey.
+ *
+ * This can be overridden in tests so as to avoid creating a real AssetManager with
+ * real APK paths.
+ * @param key The key containing the resource paths to add to the AssetManager.
+ * @return a new AssetManager.
+ */
+ @VisibleForTesting
+ @UnsupportedAppUsage
+ protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {
+ return createAssetManager(key, /* apkSupplier */ null);
+ }
+
+ /**
+ * Variant of {@link #createAssetManager(ResourcesKey)} that attempts to load ApkAssets
+ * from an {@link ApkAssetsSupplier} if non-null; otherwise ApkAssets are loaded using
+ * {@link #loadApkAssets(ApkKey)}.
+ */
+ private @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key,
+ @Nullable ApkAssetsSupplier apkSupplier) {
+ final AssetManager.Builder builder = new AssetManager.Builder();
- // continue.
+ final ArrayList<ApkKey> apkKeys = extractApkKeys(key);
+ for (int i = 0, n = apkKeys.size(); i < n; i++) {
+ final ApkKey apkKey = apkKeys.get(i);
+ try {
+ builder.addApkAssets(
+ (apkSupplier != null) ? apkSupplier.load(apkKey) : loadApkAssets(apkKey));
+ } catch (IOException e) {
+ if (apkKey.overlay) {
+ Log.w(TAG, String.format("failed to add overlay path '%s'", apkKey.path), e);
+ } else if (apkKey.sharedLib) {
+ Log.w(TAG, String.format(
+ "asset path '%s' does not exist or contains no resources",
+ apkKey.path), e);
+ } else {
+ Log.e(TAG, String.format("failed to add asset path '%s'", apkKey.path), e);
+ return null;
}
}
}
@@ -480,24 +495,6 @@ public class ResourcesManager {
pw.println("ResourcesManager:");
pw.increaseIndent();
- if (mLoadedApkAssets != null) {
- pw.print("cached apks: total=");
- pw.print(mLoadedApkAssets.size());
- pw.print(" created=");
- pw.print(mLoadedApkAssets.createCount());
- pw.print(" evicted=");
- pw.print(mLoadedApkAssets.evictionCount());
- pw.print(" hit=");
- pw.print(mLoadedApkAssets.hitCount());
- pw.print(" miss=");
- pw.print(mLoadedApkAssets.missCount());
- pw.print(" max=");
- pw.print(mLoadedApkAssets.maxSize());
- } else {
- pw.print("cached apks: 0 [cache disabled]");
- }
- pw.println();
-
pw.print("total apks: ");
pw.println(countLiveReferences(mCachedApkAssets.values()));
@@ -533,11 +530,12 @@ public class ResourcesManager {
return config;
}
- private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
+ private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key,
+ @Nullable ApkAssetsSupplier apkSupplier) {
final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
daj.setCompatibilityInfo(key.mCompatInfo);
- final AssetManager assets = createAssetManager(key);
+ final AssetManager assets = createAssetManager(key, apkSupplier);
if (assets == null) {
return null;
}
@@ -575,9 +573,18 @@ public class ResourcesManager {
*/
private @Nullable ResourcesImpl findOrCreateResourcesImplForKeyLocked(
@NonNull ResourcesKey key) {
+ return findOrCreateResourcesImplForKeyLocked(key, /* apkSupplier */ null);
+ }
+
+ /**
+ * Variant of {@link #findOrCreateResourcesImplForKeyLocked(ResourcesKey)} that attempts to
+ * load ApkAssets from a {@link ApkAssetsSupplier} when creating a new ResourcesImpl.
+ */
+ private @Nullable ResourcesImpl findOrCreateResourcesImplForKeyLocked(
+ @NonNull ResourcesKey key, @Nullable ApkAssetsSupplier apkSupplier) {
ResourcesImpl impl = findResourcesImplForKeyLocked(key);
if (impl == null) {
- impl = createResourcesImpl(key);
+ impl = createResourcesImpl(key, apkSupplier);
if (impl != null) {
mResourceImpls.put(key, new WeakReference<>(impl));
}
@@ -766,7 +773,7 @@ public class ResourcesManager {
}
// Now request an actual Resources object.
- return createResources(token, key, classLoader);
+ return createResources(token, key, classLoader, /* apkSupplier */ null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -810,18 +817,50 @@ public class ResourcesManager {
}
/**
+ * Creates an {@link ApkAssetsSupplier} and loads all the ApkAssets required by the {@param key}
+ * into the supplier. This should be done while the lock is not held to prevent performing I/O
+ * while holding the lock.
+ */
+ private @NonNull ApkAssetsSupplier createApkAssetsSupplierNotLocked(@NonNull ResourcesKey key) {
+ Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
+ "ResourcesManager#createApkAssetsSupplierNotLocked");
+ try {
+ if (Thread.holdsLock(this)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
+ + " is holding mLock", new Throwable());
+ }
+
+ final ApkAssetsSupplier supplier = new ApkAssetsSupplier();
+ final ArrayList<ApkKey> apkKeys = extractApkKeys(key);
+ for (int i = 0, n = apkKeys.size(); i < n; i++) {
+ final ApkKey apkKey = apkKeys.get(i);
+ try {
+ supplier.load(apkKey);
+ } catch (IOException e) {
+ Log.w(TAG, String.format("failed to preload asset path '%s'", apkKey.path), e);
+ }
+ }
+ return supplier;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ }
+ }
+
+ /**
* Creates a Resources object set with a ResourcesImpl object matching the given key.
*
* @param activityToken The Activity this Resources object should be associated with.
* @param key The key describing the parameters of the ResourcesImpl object.
* @param classLoader The classloader to use for the Resources object.
* If null, {@link ClassLoader#getSystemClassLoader()} is used.
+ * @param apkSupplier The apk assets supplier to use when creating a new ResourcesImpl object.
* @return A Resources object that gets updated when
* {@link #applyConfigurationToResourcesLocked(Configuration, CompatibilityInfo)}
* is called.
*/
private @Nullable Resources createResources(@Nullable IBinder activityToken,
- @NonNull ResourcesKey key, @NonNull ClassLoader classLoader) {
+ @NonNull ResourcesKey key, @NonNull ClassLoader classLoader,
+ @Nullable ApkAssetsSupplier apkSupplier) {
synchronized (this) {
if (DEBUG) {
Throwable here = new Throwable();
@@ -829,7 +868,7 @@ public class ResourcesManager {
Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
}
- ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key);
+ ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key, apkSupplier);
if (resourcesImpl == null) {
return null;
}
@@ -898,7 +937,10 @@ public class ResourcesManager {
rebaseKeyForActivity(activityToken, key);
}
- return createResources(activityToken, key, classLoader);
+ // Preload the ApkAssets required by the key to prevent performing heavy I/O while the
+ // ResourcesManager lock is held.
+ final ApkAssetsSupplier assetsSupplier = createApkAssetsSupplierNotLocked(key);
+ return createResources(activityToken, key, classLoader, assetsSupplier);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -969,7 +1011,13 @@ public class ResourcesManager {
final ResourcesKey newKey = rebaseActivityOverrideConfig(resources, oldConfig,
overrideConfig, displayId);
if (newKey != null) {
- updateActivityResources(resources, newKey, false);
+ final ResourcesImpl resourcesImpl =
+ findOrCreateResourcesImplForKeyLocked(newKey);
+ if (resourcesImpl != null && resourcesImpl != resources.getImpl()) {
+ // Set the ResourcesImpl, updating it for all users of this Resources
+ // object.
+ resources.setImpl(resourcesImpl);
+ }
}
}
}
@@ -1024,24 +1072,6 @@ public class ResourcesManager {
return newKey;
}
- private void updateActivityResources(Resources resources, ResourcesKey newKey,
- boolean hasLoader) {
- final ResourcesImpl resourcesImpl;
-
- if (hasLoader) {
- // Loaders always get new Impls because they cannot be shared
- resourcesImpl = createResourcesImpl(newKey);
- } else {
- resourcesImpl = findOrCreateResourcesImplForKeyLocked(newKey);
- }
-
- if (resourcesImpl != null && resourcesImpl != resources.getImpl()) {
- // Set the ResourcesImpl, updating it for all users of this Resources
- // object.
- resources.setImpl(resourcesImpl);
- }
- }
-
public final boolean applyConfigurationToResources(@NonNull Configuration config,
@Nullable CompatibilityInfo compat) {
synchronized(this) {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index e0951bf3f4d2..109205fadf18 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -903,7 +903,7 @@ public final class UiAutomation {
try {
// Calling out without a lock held.
screenShot = mUiAutomationConnection.takeScreenshot(
- new Rect(0, 0, displaySize.x, displaySize.y), rotation);
+ new Rect(0, 0, displaySize.x, displaySize.y));
if (screenShot == null) {
return null;
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index ce51dba76780..70d520176ca1 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -180,7 +180,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
@Override
- public Bitmap takeScreenshot(Rect crop, int rotation) {
+ public Bitmap takeScreenshot(Rect crop) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
@@ -190,7 +190,15 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
try {
int width = crop.width();
int height = crop.height();
- return SurfaceControl.screenshot(crop, width, height, rotation);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setSourceCrop(crop)
+ .setSize(width, height)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java
index 283cea00b192..98e71f07407e 100644
--- a/core/java/android/content/LocusId.java
+++ b/core/java/android/content/LocusId.java
@@ -33,7 +33,7 @@ import java.io.PrintWriter;
* by the Android System to correlate state between different subsystems such as content capture,
* shortcuts, and notifications.
*
- * <p>For example, if your app provides an activiy representing a chat between 2 users
+ * <p>For example, if your app provides an activity representing a chat between 2 users
* (say {@code A} and {@code B}, this chat state could be represented by:
*
* <pre><code>
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index cb93cbfcbfc9..fcbe36246273 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.TypedValue;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import dalvik.annotation.optimization.FastNative;
@@ -38,7 +39,8 @@ import java.io.Reader;
*
* {@hide}
*/
-final class XmlBlock implements AutoCloseable {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class XmlBlock implements AutoCloseable {
private static final boolean DEBUG=false;
@UnsupportedAppUsage
@@ -88,7 +90,8 @@ final class XmlBlock implements AutoCloseable {
}
}
- /*package*/ final class Parser implements XmlResourceParser {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public final class Parser implements XmlResourceParser {
Parser(long parseState, XmlBlock block) {
mParseState = parseState;
mBlock = block;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 7ac8d052ea86..c7f89151624d 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -260,6 +260,13 @@ public abstract class DisplayManagerInternal {
int displayId, long maxFrames, long timestamp);
/**
+ * Temporarily ignore proximity-sensor-based display behavior until there is a change
+ * to the proximity sensor state. This allows the display to turn back on even if something
+ * is obstructing the proximity sensor.
+ */
+ public abstract void ignoreProximitySensorUntilChanged();
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 885d137dd2fe..19cb13c7e114 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -1073,12 +1073,12 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
/**
* @hide
*/
- public abstract static class GenerateChallengeCallback {
- public abstract void onGenerateChallengeResult(long challenge);
+ public interface GenerateChallengeCallback {
+ void onGenerateChallengeResult(long challenge);
}
private abstract static class InternalGenerateChallengeCallback
- extends GenerateChallengeCallback {}
+ implements GenerateChallengeCallback {}
private class OnEnrollCancelListener implements OnCancelListener {
@Override
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index e384da7574ad..71598eb6394f 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -377,12 +377,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* @hide
*/
- public abstract static class GenerateChallengeCallback {
- public abstract void onChallengeGenerated(long challenge);
+ public interface GenerateChallengeCallback {
+ void onChallengeGenerated(long challenge);
}
private abstract static class InternalGenerateChallengeCallback
- extends GenerateChallengeCallback {}
+ implements GenerateChallengeCallback {}
/**
* Request authentication of a crypto object. This call warms up the fingerprint hardware
@@ -581,37 +581,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
/**
- * Same as {@link #generateChallenge(GenerateChallengeCallback)}, except blocks until the
- * TEE/hardware operation is complete.
- * @return challenge generated in the TEE/hardware
- * @hide
- */
- @RequiresPermission(MANAGE_FINGERPRINT)
- public long generateChallengeBlocking() {
- final AtomicReference<Long> result = new AtomicReference<>();
- final CountDownLatch latch = new CountDownLatch(1);
- final GenerateChallengeCallback callback = new InternalGenerateChallengeCallback() {
- @Override
- public void onChallengeGenerated(long challenge) {
- result.set(challenge);
- latch.countDown();
- }
- };
-
- generateChallenge(callback);
-
- try {
- latch.await(1, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- Slog.e(TAG, "Interrupted while generatingChallenge", e);
- e.printStackTrace();
- }
-
- return result.get();
- }
-
-
- /**
* Generates a unique random challenge in the TEE. A typical use case is to have it wrapped in a
* HardwareAuthenticationToken, minted by Gatekeeper upon PIN/Pattern/Password verification.
* The HardwareAuthenticationToken can then be sent to the biometric HAL together with a
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 0cce19222d27..8f8d451bbe8e 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -287,8 +287,8 @@ interface INetworkManagementService
/**
* Control network activity of a UID over interfaces with a quota limit.
*/
- void setUidMeteredNetworkBlacklist(int uid, boolean enable);
- void setUidMeteredNetworkWhitelist(int uid, boolean enable);
+ void setUidMeteredNetworkDenylist(int uid, boolean enable);
+ void setUidMeteredNetworkAllowlist(int uid, boolean enable);
boolean setDataSaverModeEnabled(boolean enable);
void setUidCleartextNetworkPolicy(int uid, int policy);
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index 3d3759e695e0..f14f66b07630 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -161,6 +161,7 @@ public interface Parcelable {
* @return true if this parcelable is stable.
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
default @Stability int getStability() {
return PARCELABLE_STABILITY_LOCAL;
}
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index e30a40964992..eb18b96e255b 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -17,6 +17,7 @@
package android.os;
import android.view.Display;
+import android.view.KeyEvent;
import java.util.function.Consumer;
@@ -313,4 +314,7 @@ public abstract class PowerManagerInternal {
/** Returns information about the last wakeup event. */
public abstract PowerManager.WakeData getLastWakeup();
+
+ /** Allows power button to intercept a power key button press. */
+ public abstract boolean interceptPowerKeyDown(KeyEvent event);
}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index fd68c2b9b5fd..26f3af0c68bb 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -178,6 +178,15 @@ public final class SystemClock {
native public static long uptimeMillis();
/**
+ * Returns nanoseconds since boot, not counting time spent in deep sleep.
+ *
+ * @return nanoseconds of non-sleep uptime since boot.
+ * @hide
+ */
+ @CriticalNative
+ public static native long uptimeNanos();
+
+ /**
* Return {@link Clock} that starts at system boot, not counting time spent
* in deep sleep.
*
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2ce993dfedca..6ef086b55c41 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -22,8 +22,6 @@ import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static android.view.SurfaceControlProto.HASH_CODE;
import static android.view.SurfaceControlProto.NAME;
@@ -590,6 +588,26 @@ public final class SurfaceControl implements Parcelable {
public boolean containsSecureLayers() {
return mContainsSecureLayers;
}
+
+ /**
+ * Copy content of ScreenshotHardwareBuffer into a hardware bitmap and return it.
+ * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
+ * into
+ * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
+ *
+ * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
+ * directly
+ * use the {@link HardwareBuffer} directly.
+ *
+ * @return Bitmap generated from the {@link HardwareBuffer}
+ */
+ public Bitmap asBitmap() {
+ if (mHardwareBuffer == null) {
+ Log.w(TAG, "Failed to take screenshot. Null screenshot object");
+ return null;
+ }
+ return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace);
+ }
}
/**
@@ -597,7 +615,7 @@ public final class SurfaceControl implements Parcelable {
* are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
* @hide
*/
- public abstract static class CaptureArgs {
+ private abstract static class CaptureArgs {
private final int mPixelFormat;
private final Rect mSourceCrop = new Rect();
private final float mFrameScale;
@@ -615,7 +633,7 @@ public final class SurfaceControl implements Parcelable {
*
* @param <T> A builder that extends {@link Builder}
*/
- public abstract static class Builder<T extends Builder<T>> {
+ abstract static class Builder<T extends Builder<T>> {
private int mPixelFormat = PixelFormat.RGBA_8888;
private final Rect mSourceCrop = new Rect();
private float mFrameScale = 1;
@@ -675,7 +693,6 @@ public final class SurfaceControl implements Parcelable {
private final int mWidth;
private final int mHeight;
private final boolean mUseIdentityTransform;
- private final int mRotation;
private DisplayCaptureArgs(Builder builder) {
super(builder);
@@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable {
mWidth = builder.mWidth;
mHeight = builder.mHeight;
mUseIdentityTransform = builder.mUseIdentityTransform;
- mRotation = builder.mRotation;
}
/**
@@ -694,7 +710,6 @@ public final class SurfaceControl implements Parcelable {
private int mWidth;
private int mHeight;
private boolean mUseIdentityTransform;
- private @Surface.Rotation int mRotation = Surface.ROTATION_0;
/**
* Construct a new {@link LayerCaptureArgs} with the set parameters. The builder
@@ -736,26 +751,16 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * Replace whatever transformation (rotation, scaling, translation) the surface
- * layers are currently using with the identity transformation while taking the
- * screenshot.
+ * Replace the rotation transform of the display with the identity transformation while
+ * taking the screenshot. This ensures the screenshot is taken in the ROTATION_0
+ * orientation. Set this value to false if the screenshot should be taken in the
+ * current screen orientation.
*/
public Builder setUseIdentityTransform(boolean useIdentityTransform) {
mUseIdentityTransform = useIdentityTransform;
return this;
}
- /**
- * Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take screenshots in its
- * native portrait orientation by default, so this is useful for returning screenshots
- * that are independent of device orientation.
- */
- public Builder setRotation(@Surface.Rotation int rotation) {
- mRotation = rotation;
- return this;
- }
-
@Override
Builder getThis() {
return this;
@@ -2221,130 +2226,16 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
- * @hide
- */
- @UnsupportedAppUsage
- public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
- return screenshot(sourceCrop, width, height, false, rotation);
- }
-
- /**
- * Copy the current screen contents into a hardware bitmap and return it.
- * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
- * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
+ * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
+ * the content.
*
- * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
- * unless absolutely necessary; prefer the versions that use a {@link HardwareBuffer} such as
- * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
- *
- * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
* @hide
*/
- @UnsupportedAppUsage
- public static Bitmap screenshot(Rect sourceCrop, int width, int height,
- boolean useIdentityTransform, int rotation) {
- // TODO: should take the display as a parameter
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- if (displayToken == null) {
- Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
- return null;
- }
-
- if (rotation == ROTATION_90 || rotation == ROTATION_270) {
- rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
- }
-
- SurfaceControl.rotateCropForSF(sourceCrop, rotation);
- final ScreenshotHardwareBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
- height, useIdentityTransform, rotation);
-
- if (buffer == null) {
- Log.w(TAG, "Failed to take screenshot");
- return null;
- }
- return Bitmap.wrapHardwareBuffer(buffer.getHardwareBuffer(), buffer.getColorSpace());
- }
-
- /**
- * Captures all the surfaces in a display and returns a {@link HardwareBuffer} with the content.
- *
- * @param display The display to take the screenshot of.
- * @param sourceCrop The portion of the screen to capture into the Bitmap; caller may
- * pass in 'new Rect()' if no cropping is desired.
- * @param width The desired width of the returned bitmap; the raw screen will be
- * scaled down to this size; caller may pass in 0 if no scaling is
- * desired.
- * @param height The desired height of the returned bitmap; the raw screen will
- * be scaled down to this size; caller may pass in 0 if no scaling
- * is desired.
- * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation)
- * the surface layers are currently using with the identity
- * transformation while taking the screenshot.
- * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take
- * screenshots in its native portrait orientation by default, so
- * this is useful for returning screenshots that are independent of
- * device orientation.
- * @return Returns a HardwareBuffer that contains the captured content.
- * @hide
- */
- public static ScreenshotHardwareBuffer screenshotToBuffer(IBinder display, Rect sourceCrop,
- int width, int height, boolean useIdentityTransform, int rotation) {
- if (display == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
-
- DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
- .setSourceCrop(sourceCrop)
- .setSize(width, height)
- .setUseIdentityTransform(useIdentityTransform)
- .setRotation(rotation)
- .build();
-
+ public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
return nativeCaptureDisplay(captureArgs);
}
/**
- * Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows
- * for the capture of secure layers. This is used for the screen rotation
- * animation where the system server takes screenshots but does
- * not persist them or allow them to leave the server. However in other
- * cases in the system server, we mostly want to omit secure layers
- * like when we take a screenshot on behalf of the assistant.
- *
- * @hide
- */
- public static ScreenshotHardwareBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display,
- Rect sourceCrop, int width, int height, boolean useIdentityTransform,
- int rotation) {
- if (display == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
-
- DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
- .setSourceCrop(sourceCrop)
- .setSize(width, height)
- .setUseIdentityTransform(useIdentityTransform)
- .setRotation(rotation)
- .setCaptureSecureLayers(true)
- .build();
-
- return nativeCaptureDisplay(captureArgs);
- }
-
- private static void rotateCropForSF(Rect crop, int rot) {
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- int tmp = crop.top;
- crop.top = crop.left;
- crop.left = tmp;
- tmp = crop.right;
- crop.right = crop.bottom;
- crop.bottom = tmp;
- }
- }
-
- /**
* Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
*
* @param layer The root layer to capture.
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index fed3dbf8f49c..00086587819f 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -20,9 +20,11 @@ import android.annotation.NonNull;
import android.annotation.WorkerThread;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.Objects;
+import java.util.function.Supplier;
import sun.misc.Cleaner;
@@ -40,6 +42,9 @@ final class TextClassificationSession implements TextClassifier {
private final TextClassificationContext mClassificationContext;
private final Cleaner mCleaner;
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
private boolean mDestroyed;
TextClassificationSession(TextClassificationContext context, TextClassifier delegate) {
@@ -54,8 +59,7 @@ final class TextClassificationSession implements TextClassifier {
@Override
public TextSelection suggestSelection(TextSelection.Request request) {
- checkDestroyed();
- return mDelegate.suggestSelection(request);
+ return checkDestroyedAndRun(() -> mDelegate.suggestSelection(request));
}
private void initializeRemoteSession() {
@@ -67,77 +71,97 @@ final class TextClassificationSession implements TextClassifier {
@Override
public TextClassification classifyText(TextClassification.Request request) {
- checkDestroyed();
- return mDelegate.classifyText(request);
+ return checkDestroyedAndRun(() -> mDelegate.classifyText(request));
}
@Override
public TextLinks generateLinks(TextLinks.Request request) {
- checkDestroyed();
- return mDelegate.generateLinks(request);
+ return checkDestroyedAndRun(() -> mDelegate.generateLinks(request));
}
@Override
public ConversationActions suggestConversationActions(ConversationActions.Request request) {
- checkDestroyed();
- return mDelegate.suggestConversationActions(request);
+ return checkDestroyedAndRun(() -> mDelegate.suggestConversationActions(request));
}
@Override
public TextLanguage detectLanguage(TextLanguage.Request request) {
- checkDestroyed();
- return mDelegate.detectLanguage(request);
+ return checkDestroyedAndRun(() -> mDelegate.detectLanguage(request));
}
@Override
public int getMaxGenerateLinksTextLength() {
- checkDestroyed();
- return mDelegate.getMaxGenerateLinksTextLength();
+ return checkDestroyedAndRun(mDelegate::getMaxGenerateLinksTextLength);
}
@Override
public void onSelectionEvent(SelectionEvent event) {
- try {
- if (mEventHelper.sanitizeEvent(event)) {
- mDelegate.onSelectionEvent(event);
+ checkDestroyedAndRun(() -> {
+ try {
+ if (mEventHelper.sanitizeEvent(event)) {
+ mDelegate.onSelectionEvent(event);
+ }
+ } catch (Exception e) {
+ // Avoid crashing for event reporting.
+ Log.e(LOG_TAG, "Error reporting text classifier selection event", e);
}
- } catch (Exception e) {
- // Avoid crashing for event reporting.
- Log.e(LOG_TAG, "Error reporting text classifier selection event", e);
- }
+ return null;
+ });
}
@Override
public void onTextClassifierEvent(TextClassifierEvent event) {
- try {
- event.mHiddenTempSessionId = mSessionId;
- mDelegate.onTextClassifierEvent(event);
- } catch (Exception e) {
- // Avoid crashing for event reporting.
- Log.e(LOG_TAG, "Error reporting text classifier event", e);
- }
+ checkDestroyedAndRun(() -> {
+ try {
+ event.mHiddenTempSessionId = mSessionId;
+ mDelegate.onTextClassifierEvent(event);
+ } catch (Exception e) {
+ // Avoid crashing for event reporting.
+ Log.e(LOG_TAG, "Error reporting text classifier event", e);
+ }
+ return null;
+ });
}
@Override
public void destroy() {
- mCleaner.clean();
- mDestroyed = true;
+ synchronized (mLock) {
+ if (!mDestroyed) {
+ mCleaner.clean();
+ mDestroyed = true;
+ }
+ }
}
@Override
public boolean isDestroyed() {
- return mDestroyed;
+ synchronized (mLock) {
+ return mDestroyed;
+ }
}
/**
- * @throws IllegalStateException if this TextClassification session has been destroyed.
+ * Check whether the TextClassification Session was destroyed before and after the actual API
+ * invocation, and return response if not.
+ *
+ * @param responseSupplier a Supplier that represents a TextClassifier call
+ * @return the response of the TextClassifier call
+ * @throws IllegalStateException if this TextClassification session was destroyed before the
+ * call returned
* @see #isDestroyed()
* @see #destroy()
*/
- private void checkDestroyed() {
- if (mDestroyed) {
- throw new IllegalStateException("This TextClassification session has been destroyed");
+ private <T> T checkDestroyedAndRun(Supplier<T> responseSupplier) {
+ if (!isDestroyed()) {
+ T response = responseSupplier.get();
+ synchronized (mLock) {
+ if (!mDestroyed) {
+ return response;
+ }
+ }
}
+ throw new IllegalStateException(
+ "This TextClassification session has been destroyed");
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 7683067958d8..60f8bb7ebe6c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -154,6 +154,10 @@ public class Editor {
// Specifies whether to use the magnifier when pressing the insertion or selection handles.
private static final boolean FLAG_USE_MAGNIFIER = true;
+ // Specifies how far to make the cursor start float when drag the cursor away from the
+ // beginning or end of the line.
+ private static final int CURSOR_START_FLOAT_DISTANCE_PX = 20;
+
private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
private static final int RECENT_CUT_COPY_DURATION_MS = 15 * 1000; // 15 seconds in millis
@@ -289,6 +293,9 @@ public class Editor {
private boolean mRenderCursorRegardlessTiming;
private Blink mBlink;
+ // Whether to let magnifier draw cursor on its surface. This is for floating cursor effect.
+ // And it can only be true when |mNewMagnifierEnabled| is true.
+ private boolean mDrawCursorOnMagnifier;
boolean mCursorVisible = true;
boolean mSelectAllOnFocus;
boolean mTextIsSelectable;
@@ -890,7 +897,7 @@ public class Editor {
}
boolean enabled = windowSupportsHandles && mTextView.getLayout() != null;
- mInsertionControllerEnabled = enabled && isCursorVisible();
+ mInsertionControllerEnabled = enabled && (mDrawCursorOnMagnifier || isCursorVisible());
mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected();
if (!mInsertionControllerEnabled) {
@@ -5101,26 +5108,38 @@ public class Editor {
final int[] textViewLocationOnScreen = new int[2];
mTextView.getLocationOnScreen(textViewLocationOnScreen);
final float touchXInView = event.getRawX() - textViewLocationOnScreen[0];
- float leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- float rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) {
- leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
- } else {
- leftBound += mTextView.getLayout().getLineLeft(lineNumber);
- }
- if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) {
- rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ float leftBound, rightBound;
+ if (mNewMagnifierEnabled) {
+ leftBound = 0;
+ rightBound = mTextView.getWidth();
+ if (touchXInView < leftBound || touchXInView > rightBound) {
+ // The touch is too far from the current line / selection, so hide the magnifier.
+ return false;
+ }
} else {
- rightBound += mTextView.getLayout().getLineRight(lineNumber);
- }
- leftBound *= mTextViewScaleX;
- rightBound *= mTextViewScaleX;
- final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
- / mMagnifierAnimator.mMagnifier.getZoom());
- if (touchXInView < leftBound - contentWidth / 2
- || touchXInView > rightBound + contentWidth / 2) {
- // The touch is too far from the current line / selection, so hide the magnifier.
- return false;
+ leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END)
+ ^ rtl)) {
+ leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ leftBound += mTextView.getLayout().getLineLeft(lineNumber);
+ }
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START)
+ ^ rtl)) {
+ rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ rightBound += mTextView.getLayout().getLineRight(lineNumber);
+ }
+ leftBound *= mTextViewScaleX;
+ rightBound *= mTextViewScaleX;
+ final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
+ / mMagnifierAnimator.mMagnifier.getZoom());
+ if (touchXInView < leftBound - contentWidth / 2
+ || touchXInView > rightBound + contentWidth / 2) {
+ // The touch is too far from the current line / selection, so hide the magnifier.
+ return false;
+ }
}
final float scaledTouchXInView;
@@ -5178,7 +5197,8 @@ public class Editor {
final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y,
magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(),
magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight());
- setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect));
+ setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect)
+ && !mDrawCursorOnMagnifier);
final HandleView otherHandle = getOtherSelectionHandle();
if (otherHandle != null) {
otherHandle.setVisible(!handleOverlapsMagnifier(otherHandle, magnifierRect));
@@ -5208,7 +5228,20 @@ public class Editor {
lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
int lineRight = (int) layout.getLineRight(line);
lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
+ mDrawCursorOnMagnifier =
+ showPosInView.x < lineLeft - CURSOR_START_FLOAT_DISTANCE_PX
+ || showPosInView.x > lineRight + CURSOR_START_FLOAT_DISTANCE_PX;
+ mMagnifierAnimator.mMagnifier.setDrawCursor(
+ mDrawCursorOnMagnifier, mDrawableForCursor);
+ boolean cursorVisible = mCursorVisible;
+ // Updates cursor visibility, so that the real cursor and the float cursor on
+ // magnifier surface won't appear at the same time.
+ mCursorVisible = !mDrawCursorOnMagnifier;
+ if (mCursorVisible && !cursorVisible) {
+ // When the real cursor is a drawable, hiding/showing it would change its
+ // bounds. So, call updateCursorPosition() to correct its position.
+ updateCursorPosition();
+ }
final int lineHeight =
layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
float zoom = mInitialZoom;
@@ -5230,6 +5263,11 @@ public class Editor {
if (mMagnifierAnimator != null) {
mMagnifierAnimator.dismiss();
mRenderCursorRegardlessTiming = false;
+ mDrawCursorOnMagnifier = false;
+ if (!mCursorVisible) {
+ mCursorVisible = true;
+ mTextView.invalidate();
+ }
resumeBlink();
setVisible(true);
final HandleView otherHandle = getOtherSelectionHandle();
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 89206fda39f3..c72eed45e794 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -149,9 +149,6 @@ public final class Magnifier {
private int mLeftCutWidth = 0;
// The width of the cut region on the right edge of the pixel copy source rect.
private int mRightCutWidth = 0;
- // The horizontal bounds of the content source in pixels, relative to the view.
- private int mLeftBound = Integer.MIN_VALUE;
- private int mRightBound = Integer.MAX_VALUE;
// The width of the ramp region in pixels on the left & right sides of the fish-eye effect.
private final int mRamp;
@@ -244,18 +241,6 @@ public final class Magnifier {
}
/**
- * Sets the horizontal bounds of the source when showing the magnifier.
- * This is used for new style magnifier. e.g. limit the source bounds by the text line bounds.
- *
- * @param left the left of the bounds, relative to the view.
- * @param right the right of the bounds, relative to the view.
- */
- void setSourceHorizontalBounds(int left, int right) {
- mLeftBound = left;
- mRightBound = right;
- }
-
- /**
* Shows the magnifier on the screen. The method takes the coordinates of the center
* of the content source going to be magnified and copied to the magnifier. The coordinates
* are relative to the top left corner of the magnified view. The magnifier will be
@@ -280,6 +265,14 @@ public final class Magnifier {
sourceCenterY + mDefaultVerticalSourceToMagnifierOffset);
}
+ private Drawable mCursorDrawable;
+ private boolean mDrawCursorEnabled;
+
+ void setDrawCursor(boolean enabled, Drawable cursorDrawable) {
+ mDrawCursorEnabled = enabled;
+ mCursorDrawable = cursorDrawable;
+ }
+
/**
* Shows the magnifier on the screen at a position that is independent from its content
* position. The first two arguments represent the coordinates of the center of the
@@ -309,8 +302,7 @@ public final class Magnifier {
magnifierCenterX = mClampedCenterZoomCoords.x - mViewCoordinatesInSurface[0];
magnifierCenterY = mClampedCenterZoomCoords.y - mViewCoordinatesInSurface[1];
- // mLeftBound & mRightBound (typically the text line left/right) is for magnified
- // content. However the PixelCopy requires the pre-magnified bounds.
+ // PixelCopy requires the pre-magnified bounds.
// The below logic calculates the leftBound & rightBound for the pre-magnified bounds.
final float rampPre =
(mSourceWidth - (mSourceWidth - 2 * mRamp) / mZoom) / 2;
@@ -318,7 +310,7 @@ public final class Magnifier {
// Calculates the pre-zoomed left edge.
// The leftEdge moves from the left of view towards to sourceCenterX, considering the
// fisheye-like zooming.
- final float x0 = sourceCenterX - mSourceWidth / 2;
+ final float x0 = sourceCenterX - mSourceWidth / 2f;
final float rampX0 = x0 + mRamp;
float leftEdge = 0;
if (leftEdge > rampX0) {
@@ -330,12 +322,12 @@ public final class Magnifier {
// increase per ramp zoom (ramp / rampPre).
leftEdge = x0 + rampPre - (rampX0 - leftEdge) * rampPre / mRamp;
}
- int leftBound = Math.min(Math.max((int) leftEdge, mLeftBound), mRightBound);
+ int leftBound = Math.min((int) leftEdge, mView.getWidth());
// Calculates the pre-zoomed right edge.
// The rightEdge moves from the right of view towards to sourceCenterX, considering the
// fisheye-like zooming.
- final float x1 = sourceCenterX + mSourceWidth / 2;
+ final float x1 = sourceCenterX + mSourceWidth / 2f;
final float rampX1 = x1 - mRamp;
float rightEdge = mView.getWidth();
if (rightEdge < rampX1) {
@@ -347,7 +339,7 @@ public final class Magnifier {
// increase per ramp zoom (ramp / rampPre).
rightEdge = x1 - rampPre + (rightEdge - rampX1) * rampPre / mRamp;
}
- int rightBound = Math.max(leftBound, Math.min((int) rightEdge, mRightBound));
+ int rightBound = Math.max(leftBound, (int) rightEdge);
// Gets the startX for new style, which should be bounded by the horizontal bounds.
// Also calculates the left/right cut width for pixel copy.
@@ -772,6 +764,23 @@ public final class Magnifier {
}
}
+ private void maybeDrawCursor(Canvas canvas) {
+ if (mDrawCursorEnabled) {
+ if (mCursorDrawable != null) {
+ mCursorDrawable.setBounds(
+ mSourceWidth / 2, 0,
+ mSourceWidth / 2 + mCursorDrawable.getIntrinsicWidth(), mSourceHeight);
+ mCursorDrawable.draw(canvas);
+ } else {
+ Paint paint = new Paint();
+ paint.setColor(Color.BLACK); // The cursor on magnifier is by default in black.
+ canvas.drawRect(
+ new Rect(mSourceWidth / 2 - 1, 0, mSourceWidth / 2 + 1, mSourceHeight),
+ paint);
+ }
+ }
+ }
+
private void performPixelCopy(final int startXInSurface, final int startYInSurface,
final boolean updateWindowPosition) {
if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) {
@@ -827,8 +836,10 @@ public final class Magnifier {
final Rect dstRect = new Rect(mLeftCutWidth, 0,
mSourceWidth - mRightCutWidth, bitmap.getHeight());
can.drawBitmap(bitmap, null, dstRect, null);
+ maybeDrawCursor(can);
mWindow.updateContent(newBitmap);
} else {
+ maybeDrawCursor(new Canvas(bitmap));
mWindow.updateContent(bitmap);
}
}
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index 42724bede481..f08d0ef8c052 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -83,63 +83,25 @@ public class BrightnessSynchronizer{
/**
* Converts between the int brightness system and the float brightness system.
*/
- public static float brightnessIntToFloat(Context context, int brightnessInt) {
- final PowerManager pm = context.getSystemService(PowerManager.class);
- final float pmMinBrightness = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
- final float pmMaxBrightness = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
- final int minBrightnessInt = Math.round(brightnessFloatToIntRange(pmMinBrightness,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON));
- final int maxBrightnessInt = Math.round(brightnessFloatToIntRange(pmMaxBrightness,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON));
-
- return brightnessIntToFloat(brightnessInt, minBrightnessInt, maxBrightnessInt,
- pmMinBrightness, pmMaxBrightness);
- }
-
- /**
- * Converts between the int brightness system and the float brightness system.
- */
- public static float brightnessIntToFloat(int brightnessInt, int minInt, int maxInt,
- float minFloat, float maxFloat) {
+ public static float brightnessIntToFloat(int brightnessInt) {
if (brightnessInt == PowerManager.BRIGHTNESS_OFF) {
return PowerManager.BRIGHTNESS_OFF_FLOAT;
} else if (brightnessInt == PowerManager.BRIGHTNESS_INVALID) {
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
} else {
- return MathUtils.constrainedMap(minFloat, maxFloat, (float) minInt, (float) maxInt,
- brightnessInt);
+ final float minFloat = PowerManager.BRIGHTNESS_MIN;
+ final float maxFloat = PowerManager.BRIGHTNESS_MAX;
+ final float minInt = PowerManager.BRIGHTNESS_OFF + 1;
+ final float maxInt = PowerManager.BRIGHTNESS_ON;
+ return MathUtils.constrainedMap(minFloat, maxFloat, minInt, maxInt, brightnessInt);
}
}
/**
* Converts between the float brightness system and the int brightness system.
*/
- public static int brightnessFloatToInt(Context context, float brightnessFloat) {
- return Math.round(brightnessFloatToIntRange(context, brightnessFloat));
- }
-
- /**
- * Converts between the float brightness system and the int brightness system, but returns
- * the converted value as a float within the int-system's range. This method helps with
- * conversions from one system to the other without losing the floating-point precision.
- */
- public static float brightnessFloatToIntRange(Context context, float brightnessFloat) {
- final PowerManager pm = context.getSystemService(PowerManager.class);
- final float minFloat = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
- final float maxFloat = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
- final float minInt = brightnessFloatToIntRange(minFloat,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON);
- final float maxInt = brightnessFloatToIntRange(maxFloat,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX,
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON);
- return brightnessFloatToIntRange(brightnessFloat, minFloat, maxFloat, minInt, maxInt);
+ public static int brightnessFloatToInt(float brightnessFloat) {
+ return Math.round(brightnessFloatToIntRange(brightnessFloat));
}
/**
@@ -148,20 +110,24 @@ public class BrightnessSynchronizer{
* Value returned as a float privimite (to preserve precision), but is a value within the
* int-system range.
*/
- private static float brightnessFloatToIntRange(float brightnessFloat, float minFloat,
- float maxFloat, float minInt, float maxInt) {
+ public static float brightnessFloatToIntRange(float brightnessFloat) {
if (floatEquals(brightnessFloat, PowerManager.BRIGHTNESS_OFF_FLOAT)) {
return PowerManager.BRIGHTNESS_OFF;
} else if (Float.isNaN(brightnessFloat)) {
return PowerManager.BRIGHTNESS_INVALID;
} else {
+ final float minFloat = PowerManager.BRIGHTNESS_MIN;
+ final float maxFloat = PowerManager.BRIGHTNESS_MAX;
+ final float minInt = PowerManager.BRIGHTNESS_OFF + 1;
+ final float maxInt = PowerManager.BRIGHTNESS_ON;
return MathUtils.constrainedMap(minInt, maxInt, minFloat, maxFloat, brightnessFloat);
}
}
private static float getScreenBrightnessFloat(Context context) {
return Settings.System.getFloatForUser(context.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_FLOAT, Float.NaN, UserHandle.USER_CURRENT);
+ Settings.System.SCREEN_BRIGHTNESS_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ UserHandle.USER_CURRENT);
}
private static int getScreenBrightnessInt(Context context) {
@@ -185,10 +151,10 @@ public class BrightnessSynchronizer{
if (topOfQueue != null && topOfQueue.equals(value)) {
mWriteHistory.poll();
} else {
- if (brightnessFloatToInt(mContext, mPreferredSettingValue) == value) {
+ if (brightnessFloatToInt(mPreferredSettingValue) == value) {
return;
}
- float newBrightnessFloat = brightnessIntToFloat(mContext, value);
+ float newBrightnessFloat = brightnessIntToFloat(value);
mWriteHistory.offer(newBrightnessFloat);
mPreferredSettingValue = newBrightnessFloat;
Settings.System.putFloatForUser(mContext.getContentResolver(),
@@ -207,7 +173,7 @@ public class BrightnessSynchronizer{
* @param value Brightness setting as float to store in int setting.
*/
private void updateBrightnessIntFromFloat(float value) {
- int newBrightnessInt = brightnessFloatToInt(mContext, value);
+ int newBrightnessInt = brightnessFloatToInt(value);
Object topOfQueue = mWriteHistory.peek();
if (topOfQueue != null && topOfQueue.equals(value)) {
mWriteHistory.poll();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 49ad81b2bbc8..fd90b56426aa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -206,6 +206,7 @@ public class ChooserActivity extends ResolverActivity implements
public static final int SELECTION_TYPE_APP = 2;
public static final int SELECTION_TYPE_STANDARD = 3;
public static final int SELECTION_TYPE_COPY = 4;
+ public static final int SELECTION_TYPE_NEARBY = 5;
private static final int SCROLL_STATUS_IDLE = 0;
private static final int SCROLL_STATUS_SCROLLING_VERTICAL = 1;
@@ -784,8 +785,8 @@ public class ChooserActivity extends ResolverActivity implements
FrameworkStatsLog.SHARESHEET_STARTED,
getReferrerPackageName(),
target.getType(),
- initialIntents == null ? 0 : initialIntents.length,
mCallerChooserTargets == null ? 0 : mCallerChooserTargets.length,
+ initialIntents == null ? 0 : initialIntents.length,
isWorkProfile(),
findPreferredContentPreview(getTargetIntent(), getContentResolver()),
target.getAction()
@@ -1135,7 +1136,8 @@ public class ChooserActivity extends ResolverActivity implements
return displayContentPreview(previewType, targetIntent, getLayoutInflater(), parent);
}
- private ComponentName getNearbySharingComponent() {
+ @VisibleForTesting
+ protected ComponentName getNearbySharingComponent() {
String nearbyComponent = Settings.Secure.getString(
getContentResolver(),
Settings.Secure.NEARBY_SHARING_COMPONENT);
@@ -1148,7 +1150,8 @@ public class ChooserActivity extends ResolverActivity implements
return ComponentName.unflattenFromString(nearbyComponent);
}
- private TargetInfo getNearbySharingTarget(Intent originalIntent) {
+ @VisibleForTesting
+ protected TargetInfo getNearbySharingTarget(Intent originalIntent) {
final ComponentName cn = getNearbySharingComponent();
if (cn == null) return null;
@@ -1216,14 +1219,21 @@ public class ChooserActivity extends ResolverActivity implements
final TargetInfo ti = getNearbySharingTarget(originalIntent);
if (ti == null) return null;
- return createActionButton(
+ final Button b = createActionButton(
ti.getDisplayIcon(this),
ti.getDisplayLabel(),
(View unused) -> {
+ // Log share completion via nearby
+ getChooserActivityLogger().logShareTargetSelected(
+ SELECTION_TYPE_NEARBY,
+ "",
+ -1);
safelyStartActivity(ti);
finish();
}
);
+ b.setId(R.id.chooser_nearby_button);
+ return b;
}
private void addActionButton(ViewGroup parent, Button b) {
@@ -2616,7 +2626,9 @@ public class ChooserActivity extends ResolverActivity implements
}
}
- static final class EmptyTargetInfo extends NotSelectableTargetInfo {
+ protected static final class EmptyTargetInfo extends NotSelectableTargetInfo {
+ public EmptyTargetInfo() {}
+
public Drawable getDisplayIcon(Context context) {
return null;
}
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
index c26bac437915..426859e1d527 100644
--- a/core/java/com/android/internal/app/ChooserActivityLogger.java
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -116,7 +116,9 @@ public interface ChooserActivityLogger {
@UiEvent(doc = "User selected a standard target.")
SHARESHEET_STANDARD_TARGET_SELECTED(234),
@UiEvent(doc = "User selected the copy target.")
- SHARESHEET_COPY_TARGET_SELECTED(235);
+ SHARESHEET_COPY_TARGET_SELECTED(235),
+ @UiEvent(doc = "User selected the nearby target.")
+ SHARESHEET_NEARBY_TARGET_SELECTED(626);
private final int mId;
SharesheetTargetSelectedEvent(int id) {
@@ -136,6 +138,8 @@ public interface ChooserActivityLogger {
return SHARESHEET_STANDARD_TARGET_SELECTED;
case ChooserActivity.SELECTION_TYPE_COPY:
return SHARESHEET_COPY_TARGET_SELECTED;
+ case ChooserActivity.SELECTION_TYPE_NEARBY:
+ return SHARESHEET_NEARBY_TARGET_SELECTED;
default:
return INVALID;
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 201626abd820..f5bef0b006f5 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -74,6 +74,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
// Whether to collect all the data: cpu + exceptions + reply/request sizes.
private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
+ // If set to true, indicates that all transactions for specific UIDs are being
+ // recorded, ignoring sampling. The UidEntry.recordAllTransactions flag is also set
+ // for the UIDs being tracked.
+ private boolean mRecordingAllTransactionsForUid;
// Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
// of 100 requests.
private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
@@ -178,7 +182,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
@Override
@Nullable
public CallSession callStarted(Binder binder, int code, int workSourceUid) {
- if (mDeviceState == null || mDeviceState.isCharging()) {
+ if (!mRecordingAllTransactionsForUid
+ && (mDeviceState == null || mDeviceState.isCharging())) {
return null;
}
@@ -190,7 +195,9 @@ public class BinderCallsStats implements BinderInternal.Observer {
s.exceptionThrown = false;
s.cpuTimeStarted = -1;
s.timeStarted = -1;
- if (shouldRecordDetailedData()) {
+ s.recordedCall = shouldRecordDetailedData();
+
+ if (mRecordingAllTransactionsForUid || s.recordedCall) {
s.cpuTimeStarted = getThreadTimeMicro();
s.timeStarted = getElapsedRealtimeMicro();
}
@@ -218,8 +225,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
private void processCallEnded(CallSession s,
int parcelRequestSize, int parcelReplySize, int workSourceUid) {
- // Non-negative time signals we need to record data for this call.
- final boolean recordCall = s.cpuTimeStarted >= 0;
+ UidEntry uidEntry = null;
+ final boolean recordCall;
+ if (s.recordedCall) {
+ recordCall = true;
+ } else if (mRecordingAllTransactionsForUid) {
+ uidEntry = getUidEntry(workSourceUid);
+ recordCall = uidEntry.recordAllTransactions;
+ } else {
+ recordCall = false;
+ }
+
final long duration;
final long latencyDuration;
if (recordCall) {
@@ -238,14 +254,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
synchronized (mLock) {
// This was already checked in #callStart but check again while synchronized.
- if (mDeviceState == null || mDeviceState.isCharging()) {
+ if (!mRecordingAllTransactionsForUid
+ && (mDeviceState == null || mDeviceState.isCharging())) {
return;
}
- final UidEntry uidEntry = getUidEntry(workSourceUid);
+ if (uidEntry == null) {
+ uidEntry = getUidEntry(workSourceUid);
+ }
+
uidEntry.callCount++;
uidEntry.incrementalCallCount++;
-
if (recordCall) {
uidEntry.cpuTimeMicros += duration;
uidEntry.recordedCallCount++;
@@ -357,28 +376,67 @@ public class BinderCallsStats implements BinderInternal.Observer {
for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) {
final UidEntry entry = mUidEntries.valueAt(entryIdx);
for (CallStat stat : entry.getCallStatsList()) {
- ExportedCallStat exported = new ExportedCallStat();
- exported.workSourceUid = entry.workSourceUid;
- exported.callingUid = stat.callingUid;
- exported.className = stat.binderClass.getName();
- exported.binderClass = stat.binderClass;
- exported.transactionCode = stat.transactionCode;
- exported.screenInteractive = stat.screenInteractive;
- exported.cpuTimeMicros = stat.cpuTimeMicros;
- exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
- exported.latencyMicros = stat.latencyMicros;
- exported.maxLatencyMicros = stat.maxLatencyMicros;
- exported.recordedCallCount = stat.recordedCallCount;
- exported.callCount = stat.callCount;
- exported.maxRequestSizeBytes = stat.maxRequestSizeBytes;
- exported.maxReplySizeBytes = stat.maxReplySizeBytes;
- exported.exceptionCount = stat.exceptionCount;
- resultCallStats.add(exported);
+ resultCallStats.add(getExportedCallStat(entry.workSourceUid, stat));
}
}
}
// Resolve codes outside of the lock since it can be slow.
+ resolveBinderMethodNames(resultCallStats);
+
+ // Debug entries added to help validate the data.
+ if (mAddDebugEntries && mBatteryStopwatch != null) {
+ resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime));
+ resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
+ resultCallStats.add(
+ createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
+ resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval));
+ }
+
+ return resultCallStats;
+ }
+
+ /**
+ * This method is expensive to call.
+ */
+ public ArrayList<ExportedCallStat> getExportedCallStats(int workSourceUid) {
+ ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
+ synchronized (mLock) {
+ final UidEntry entry = getUidEntry(workSourceUid);
+ for (CallStat stat : entry.getCallStatsList()) {
+ resultCallStats.add(getExportedCallStat(workSourceUid, stat));
+ }
+ }
+
+ // Resolve codes outside of the lock since it can be slow.
+ resolveBinderMethodNames(resultCallStats);
+
+ return resultCallStats;
+ }
+
+ private ExportedCallStat getExportedCallStat(int workSourceUid, CallStat stat) {
+ ExportedCallStat exported = new ExportedCallStat();
+ exported.workSourceUid = workSourceUid;
+ exported.callingUid = stat.callingUid;
+ exported.className = stat.binderClass.getName();
+ exported.binderClass = stat.binderClass;
+ exported.transactionCode = stat.transactionCode;
+ exported.screenInteractive = stat.screenInteractive;
+ exported.cpuTimeMicros = stat.cpuTimeMicros;
+ exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
+ exported.latencyMicros = stat.latencyMicros;
+ exported.maxLatencyMicros = stat.maxLatencyMicros;
+ exported.recordedCallCount = stat.recordedCallCount;
+ exported.callCount = stat.callCount;
+ exported.maxRequestSizeBytes = stat.maxRequestSizeBytes;
+ exported.maxReplySizeBytes = stat.maxReplySizeBytes;
+ exported.exceptionCount = stat.exceptionCount;
+ return exported;
+ }
+
+ private void resolveBinderMethodNames(
+ ArrayList<ExportedCallStat> resultCallStats) {
+ // Resolve codes outside of the lock since it can be slow.
ExportedCallStat previous = null;
String previousMethodName = null;
resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode);
@@ -398,17 +456,6 @@ public class BinderCallsStats implements BinderInternal.Observer {
exported.methodName = methodName;
previous = exported;
}
-
- // Debug entries added to help validate the data.
- if (mAddDebugEntries && mBatteryStopwatch != null) {
- resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime));
- resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
- resultCallStats.add(
- createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
- resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval));
- }
-
- return resultCallStats;
}
private ExportedCallStat createDebugEntry(String variableName, long value) {
@@ -432,33 +479,24 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
/** Writes the collected statistics to the supplied {@link PrintWriter}.*/
- public void dump(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
+ public void dump(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid,
+ boolean verbose) {
synchronized (mLock) {
- dumpLocked(pw, packageMap, verbose);
+ dumpLocked(pw, packageMap, workSourceUid, verbose);
}
}
- private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
- long totalCallsCount = 0;
- long totalRecordedCallsCount = 0;
- long totalCpuTime = 0;
+ private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid,
+ boolean verbose) {
+ if (workSourceUid != Process.INVALID_UID) {
+ verbose = true;
+ }
pw.print("Start time: ");
pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartCurrentTime));
pw.print("On battery time (ms): ");
pw.println(mBatteryStopwatch != null ? mBatteryStopwatch.getMillis() : 0);
pw.println("Sampling interval period: " + mPeriodicSamplingInterval);
- final List<UidEntry> entries = new ArrayList<>();
- final int uidEntriesSize = mUidEntries.size();
- for (int i = 0; i < uidEntriesSize; i++) {
- UidEntry e = mUidEntries.valueAt(i);
- entries.add(e);
- totalCpuTime += e.cpuTimeMicros;
- totalRecordedCallsCount += e.recordedCallCount;
- totalCallsCount += e.callCount;
- }
-
- entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
final StringBuilder sb = new StringBuilder();
pw.println("Per-UID raw data " + datasetSizeDesc
@@ -467,10 +505,15 @@ public class BinderCallsStats implements BinderInternal.Observer {
+ "latency_time_micros, max_latency_time_micros, exception_count, "
+ "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, "
+ "call_count):");
- final List<ExportedCallStat> exportedCallStats = getExportedCallStats();
+ final List<ExportedCallStat> exportedCallStats;
+ if (workSourceUid != Process.INVALID_UID) {
+ exportedCallStats = getExportedCallStats(workSourceUid);
+ } else {
+ exportedCallStats = getExportedCallStats();
+ }
exportedCallStats.sort(BinderCallsStats::compareByCpuDesc);
for (ExportedCallStat e : exportedCallStats) {
- if (e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) {
+ if (e.methodName != null && e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) {
// Do not dump debug entries.
continue;
}
@@ -494,6 +537,30 @@ public class BinderCallsStats implements BinderInternal.Observer {
pw.println(sb);
}
pw.println();
+ final List<UidEntry> entries = new ArrayList<>();
+ long totalCallsCount = 0;
+ long totalRecordedCallsCount = 0;
+ long totalCpuTime = 0;
+
+ if (workSourceUid != Process.INVALID_UID) {
+ UidEntry e = getUidEntry(workSourceUid);
+ entries.add(e);
+ totalCpuTime += e.cpuTimeMicros;
+ totalRecordedCallsCount += e.recordedCallCount;
+ totalCallsCount += e.callCount;
+ } else {
+ final int uidEntriesSize = mUidEntries.size();
+ for (int i = 0; i < uidEntriesSize; i++) {
+ UidEntry e = mUidEntries.valueAt(i);
+ entries.add(e);
+ totalCpuTime += e.cpuTimeMicros;
+ totalRecordedCallsCount += e.recordedCallCount;
+ totalCallsCount += e.callCount;
+ }
+ entries.sort(
+ Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
+ }
+
pw.println("Per-UID Summary " + datasetSizeDesc
+ "(cpu_time, % of total cpu_time, recorded_call_count, call_count, package/uid):");
final List<UidEntry> summaryEntries = verbose ? entries
@@ -505,10 +572,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
entry.recordedCallCount, entry.callCount, uidStr));
}
pw.println();
- pw.println(String.format(" Summary: total_cpu_time=%d, "
- + "calls_count=%d, avg_call_cpu_time=%.0f",
- totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount));
- pw.println();
+ if (workSourceUid == Process.INVALID_UID) {
+ pw.println(String.format(" Summary: total_cpu_time=%d, "
+ + "calls_count=%d, avg_call_cpu_time=%.0f",
+ totalCpuTime, totalCallsCount,
+ (double) totalCpuTime / totalRecordedCallsCount));
+ pw.println();
+ }
pw.println("Exceptions thrown (exception_count, class_name):");
final List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
@@ -590,6 +660,22 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
}
+ /**
+ * Marks the specified work source UID for total binder call tracking: detailed information
+ * will be recorded for all calls from this source ID.
+ *
+ * This is expensive and can cause memory pressure, therefore this mode should only be used
+ * for debugging.
+ */
+ public void recordAllCallsForWorkSourceUid(int workSourceUid) {
+ setDetailedTracking(true);
+
+ Slog.i(TAG, "Recording all Binder calls for UID: " + workSourceUid);
+ UidEntry uidEntry = getUidEntry(workSourceUid);
+ uidEntry.recordAllTransactions = true;
+ mRecordingAllTransactionsForUid = true;
+ }
+
public void setAddDebugEntries(boolean addDebugEntries) {
mAddDebugEntries = addDebugEntries;
}
@@ -637,6 +723,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
if (mBatteryStopwatch != null) {
mBatteryStopwatch.reset();
}
+ mRecordingAllTransactionsForUid = false;
}
}
@@ -767,6 +854,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
public long cpuTimeMicros;
// Call count that gets reset after delivery to BatteryStats
public long incrementalCallCount;
+ // Indicates that all transactions for the UID must be tracked
+ public boolean recordAllTransactions;
UidEntry(int uid) {
this.workSourceUid = uid;
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index f14d5f2bbbeb..2645b8e84cf1 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -85,9 +85,10 @@ public class BinderInternal {
long timeStarted;
// Should be set to one when an exception is thrown.
boolean exceptionThrown;
+ // Detailed information should be recorded for this call when it ends.
+ public boolean recordedCall;
}
-
/**
* Responsible for resolving a work source.
*/
diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 51725cecbc74..73d148c1f233 100644
--- a/services/core/java/com/android/server/wm/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.server.wm;
+package com.android.internal.protolog;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.IProtoLogGroup;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.IProtoLogGroup;
/**
* Defines logging groups for ProtoLog.
@@ -118,16 +116,6 @@ public enum ProtoLogGroup implements IProtoLogGroup {
this.mLogToLogcat = logToLogcat;
}
- /**
- * Test function for automated integration tests. Can be also called manually from adb shell.
- */
- @VisibleForTesting
- public static void testProtoLog() {
- ProtoLog.e(ProtoLogGroup.TEST_GROUP,
- "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
- true, 1, 2, 3, 0.4, 0.5, 0.6, "ok");
- }
-
private static class Consts {
private static final String TAG_WM = "WindowManager";
diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index c9d42c854b54..6874f10e6abc 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-package com.android.server.protolog;
-
-import static com.android.server.protolog.ProtoLogFileProto.LOG;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_H;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_L;
-import static com.android.server.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS;
-import static com.android.server.protolog.ProtoLogFileProto.VERSION;
-import static com.android.server.protolog.ProtoLogMessage.BOOLEAN_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.DOUBLE_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS;
-import static com.android.server.protolog.ProtoLogMessage.MESSAGE_HASH;
-import static com.android.server.protolog.ProtoLogMessage.SINT64_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.STR_PARAMS;
+package com.android.internal.protolog;
+
+import static com.android.internal.protolog.ProtoLogFileProto.LOG;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_H;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_L;
+import static com.android.internal.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS;
+import static com.android.internal.protolog.ProtoLogFileProto.VERSION;
+import static com.android.internal.protolog.ProtoLogMessage.BOOLEAN_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.DOUBLE_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS;
+import static com.android.internal.protolog.ProtoLogMessage.MESSAGE_HASH;
+import static com.android.internal.protolog.ProtoLogMessage.SINT64_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.STR_PARAMS;
import android.annotation.Nullable;
import android.os.ShellCommand;
@@ -36,10 +36,9 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.IProtoLogGroup;
-import com.android.server.protolog.common.LogDataType;
+import com.android.internal.protolog.common.IProtoLogGroup;
+import com.android.internal.protolog.common.LogDataType;
import com.android.internal.util.TraceBuffer;
-import com.android.server.wm.ProtoLogGroup;
import java.io.File;
import java.io.IOException;
@@ -62,7 +61,7 @@ public class ProtoLogImpl {
* Must be invoked after every action that could change the result of {@link #isEnabled}, eg.
* starting / stopping proto log, or enabling / disabling log groups.
*/
- static Runnable sCacheUpdater = () -> { };
+ public static Runnable sCacheUpdater = () -> { };
private static void addLogGroupEnum(IProtoLogGroup[] config) {
for (IProtoLogGroup group : config) {
@@ -289,9 +288,7 @@ public class ProtoLogImpl {
}
}
-
- @VisibleForTesting
- ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) {
+ public ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) {
mLogFile = file;
mBuffer = new TraceBuffer(bufferCapacity);
mViewerConfig = viewerConfig;
diff --git a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 494421717800..e381d30da524 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog;
-
-import static com.android.server.protolog.ProtoLogImpl.logAndPrintln;
+package com.android.internal.protolog;
import org.json.JSONException;
import org.json.JSONObject;
@@ -80,16 +78,17 @@ public class ProtoLogViewerConfigReader {
// Not a messageHash - skip it
}
}
- logAndPrintln(pw, "Loaded " + mLogMessageMap.size() + " log definitions from "
- + viewerConfigFilename);
+ ProtoLogImpl.logAndPrintln(pw, "Loaded " + mLogMessageMap.size()
+ + " log definitions from " + viewerConfigFilename);
} catch (FileNotFoundException e) {
- logAndPrintln(pw, "Unable to load log definitions: File "
+ ProtoLogImpl.logAndPrintln(pw, "Unable to load log definitions: File "
+ viewerConfigFilename + " not found." + e);
} catch (IOException e) {
- logAndPrintln(pw, "Unable to load log definitions: IOException while reading "
+ ProtoLogImpl.logAndPrintln(pw,
+ "Unable to load log definitions: IOException while reading "
+ viewerConfigFilename + ". " + e);
} catch (JSONException e) {
- logAndPrintln(pw,
+ ProtoLogImpl.logAndPrintln(pw,
"Unable to load log definitions: JSON parsing exception while reading "
+ viewerConfigFilename + ". " + e);
}
diff --git a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java
index 7bb27b2d9bcd..68b9d6910b57 100644
--- a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java
+++ b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Error while converting a bitmask representing a list of LogDataTypes.
diff --git a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
index 2c65341453e9..e3db46832a6f 100644
--- a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Defines a log group configuration object for ProtoLog. Should be implemented as en enum.
diff --git a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java
index 947bf98eea3c..97d3dfb7e6c2 100644
--- a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java
+++ b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Unsupported/invalid message format string error.
diff --git a/services/core/java/com/android/server/protolog/common/LogDataType.java b/core/java/com/android/internal/protolog/common/LogDataType.java
index e73b41abddc7..651932a7ba7e 100644
--- a/services/core/java/com/android/server/protolog/common/LogDataType.java
+++ b/core/java/com/android/internal/protolog/common/LogDataType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
import java.util.ArrayList;
import java.util.List;
diff --git a/services/core/java/com/android/server/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java
index b631bcb23f5f..ab58d351d3b9 100644
--- a/services/core/java/com/android/server/protolog/common/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/ProtoLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* ProtoLog API - exposes static logging methods. Usage of this API is similar
diff --git a/core/java/com/android/internal/util/StatLogger.java b/core/java/com/android/internal/util/StatLogger.java
index 29568d5020e3..2d65090ce51e 100644
--- a/core/java/com/android/internal/util/StatLogger.java
+++ b/core/java/com/android/internal/util/StatLogger.java
@@ -84,7 +84,7 @@ public class StatLogger {
* give it back to the {@link #logDurationStat(int, long)}} after the event.
*/
public long getTime() {
- return SystemClock.elapsedRealtimeNanos() / 1000;
+ return SystemClock.uptimeNanos() / 1000;
}
/**
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index e35fda1ee76d..d5d635de81d8 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -47,8 +47,9 @@ interface ILockSettings {
void resetKeyStore(int userId);
VerifyCredentialResponse checkCredential(in LockscreenCredential credential, int userId,
in ICheckCredentialProgressCallback progressCallback);
- VerifyCredentialResponse verifyCredential(in LockscreenCredential credential, long challenge, int userId);
- VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, long challenge, int userId);
+ VerifyCredentialResponse verifyCredential(in LockscreenCredential credential, int userId, int flags);
+ VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags);
+ VerifyCredentialResponse verifyGatekeeperPassword(in byte[] gatekeeperPassword, long challenge, int userId);
boolean checkVoldPassword(int userId);
int getCredentialType(int userId);
byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 85a45fd8e0c0..5adbc583140f 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -1,5 +1,6 @@
package com.android.internal.widget;
+import android.annotation.NonNull;
import android.os.AsyncTask;
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
@@ -41,11 +42,11 @@ public final class LockPatternChecker {
/**
* Invoked when a security verification is finished.
*
- * @param attestation The attestation that the challenge was verified, or null.
+ * @param response The response, optionally containing Gatekeeper HAT or Gatekeeper Password
* @param throttleTimeoutMs The amount of time in ms to wait before reattempting
- * the call. Only non-0 if attestation is null.
+ * the call. Only non-0 if the response is {@link VerifyCredentialResponse#RESPONSE_RETRY}.
*/
- void onVerified(byte[] attestation, int throttleTimeoutMs);
+ void onVerified(@NonNull VerifyCredentialResponse response, int throttleTimeoutMs);
}
/**
@@ -53,33 +54,27 @@ public final class LockPatternChecker {
*
* @param utils The LockPatternUtils instance to use.
* @param credential The credential to check.
- * @param challenge The challenge to verify against the credential.
* @param userId The user to check against the credential.
+ * @param flags See {@link LockPatternUtils.VerifyFlag}
* @param callback The callback to be invoked with the verification result.
*/
public static AsyncTask<?, ?, ?> verifyCredential(final LockPatternUtils utils,
final LockscreenCredential credential,
- final long challenge,
final int userId,
+ final @LockPatternUtils.VerifyFlag int flags,
final OnVerifyCallback callback) {
// Create a copy of the credential since checking credential is asynchrounous.
final LockscreenCredential credentialCopy = credential.duplicate();
- AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
- private int mThrottleTimeout;
-
+ AsyncTask<Void, Void, VerifyCredentialResponse> task =
+ new AsyncTask<Void, Void, VerifyCredentialResponse>() {
@Override
- protected byte[] doInBackground(Void... args) {
- try {
- return utils.verifyCredential(credentialCopy, challenge, userId);
- } catch (RequestThrottledException ex) {
- mThrottleTimeout = ex.getTimeoutMs();
- return null;
- }
+ protected VerifyCredentialResponse doInBackground(Void... args) {
+ return utils.verifyCredential(credentialCopy, userId, flags);
}
@Override
- protected void onPostExecute(byte[] result) {
- callback.onVerified(result, mThrottleTimeout);
+ protected void onPostExecute(@NonNull VerifyCredentialResponse result) {
+ callback.onVerified(result, result.getTimeout());
credentialCopy.zeroize();
}
@@ -141,33 +136,27 @@ public final class LockPatternChecker {
*
* @param utils The LockPatternUtils instance to use.
* @param credential The credential to check.
- * @param challenge The challenge to verify against the credential.
* @param userId The user to check against the credential.
+ * @param flags See {@link LockPatternUtils.VerifyFlag}
* @param callback The callback to be invoked with the verification result.
*/
public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
final LockscreenCredential credential,
- final long challenge,
final int userId,
+ final @LockPatternUtils.VerifyFlag int flags,
final OnVerifyCallback callback) {
- // Create a copy of the credential since checking credential is asynchrounous.
+ // Create a copy of the credential since checking credential is asynchronous.
final LockscreenCredential credentialCopy = credential.duplicate();
- AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
- private int mThrottleTimeout;
-
+ AsyncTask<Void, Void, VerifyCredentialResponse> task =
+ new AsyncTask<Void, Void, VerifyCredentialResponse>() {
@Override
- protected byte[] doInBackground(Void... args) {
- try {
- return utils.verifyTiedProfileChallenge(credentialCopy, challenge, userId);
- } catch (RequestThrottledException ex) {
- mThrottleTimeout = ex.getTimeoutMs();
- return null;
- }
+ protected VerifyCredentialResponse doInBackground(Void... args) {
+ return utils.verifyTiedProfileChallenge(credentialCopy, userId, flags);
}
@Override
- protected void onPostExecute(byte[] result) {
- callback.onVerified(result, mThrottleTimeout);
+ protected void onPostExecute(@NonNull VerifyCredentialResponse response) {
+ callback.onVerified(response, response.getTimeout());
credentialCopy.zeroize();
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 93690cdfc811..f7370d6a22f9 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -130,6 +130,18 @@ public class LockPatternUtils {
public @interface CredentialType {}
/**
+ * Flag provided to {@link #verifyCredential(LockscreenCredential, long, int, int)} . If set,
+ * the method will return the Gatekeeper Password in the {@link VerifyCredentialResponse}.
+ */
+ public static final int VERIFY_FLAG_RETURN_GK_PW = 1 << 0;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {
+ VERIFY_FLAG_RETURN_GK_PW
+ })
+ public @interface VerifyFlag {}
+
+ /**
* Special user id for triggering the FRP verification flow.
*/
public static final int USER_FRP = UserHandle.USER_NULL + 1;
@@ -374,29 +386,46 @@ public class LockPatternUtils {
* If credential matches, return an opaque attestation that the challenge was verified.
*
* @param credential The credential to check.
- * @param challenge The challenge to verify against the credential
* @param userId The user whose credential is being verified
- * @return the attestation that the challenge was verified, or null
- * @throws RequestThrottledException if credential verification is being throttled due to
- * to many incorrect attempts.
+ * @param flags See {@link VerifyFlag}
* @throws IllegalStateException if called on the main thread.
*/
- public byte[] verifyCredential(@NonNull LockscreenCredential credential, long challenge,
- int userId) throws RequestThrottledException {
+ @NonNull
+ public VerifyCredentialResponse verifyCredential(@NonNull LockscreenCredential credential,
+ int userId, @VerifyFlag int flags) {
throwIfCalledOnMainThread();
try {
- VerifyCredentialResponse response = getLockSettings().verifyCredential(
- credential, challenge, userId);
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
- return response.getPayload();
- } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
- throw new RequestThrottledException(response.getTimeout());
+ final VerifyCredentialResponse response = getLockSettings().verifyCredential(
+ credential, userId, flags);
+ if (response == null) {
+ return VerifyCredentialResponse.ERROR;
} else {
- return null;
+ return response;
}
} catch (RemoteException re) {
Log.e(TAG, "failed to verify credential", re);
- return null;
+ return VerifyCredentialResponse.ERROR;
+ }
+ }
+
+ /**
+ * With the Gatekeeper Password returned via {@link #verifyCredential(LockscreenCredential,
+ * int, int)}, request Gatekeeper to create a HardwareAuthToken wrapping the given
+ * challenge.
+ */
+ @NonNull
+ public VerifyCredentialResponse verifyGatekeeperPassword(@NonNull byte[] gatekeeperPassword,
+ long challenge, int userId) {
+ try {
+ final VerifyCredentialResponse response = getLockSettings().verifyGatekeeperPassword(
+ gatekeeperPassword, challenge, userId);
+ if (response == null) {
+ return VerifyCredentialResponse.ERROR;
+ }
+ return response;
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to verify gatekeeper password", e);
+ return VerifyCredentialResponse.ERROR;
}
}
@@ -418,8 +447,9 @@ public class LockPatternUtils {
try {
VerifyCredentialResponse response = getLockSettings().checkCredential(
credential, userId, wrapCallback(progressCallback));
-
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ if (response == null) {
+ return false;
+ } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
return true;
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
throw new RequestThrottledException(response.getTimeout());
@@ -439,30 +469,26 @@ public class LockPatternUtils {
* verified.
*
* @param credential The parent user's credential to check.
- * @param challenge The challenge to verify against the credential
* @return the attestation that the challenge was verified, or null
* @param userId The managed profile user id
- * @throws RequestThrottledException if credential verification is being throttled due to
- * to many incorrect attempts.
+ * @param flags See {@link VerifyFlag}
* @throws IllegalStateException if called on the main thread.
*/
- public byte[] verifyTiedProfileChallenge(@NonNull LockscreenCredential credential,
- long challenge, int userId) throws RequestThrottledException {
+ @NonNull
+ public VerifyCredentialResponse verifyTiedProfileChallenge(
+ @NonNull LockscreenCredential credential, int userId, @VerifyFlag int flags) {
throwIfCalledOnMainThread();
try {
- VerifyCredentialResponse response =
- getLockSettings().verifyTiedProfileChallenge(credential, challenge, userId);
-
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
- return response.getPayload();
- } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
- throw new RequestThrottledException(response.getTimeout());
+ final VerifyCredentialResponse response = getLockSettings()
+ .verifyTiedProfileChallenge(credential, userId, flags);
+ if (response == null) {
+ return VerifyCredentialResponse.ERROR;
} else {
- return null;
+ return response;
}
} catch (RemoteException re) {
Log.e(TAG, "failed to verify tied profile credential", re);
- return null;
+ return VerifyCredentialResponse.ERROR;
}
}
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 55f30fb89253..a488449db019 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -48,7 +48,7 @@ import java.util.Objects;
* // Process the credential in some way
* }
* </pre>
- * With this construct, we can garantee that there will be no copies of the password left in
+ * With this construct, we can guarantee that there will be no copies of the password left in
* memory when the credential goes out of scope. This should help mitigate certain class of
* attacks where the attcker gains read-only access to full device memory (cold boot attack,
* unsecured software/hardware memory dumping interfaces such as JTAG).
diff --git a/core/java/com/android/internal/widget/VerifyCredentialResponse.java b/core/java/com/android/internal/widget/VerifyCredentialResponse.java
index 7d1c70647092..e09eb4228219 100644
--- a/core/java/com/android/internal/widget/VerifyCredentialResponse.java
+++ b/core/java/com/android/internal/widget/VerifyCredentialResponse.java
@@ -16,11 +16,16 @@
package com.android.internal.widget;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.gatekeeper.GateKeeperResponse;
import android.util.Slog;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Response object for a ILockSettings credential verification request.
* @hide
@@ -30,78 +35,114 @@ public final class VerifyCredentialResponse implements Parcelable {
public static final int RESPONSE_ERROR = -1;
public static final int RESPONSE_OK = 0;
public static final int RESPONSE_RETRY = 1;
-
- public static final VerifyCredentialResponse OK = new VerifyCredentialResponse();
- public static final VerifyCredentialResponse ERROR
- = new VerifyCredentialResponse(RESPONSE_ERROR, 0, null);
+ @IntDef({RESPONSE_ERROR,
+ RESPONSE_OK,
+ RESPONSE_RETRY})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ResponseCode {}
+
+ public static final VerifyCredentialResponse OK = new VerifyCredentialResponse.Builder()
+ .build();
+ public static final VerifyCredentialResponse ERROR = fromError();
private static final String TAG = "VerifyCredentialResponse";
- private int mResponseCode;
- private byte[] mPayload;
- private int mTimeout;
+ private final @ResponseCode int mResponseCode;
+ private final int mTimeout;
+ @Nullable private final byte[] mGatekeeperHAT;
+ @Nullable private final byte[] mGatekeeperPw;
public static final Parcelable.Creator<VerifyCredentialResponse> CREATOR
= new Parcelable.Creator<VerifyCredentialResponse>() {
@Override
public VerifyCredentialResponse createFromParcel(Parcel source) {
- int responseCode = source.readInt();
- VerifyCredentialResponse response = new VerifyCredentialResponse(responseCode, 0, null);
- if (responseCode == RESPONSE_RETRY) {
- response.setTimeout(source.readInt());
- } else if (responseCode == RESPONSE_OK) {
- int size = source.readInt();
- if (size > 0) {
- byte[] payload = new byte[size];
- source.readByteArray(payload);
- response.setPayload(payload);
- }
- }
- return response;
+ final @ResponseCode int responseCode = source.readInt();
+ final int timeout = source.readInt();
+ final byte[] gatekeeperHAT = source.createByteArray();
+ final byte[] gatekeeperPassword = source.createByteArray();
+
+ return new VerifyCredentialResponse(responseCode, timeout, gatekeeperHAT,
+ gatekeeperPassword);
}
@Override
public VerifyCredentialResponse[] newArray(int size) {
return new VerifyCredentialResponse[size];
}
-
};
- public VerifyCredentialResponse() {
- mResponseCode = RESPONSE_OK;
- mPayload = null;
- }
+ public static class Builder {
+ @Nullable private byte[] mGatekeeperHAT;
+ @Nullable private byte[] mGatekeeperPassword;
+ /**
+ * @param gatekeeperHAT Gatekeeper HardwareAuthToken, minted upon successful authentication.
+ */
+ public Builder setGatekeeperHAT(byte[] gatekeeperHAT) {
+ mGatekeeperHAT = gatekeeperHAT;
+ return this;
+ }
- public VerifyCredentialResponse(byte[] payload) {
- mPayload = payload;
- mResponseCode = RESPONSE_OK;
+ public Builder setGatekeeperPassword(byte[] gatekeeperPassword) {
+ mGatekeeperPassword = gatekeeperPassword;
+ return this;
+ }
+
+ /**
+ * Builds a VerifyCredentialResponse with {@link #RESPONSE_OK} and any other parameters
+ * that were preveiously set.
+ * @return
+ */
+ public VerifyCredentialResponse build() {
+ return new VerifyCredentialResponse(RESPONSE_OK,
+ 0 /* timeout */,
+ mGatekeeperHAT,
+ mGatekeeperPassword);
+ }
}
- public VerifyCredentialResponse(int timeout) {
- mTimeout = timeout;
- mResponseCode = RESPONSE_RETRY;
- mPayload = null;
+ /**
+ * Since timeouts are always an error, provide a way to create the VerifyCredentialResponse
+ * object directly. None of the other fields (Gatekeeper HAT, Gatekeeper Password, etc)
+ * are valid in this case. Similarly, the response code will always be
+ * {@link #RESPONSE_RETRY}.
+ */
+ public static VerifyCredentialResponse fromTimeout(int timeout) {
+ return new VerifyCredentialResponse(RESPONSE_RETRY,
+ timeout,
+ null /* gatekeeperHAT */,
+ null /* gatekeeperPassword */);
+ }
+
+ /**
+ * Since error (incorrect password) should never result in any of the other fields from
+ * being populated, provide a default method to return a VerifyCredentialResponse.
+ */
+ public static VerifyCredentialResponse fromError() {
+ return new VerifyCredentialResponse(RESPONSE_ERROR,
+ 0 /* timeout */,
+ null /* gatekeeperHAT */,
+ null /* gatekeeperPassword */);
}
- private VerifyCredentialResponse(int responseCode, int timeout, byte[] payload) {
+ private VerifyCredentialResponse(@ResponseCode int responseCode, int timeout,
+ @Nullable byte[] gatekeeperHAT, @Nullable byte[] gatekeeperPassword) {
mResponseCode = responseCode;
mTimeout = timeout;
- mPayload = payload;
+ mGatekeeperHAT = gatekeeperHAT;
+ mGatekeeperPw = gatekeeperPassword;
+ }
+
+ public VerifyCredentialResponse stripPayload() {
+ return new VerifyCredentialResponse(mResponseCode, mTimeout,
+ null /* gatekeeperHAT */, null /* gatekeeperPassword */);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mResponseCode);
- if (mResponseCode == RESPONSE_RETRY) {
- dest.writeInt(mTimeout);
- } else if (mResponseCode == RESPONSE_OK) {
- if (mPayload != null) {
- dest.writeInt(mPayload.length);
- dest.writeByteArray(mPayload);
- } else {
- dest.writeInt(0);
- }
- }
+ dest.writeInt(mTimeout);
+ dest.writeByteArray(mGatekeeperHAT);
+ dest.writeByteArray(mGatekeeperPw);
}
@Override
@@ -109,48 +150,51 @@ public final class VerifyCredentialResponse implements Parcelable {
return 0;
}
- public byte[] getPayload() {
- return mPayload;
+ @Nullable
+ public byte[] getGatekeeperHAT() {
+ return mGatekeeperHAT;
+ }
+
+ @Nullable
+ public byte[] getGatekeeperPw() {
+ return mGatekeeperPw;
}
public int getTimeout() {
return mTimeout;
}
- public int getResponseCode() {
+ public @ResponseCode int getResponseCode() {
return mResponseCode;
}
- private void setTimeout(int timeout) {
- mTimeout = timeout;
- }
-
- private void setPayload(byte[] payload) {
- mPayload = payload;
+ public boolean isMatched() {
+ return mResponseCode == RESPONSE_OK;
}
- public VerifyCredentialResponse stripPayload() {
- return new VerifyCredentialResponse(mResponseCode, mTimeout, new byte[0]);
+ @Override
+ public String toString() {
+ return "Response: " + mResponseCode
+ + ", GK HAT: " + (mGatekeeperHAT != null)
+ + ", GK PW: " + (mGatekeeperPw != null);
}
public static VerifyCredentialResponse fromGateKeeperResponse(
GateKeeperResponse gateKeeperResponse) {
- VerifyCredentialResponse response;
int responseCode = gateKeeperResponse.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
+ return fromTimeout(gateKeeperResponse.getTimeout());
} else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
byte[] token = gateKeeperResponse.getPayload();
if (token == null) {
// something's wrong if there's no payload with a challenge
Slog.e(TAG, "verifyChallenge response had no associated payload");
- response = VerifyCredentialResponse.ERROR;
+ return fromError();
} else {
- response = new VerifyCredentialResponse(token);
+ return new VerifyCredentialResponse.Builder().setGatekeeperHAT(token).build();
}
} else {
- response = VerifyCredentialResponse.ERROR;
+ return fromError();
}
- return response;
}
}
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index b1f600053b9b..2fba445428f4 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -37,10 +37,12 @@ namespace android {
static_assert(std::is_same<int64_t, jlong>::value, "jlong isn't an int64_t");
static_assert(std::is_same<decltype(uptimeMillis()), int64_t>::value,
"uptimeMillis signature change, expected int64_t return value");
+static_assert(std::is_same<decltype(uptimeNanos()), int64_t>::value,
+ "uptimeNanos signature change, expected int64_t return value");
static_assert(std::is_same<decltype(elapsedRealtime()), int64_t>::value,
- "uptimeMillis signature change, expected int64_t return value");
+ "elapsedRealtime signature change, expected int64_t return value");
static_assert(std::is_same<decltype(elapsedRealtimeNano()), int64_t>::value,
- "uptimeMillis signature change, expected int64_t return value");
+ "elapsedRealtimeNano signature change, expected int64_t return value");
/*
* native public static long currentThreadTimeMillis();
@@ -76,6 +78,7 @@ static const JNINativeMethod gMethods[] = {
// All of these are @CriticalNative, so we can defer directly to SystemClock.h for
// some of these
{ "uptimeMillis", "()J", (void*) uptimeMillis },
+ { "uptimeNanos", "()J", (void*) uptimeNanos },
{ "elapsedRealtime", "()J", (void*) elapsedRealtime },
{ "elapsedRealtimeNanos", "()J", (void*) elapsedRealtimeNano },
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index e715be21f146..50a557bb53a1 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -63,6 +63,7 @@ private:
void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
int32_t configId, nsecs_t vsyncPeriod) override;
+ void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
};
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d6a773fb91e0..85b4fe197980 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -116,7 +116,6 @@ static struct {
jfieldID width;
jfieldID height;
jfieldID useIdentityTransform;
- jfieldID rotation;
} gDisplayCaptureArgsClassInfo;
static struct {
@@ -325,8 +324,6 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
captureArgs.useIdentityTransform =
env->GetBooleanField(displayCaptureArgsObject,
gDisplayCaptureArgsClassInfo.useIdentityTransform);
- captureArgs.rotation = ui::toRotation(
- env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation));
return captureArgs;
}
@@ -1849,8 +1846,6 @@ int register_android_view_SurfaceControl(JNIEnv* env)
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I");
gDisplayCaptureArgsClassInfo.useIdentityTransform =
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z");
- gDisplayCaptureArgsClassInfo.rotation =
- GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I");
jclass layerCaptureArgsClazz =
FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs");
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index eeda275b811c..d629e0dae6dd 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -104,6 +104,31 @@ static inline std::string getStringField(JNIEnv* env, jobject obj, jfieldID fiel
return std::string(defaultValue);
}
+static inline JNIEnv* GetJNIEnvironment(JavaVM* vm, jint version = JNI_VERSION_1_4) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), version) != JNI_OK) {
+ return nullptr;
+ }
+ return env;
+}
+
+static inline JNIEnv* GetOrAttachJNIEnvironment(JavaVM* jvm, jint version = JNI_VERSION_1_4) {
+ JNIEnv* env = GetJNIEnvironment(jvm, version);
+ if (!env) {
+ int result = jvm->AttachCurrentThread(&env, nullptr);
+ LOG_ALWAYS_FATAL_IF(result != JNI_OK, "JVM thread attach failed.");
+ struct VmDetacher {
+ VmDetacher(JavaVM* vm) : mVm(vm) {}
+ ~VmDetacher() { mVm->DetachCurrentThread(); }
+
+ private:
+ JavaVM* const mVm;
+ };
+ static thread_local VmDetacher detacher(jvm);
+ }
+ return env;
+}
+
} // namespace android
#endif // CORE_JNI_HELPERS
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 5b22e3126eaf..1014fbb73877 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2698,4 +2698,9 @@ enum PageId {
// CATEGORY: SETTINGS
// OS: S
EMERGENCY_SOS_GESTURE_SETTINGS = 1847;
+
+ // OPEN: Settings > System > Gestures > Double tap
+ // CATEGORY: SETTINGS
+ // OS: S
+ SETTINGS_COLUMBUS = 1848;
}
diff --git a/core/proto/android/server/protolog.proto b/core/proto/android/internal/protolog.proto
index 34dc55b959c2..fee7a878f860 100644
--- a/core/proto/android/server/protolog.proto
+++ b/core/proto/android/internal/protolog.proto
@@ -16,7 +16,7 @@
syntax = "proto2";
-package com.android.server.protolog;
+package com.android.internal.protolog;
option java_multiple_files = true;
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 2e4169e15c3b..4f55bf51c826 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -470,10 +470,10 @@
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Permet que l\'aplicació impedeixi que la tauleta entri en repòs."</string>
<string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Permet que l\'aplicació impedeixi que el dispositiu Android TV entri en repòs."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Permet que l\'aplicació impedeixi que el telèfon entri en repòs."</string>
- <string name="permlab_transmitIr" msgid="8077196086358004010">"transmissió d\'infraroigs"</string>
- <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Permet que l\'aplicació utilitzi el transmissor d\'infraroigs de la tauleta."</string>
- <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Permet que l\'aplicació faci servir el transmissor d\'infraroigs del dispositiu Android TV."</string>
- <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Permet que l\'aplicació utilitzi el transmissor d\'infraroigs del telèfon."</string>
+ <string name="permlab_transmitIr" msgid="8077196086358004010">"transmissió d\'infrarojos"</string>
+ <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Permet que l\'aplicació utilitzi el transmissor d\'infrarojos de la tauleta."</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Permet que l\'aplicació faci servir el transmissor d\'infrarojos del dispositiu Android TV."</string>
+ <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Permet que l\'aplicació utilitzi el transmissor d\'infrarojos del telèfon."</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"establir fons de pantalla"</string>
<string name="permdesc_setWallpaper" msgid="2973996714129021397">"Permet que l\'aplicació estableixi el fons de pantalla del sistema."</string>
<string name="permlab_setWallpaperHints" msgid="1153485176642032714">"ajustament de la mida del fons de pantalla"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index fd7b1b2ab55a..bb79c2193a36 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1633,7 +1633,7 @@
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"निष्क्रिय"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> लाई तपाईंको यन्त्र पूर्ण रूपमा नियन्त्रण गर्न दिने हो?"</string>
<string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"तपाईंले <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्नुभयो भने तपाईंको यन्त्रले डेटा इन्क्रिप्ट गर्ने सुविधाको स्तरोन्नति गर्न तपाईंको स्क्रिन लक सुविधाको प्रयोग गर्ने छैन।"</string>
- <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने अनुप्रयोगहरूमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
+ <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने एपमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
<string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रिन हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यसले स्क्रिनमा देखिने सबै सामग्री पढ्न सक्छ र अन्य एपहरूमा उक्त सामग्री देखाउन सक्छ।"</string>
<string name="accessibility_service_action_perform_title" msgid="779670378951658160">"कारबाहीहरू हेर्नुहोस् र तिनमा कार्य गर्नुहोस्"</string>
diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml
index 3a1679c19fc8..f46f70c2debf 100644
--- a/core/res/res/values/donottranslate.xml
+++ b/core/res/res/values/donottranslate.xml
@@ -23,7 +23,7 @@
<!-- @hide DO NOT TRANSLATE. Control aspect ratio of lock pattern -->
<string name="lock_pattern_view_aspect">square</string>
<!-- @hide DO NOT TRANSLATE. ICU pattern for "Mon, 14 January" -->
- <string name="icu_abbrev_wday_month_day_no_year">eeeMMMMd</string>
+ <string name="icu_abbrev_wday_month_day_no_year">EEEMMMMd</string>
<!-- @hide DO NOT TRANSLATE. date formatting pattern for system ui.-->
<string name="system_ui_date_pattern">@string/icu_abbrev_wday_month_day_no_year</string>
<!-- @hide DO NOT TRANSLATE Spans within this text are applied to style composing regions
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bddda1bf6f6f..f77c6f99c063 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -197,6 +197,9 @@
<!-- Marks the "copy to clipboard" button in the ChooserActivity -->
<item type="id" name="chooser_copy_button" />
+ <!-- Marks the "nearby" button in the ChooserActivity -->
+ <item type="id" name="chooser_nearby_button" />
+
<!-- Accessibility action identifier for {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK}. -->
<item type="id" name="accessibilitySystemActionBack" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d5c72da2d29f..040fad5e6410 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3841,6 +3841,7 @@
<java-symbol type="layout" name="chooser_dialog_item" />
<java-symbol type="drawable" name="chooser_dialog_background" />
<java-symbol type="id" name="chooser_copy_button" />
+ <java-symbol type="id" name="chooser_nearby_button" />
<java-symbol type="layout" name="chooser_action_button" />
<java-symbol type="dimen" name="chooser_action_button_icon_size" />
<java-symbol type="string" name="config_defaultNearbySharingComponent" />
diff --git a/core/tests/coretests/src/android/app/WindowContextTest.java b/core/tests/coretests/src/android/app/WindowContextTest.java
index 630e16ac80d4..0f9bc4bee99a 100644
--- a/core/tests/coretests/src/android/app/WindowContextTest.java
+++ b/core/tests/coretests/src/android/app/WindowContextTest.java
@@ -30,7 +30,6 @@ import android.view.Display;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -47,7 +46,6 @@ import org.junit.runner.RunWith;
* <p>This test class is a part of Window Manager Service tests and specified in
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
-@FlakyTest(bugId = 150812449, detail = "Remove after confirmed it's stable.")
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/view/WindowMetricsTest.java b/core/tests/coretests/src/android/view/WindowMetricsTest.java
index ddc977d380ae..96df9dda23c7 100644
--- a/core/tests/coretests/src/android/view/WindowMetricsTest.java
+++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java
@@ -27,7 +27,6 @@ import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -46,7 +45,6 @@ import org.junit.runner.RunWith;
* <p>This test class is a part of Window Manager Service tests and specified in
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
-@FlakyTest(bugId = 148789183, detail = "Remove after confirmed it's stable.")
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 090645f6f7a8..787879a6a144 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -590,6 +590,54 @@ public class ChooserActivityTest {
is(1));
}
+
+ @Test
+ public void testNearbyShareLogging() throws Exception {
+ Intent sendIntent = createSendTextIntent();
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+
+ onView(withId(R.id.chooser_nearby_button)).check(matches(isDisplayed()));
+ onView(withId(R.id.chooser_nearby_button)).perform(click());
+
+ ChooserActivityLoggerFake logger =
+ (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+ assertThat(logger.numCalls(), is(6));
+ // first one should be SHARESHEET_TRIGGERED uievent
+ assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(0).event.getId(),
+ is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+ // second one should be SHARESHEET_STARTED event
+ assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+ assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+ assertThat(logger.get(1).mimeType, is("text/plain"));
+ assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+ assertThat(logger.get(1).appProvidedApp, is(0));
+ assertThat(logger.get(1).appProvidedDirect, is(0));
+ assertThat(logger.get(1).isWorkprofile, is(false));
+ assertThat(logger.get(1).previewType, is(3));
+ // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+ assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(2).event.getId(),
+ is(ChooserActivityLogger
+ .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+ // fourth and fifth are just artifacts of test set-up
+ // sixth one should be ranking atom with SHARESHEET_NEARBY_TARGET_SELECTED event
+ assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+ assertThat(logger.get(5).targetType,
+ is(ChooserActivityLogger
+ .SharesheetTargetSelectedEvent.SHARESHEET_NEARBY_TARGET_SELECTED.getId()));
+ }
+
+
@Test
public void oneVisibleImagePreview() throws InterruptedException {
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index d3d5caf3f7e2..16a2fbd6465e 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -21,6 +21,7 @@ import static org.mockito.Mockito.when;
import android.annotation.Nullable;
import android.app.usage.UsageStatsManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -89,6 +90,18 @@ public class ChooserWrapperActivity extends ChooserActivity {
boolean getIsSelected() { return mIsSuccessfullySelected; }
+ @Override
+ protected ComponentName getNearbySharingComponent() {
+ // an arbitrary pre-installed activity that handles this type of intent
+ return ComponentName.unflattenFromString("com.google.android.apps.messaging/"
+ + "com.google.android.apps.messaging.ui.conversationlist.ShareIntentActivity");
+ }
+
+ @Override
+ protected TargetInfo getNearbySharingTarget(Intent originalIntent) {
+ return new ChooserWrapperActivity.EmptyTargetInfo();
+ }
+
UsageStatsManager getUsageStatsManager() {
if (mUsm == null) {
mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 188ba9e0ca0e..96250db4aa51 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.os.Binder;
import android.os.Handler;
@@ -44,6 +45,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
@@ -493,7 +495,9 @@ public class BinderCallsStatsTest {
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
PrintWriter pw = new PrintWriter(new StringWriter());
- bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), true);
+ bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), Process.INVALID_UID, true);
+
+ bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), WORKSOURCE_UID, true);
}
@Test
@@ -606,8 +610,8 @@ public class BinderCallsStatsTest {
assertEquals("-1", callStats.methodName);
assertEquals("com.android.internal.os.BinderCallsStats$OverflowBinder",
callStats.className);
- assertEquals(false , callStats.screenInteractive);
- assertEquals(-1 , callStats.callingUid);
+ assertEquals(false, callStats.screenInteractive);
+ assertEquals(-1, callStats.callingUid);
}
@Test
@@ -785,7 +789,7 @@ public class BinderCallsStatsTest {
bcs.time += 30;
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
- for (Runnable runnable: mHandler.mRunnables) {
+ for (Runnable runnable : mHandler.mRunnables) {
// Execute all pending runnables. Ignore the delay.
runnable.run();
}
@@ -839,6 +843,53 @@ public class BinderCallsStatsTest {
assertEquals(3, tids[2]);
}
+ @Test
+ public void testTrackingSpecificWorksourceUid() {
+ mDeviceState.setCharging(true);
+
+ Binder binder = new Binder();
+
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.recordAllCallsForWorkSourceUid(WORKSOURCE_UID);
+
+ int[] transactions = {41, 42, 43, 42, 43, 43};
+ int[] durationsMs = {100, 200, 300, 400, 500, 600};
+
+ for (int i = 0; i < transactions.length; i++) {
+ CallSession callSession = bcs.callStarted(binder, transactions[i], WORKSOURCE_UID);
+ bcs.time += durationsMs[i];
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+ }
+
+ BinderCallsStats.UidEntry uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
+ Assert.assertNotNull(uidEntry);
+ assertEquals(6, uidEntry.callCount);
+
+ Collection<BinderCallsStats.CallStat> callStatsList = uidEntry.getCallStatsList();
+ assertEquals(3, callStatsList.size());
+ for (BinderCallsStats.CallStat callStat : callStatsList) {
+ switch (callStat.transactionCode) {
+ case 41:
+ assertEquals(1, callStat.callCount);
+ assertEquals(1, callStat.incrementalCallCount);
+ assertEquals(100, callStat.cpuTimeMicros);
+ break;
+ case 42:
+ assertEquals(2, callStat.callCount);
+ assertEquals(2, callStat.incrementalCallCount);
+ assertEquals(200 + 400, callStat.cpuTimeMicros);
+ break;
+ case 43:
+ assertEquals(3, callStat.callCount);
+ assertEquals(3, callStat.incrementalCallCount);
+ assertEquals(300 + 500 + 600, callStat.cpuTimeMicros);
+ break;
+ default:
+ fail("Unexpected transaction code: " + callStat.transactionCode);
+ }
+ }
+ }
+
private static class TestHandler extends Handler {
ArrayList<Runnable> mRunnables = new ArrayList<>();
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 5711f98e3b75..bd2d4af54c83 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -345,10 +345,10 @@ key 377 TV
# key 395 "KEY_LIST"
# key 396 "KEY_MEMO"
key 397 CALENDAR
-# key 398 "KEY_RED"
-# key 399 "KEY_GREEN"
-# key 400 "KEY_YELLOW"
-# key 401 "KEY_BLUE"
+key 398 PROG_RED
+key 399 PROG_GREEN
+key 400 PROG_YELLOW
+key 401 PROG_BLUE
key 402 CHANNEL_UP
key 403 CHANNEL_DOWN
# key 404 "KEY_FIRST"
diff --git a/framework-jarjar-rules.txt b/framework-jarjar-rules.txt
index d8af726ffa72..70dedb8179b0 100644
--- a/framework-jarjar-rules.txt
+++ b/framework-jarjar-rules.txt
@@ -1,2 +1,6 @@
rule android.hidl.** android.internal.hidl.@1
rule android.net.wifi.WifiAnnotations* android.internal.wifi.WifiAnnotations@1
+
+# Hide media mainline module implementation classes to avoid collisions with
+# app-bundled ExoPlayer classes.
+rule com.google.android.exoplayer2.** android.media.internal.exo.@1
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index b3103fd516dd..0452933328e2 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -634,6 +634,19 @@ public class HardwareRenderer {
}
/**
+ * Sets the colormode with the desired SDR white point.
+ *
+ * The white point only applies if the color mode is an HDR mode
+ *
+ * @hide
+ */
+ public void setColorMode(@ActivityInfo.ColorMode int colorMode, float whitePoint) {
+ nSetSdrWhitePoint(mNativeProxy, whitePoint);
+ mColorMode = colorMode;
+ nSetColorMode(mNativeProxy, colorMode);
+ }
+
+ /**
* Blocks until all previously queued work has completed.
*
* TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
@@ -1227,6 +1240,8 @@ public class HardwareRenderer {
private static native void nSetColorMode(long nativeProxy, int colorMode);
+ private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
+
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy, long rootRenderNode);
diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS
index 936ba5cc8311..c232d1360419 100644
--- a/libs/hwui/OWNERS
+++ b/libs/hwui/OWNERS
@@ -1,6 +1,7 @@
+alecmouri@google.com
+djsollen@google.com
jreck@google.com
njawad@google.com
-djsollen@google.com
-stani@google.com
-scroggo@google.com
reed@google.com
+scroggo@google.com
+stani@google.com
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 446e81e65bb8..ba44d056dda3 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -78,6 +78,7 @@ bool Properties::isolatedProcess = false;
int Properties::contextPriority = 0;
int Properties::defaultRenderAhead = -1;
+float Properties::defaultSdrWhitePoint = 200.f;
bool Properties::load() {
bool prevDebugLayersUpdates = debugLayersUpdates;
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c8f6b3b7ff99..85a0f4aa7809 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -249,6 +249,8 @@ public:
static int defaultRenderAhead;
+ static float defaultSdrWhitePoint;
+
private:
static ProfileType sProfileType;
static bool sDisableProfileBars;
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 7d6875f59d17..fc594da19708 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -223,6 +223,11 @@ static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject claz
proxy->setColorMode(static_cast<ColorMode>(colorMode));
}
+static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jfloat sdrWhitePoint) {
+ Properties::defaultSdrWhitePoint = sdrWhitePoint;
+}
+
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
@@ -671,6 +676,7 @@ static const JNINativeMethod gMethods[] = {
{"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
{"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
{"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
+ {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
{"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
{"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
{"nRegisterAnimatingRenderNode", "(JJ)V",
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 644d5fbd5bf9..e4198017aee0 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -559,6 +559,7 @@ void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data,
AStatsEvent_writeBool(event, !lastFullDay);
AStatsEvent_build(event);
}
+ delete dump;
}
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index eff34a83af1b..87512f0354c8 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -26,6 +26,7 @@
#include <algorithm>
#include <cmath>
+#include <Properties.h>
namespace android {
namespace uirenderer {
@@ -344,13 +345,9 @@ SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) {
static_cast<uint8_t>(rgb.b * 255));
}
-// Note that SkColorSpace doesn't have the notion of an unspecified SDR white
-// level.
-static constexpr float kDefaultSDRWhiteLevel = 150.f;
-
skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) {
if (sdr_white_level <= 0.f) {
- sdr_white_level = kDefaultSDRWhiteLevel;
+ sdr_white_level = Properties::defaultSdrWhitePoint;
}
// The generic PQ transfer function produces normalized luminance values i.e.
// the range 0-1 represents 0-10000 nits for the reference display, but we
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 5252cd041199..dca35012cbdd 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -16,6 +16,9 @@ cc_library_shared {
name: "libinputservice",
srcs: [
"PointerController.cpp",
+ "PointerControllerContext.cpp",
+ "MouseCursorController.cpp",
+ "TouchSpotController.cpp",
"SpriteController.cpp",
"SpriteIcon.cpp",
],
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
new file mode 100644
index 000000000000..80b555be97dd
--- /dev/null
+++ b/libs/input/MouseCursorController.cpp
@@ -0,0 +1,460 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "MouseCursorController"
+//#define LOG_NDEBUG 0
+
+// Log debug messages about pointer updates
+#define DEBUG_MOUSE_CURSOR_UPDATES 0
+
+#include "MouseCursorController.h"
+
+#include <log/log.h>
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
+
+namespace {
+// Time to spend fading out the pointer completely.
+const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
+} // namespace
+
+namespace android {
+
+// --- MouseCursorController ---
+
+MouseCursorController::MouseCursorController(PointerControllerContext& context)
+ : mContext(context) {
+ std::scoped_lock lock(mLock);
+
+ mLocked.animationFrameIndex = 0;
+ mLocked.lastFrameUpdatedTime = 0;
+
+ mLocked.pointerFadeDirection = 0;
+ mLocked.pointerX = 0;
+ mLocked.pointerY = 0;
+ mLocked.pointerAlpha = 0.0f; // pointer is initially faded
+ mLocked.pointerSprite = mContext.getSpriteController()->createSprite();
+ mLocked.updatePointerIcon = false;
+ mLocked.requestedPointerType = mContext.getPolicy()->getDefaultPointerIconId();
+
+ mLocked.resourcesLoaded = false;
+
+ mLocked.buttonState = 0;
+}
+
+MouseCursorController::~MouseCursorController() {
+ std::scoped_lock lock(mLock);
+
+ mLocked.pointerSprite.clear();
+}
+
+bool MouseCursorController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
+ float* outMaxY) const {
+ std::scoped_lock lock(mLock);
+
+ return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
+}
+
+bool MouseCursorController::getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX,
+ float* outMaxY) const REQUIRES(mLock) {
+ if (!mLocked.viewport.isValid()) {
+ return false;
+ }
+
+ *outMinX = mLocked.viewport.logicalLeft;
+ *outMinY = mLocked.viewport.logicalTop;
+ *outMaxX = mLocked.viewport.logicalRight - 1;
+ *outMaxY = mLocked.viewport.logicalBottom - 1;
+ return true;
+}
+
+void MouseCursorController::move(float deltaX, float deltaY) {
+#if DEBUG_MOUSE_CURSOR_UPDATES
+ ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
+#endif
+ if (deltaX == 0.0f && deltaY == 0.0f) {
+ return;
+ }
+
+ std::scoped_lock lock(mLock);
+
+ setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
+}
+
+void MouseCursorController::setButtonState(int32_t buttonState) {
+#if DEBUG_MOUSE_CURSOR_UPDATES
+ ALOGD("Set button state 0x%08x", buttonState);
+#endif
+ std::scoped_lock lock(mLock);
+
+ if (mLocked.buttonState != buttonState) {
+ mLocked.buttonState = buttonState;
+ }
+}
+
+int32_t MouseCursorController::getButtonState() const {
+ std::scoped_lock lock(mLock);
+ return mLocked.buttonState;
+}
+
+void MouseCursorController::setPosition(float x, float y) {
+#if DEBUG_MOUSE_CURSOR_UPDATES
+ ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
+#endif
+ std::scoped_lock lock(mLock);
+ setPositionLocked(x, y);
+}
+
+void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
+ float minX, minY, maxX, maxY;
+ if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+ if (x <= minX) {
+ mLocked.pointerX = minX;
+ } else if (x >= maxX) {
+ mLocked.pointerX = maxX;
+ } else {
+ mLocked.pointerX = x;
+ }
+ if (y <= minY) {
+ mLocked.pointerY = minY;
+ } else if (y >= maxY) {
+ mLocked.pointerY = maxY;
+ } else {
+ mLocked.pointerY = y;
+ }
+ updatePointerLocked();
+ }
+}
+
+void MouseCursorController::getPosition(float* outX, float* outY) const {
+ std::scoped_lock lock(mLock);
+
+ *outX = mLocked.pointerX;
+ *outY = mLocked.pointerY;
+}
+
+int32_t MouseCursorController::getDisplayId() const {
+ std::scoped_lock lock(mLock);
+ return mLocked.viewport.displayId;
+}
+
+void MouseCursorController::fade(PointerControllerInterface::Transition transition) {
+ std::scoped_lock lock(mLock);
+
+ // Remove the inactivity timeout, since we are fading now.
+ mContext.removeInactivityTimeout();
+
+ // Start fading.
+ if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
+ mLocked.pointerFadeDirection = 0;
+ mLocked.pointerAlpha = 0.0f;
+ updatePointerLocked();
+ } else {
+ mLocked.pointerFadeDirection = -1;
+ mContext.startAnimation();
+ }
+}
+
+void MouseCursorController::unfade(PointerControllerInterface::Transition transition) {
+ std::scoped_lock lock(mLock);
+
+ // Always reset the inactivity timer.
+ mContext.resetInactivityTimeout();
+
+ // Start unfading.
+ if (transition == PointerControllerInterface::Transition::IMMEDIATE) {
+ mLocked.pointerFadeDirection = 0;
+ mLocked.pointerAlpha = 1.0f;
+ updatePointerLocked();
+ } else {
+ mLocked.pointerFadeDirection = 1;
+ mContext.startAnimation();
+ }
+}
+
+void MouseCursorController::reloadPointerResources(bool getAdditionalMouseResources) {
+ std::scoped_lock lock(mLock);
+
+ loadResourcesLocked(getAdditionalMouseResources);
+ updatePointerLocked();
+}
+
+/**
+ * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
+ * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
+ */
+static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
+ width = viewport.deviceWidth;
+ height = viewport.deviceHeight;
+
+ if (viewport.orientation == DISPLAY_ORIENTATION_90 ||
+ viewport.orientation == DISPLAY_ORIENTATION_270) {
+ std::swap(width, height);
+ }
+}
+
+void MouseCursorController::setDisplayViewport(const DisplayViewport& viewport,
+ bool getAdditionalMouseResources) {
+ std::scoped_lock lock(mLock);
+
+ if (viewport == mLocked.viewport) {
+ return;
+ }
+
+ const DisplayViewport oldViewport = mLocked.viewport;
+ mLocked.viewport = viewport;
+
+ int32_t oldDisplayWidth, oldDisplayHeight;
+ getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
+ int32_t newDisplayWidth, newDisplayHeight;
+ getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
+
+ // Reset cursor position to center if size or display changed.
+ if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
+ oldDisplayHeight != newDisplayHeight) {
+ float minX, minY, maxX, maxY;
+ if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+ mLocked.pointerX = (minX + maxX) * 0.5f;
+ mLocked.pointerY = (minY + maxY) * 0.5f;
+ // Reload icon resources for density may be changed.
+ loadResourcesLocked(getAdditionalMouseResources);
+ } else {
+ mLocked.pointerX = 0;
+ mLocked.pointerY = 0;
+ }
+ } else if (oldViewport.orientation != viewport.orientation) {
+ // Apply offsets to convert from the pixel top-left corner position to the pixel center.
+ // This creates an invariant frame of reference that we can easily rotate when
+ // taking into account that the pointer may be located at fractional pixel offsets.
+ float x = mLocked.pointerX + 0.5f;
+ float y = mLocked.pointerY + 0.5f;
+ float temp;
+
+ // Undo the previous rotation.
+ switch (oldViewport.orientation) {
+ case DISPLAY_ORIENTATION_90:
+ temp = x;
+ x = oldViewport.deviceHeight - y;
+ y = temp;
+ break;
+ case DISPLAY_ORIENTATION_180:
+ x = oldViewport.deviceWidth - x;
+ y = oldViewport.deviceHeight - y;
+ break;
+ case DISPLAY_ORIENTATION_270:
+ temp = x;
+ x = y;
+ y = oldViewport.deviceWidth - temp;
+ break;
+ }
+
+ // Perform the new rotation.
+ switch (viewport.orientation) {
+ case DISPLAY_ORIENTATION_90:
+ temp = x;
+ x = y;
+ y = viewport.deviceHeight - temp;
+ break;
+ case DISPLAY_ORIENTATION_180:
+ x = viewport.deviceWidth - x;
+ y = viewport.deviceHeight - y;
+ break;
+ case DISPLAY_ORIENTATION_270:
+ temp = x;
+ x = viewport.deviceWidth - y;
+ y = temp;
+ break;
+ }
+
+ // Apply offsets to convert from the pixel center to the pixel top-left corner position
+ // and save the results.
+ mLocked.pointerX = x - 0.5f;
+ mLocked.pointerY = y - 0.5f;
+ }
+
+ updatePointerLocked();
+}
+
+void MouseCursorController::updatePointerIcon(int32_t iconId) {
+ std::scoped_lock lock(mLock);
+
+ if (mLocked.requestedPointerType != iconId) {
+ mLocked.requestedPointerType = iconId;
+ mLocked.updatePointerIcon = true;
+ updatePointerLocked();
+ }
+}
+
+void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
+ std::scoped_lock lock(mLock);
+
+ const int32_t iconId = mContext.getPolicy()->getCustomPointerIconId();
+ mLocked.additionalMouseResources[iconId] = icon;
+ mLocked.requestedPointerType = iconId;
+ mLocked.updatePointerIcon = true;
+ updatePointerLocked();
+}
+
+bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) {
+ nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
+
+ std::scoped_lock lock(mLock);
+
+ // Animate pointer fade.
+ if (mLocked.pointerFadeDirection < 0) {
+ mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
+ if (mLocked.pointerAlpha <= 0.0f) {
+ mLocked.pointerAlpha = 0.0f;
+ mLocked.pointerFadeDirection = 0;
+ } else {
+ keepAnimating = true;
+ }
+ updatePointerLocked();
+ } else if (mLocked.pointerFadeDirection > 0) {
+ mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
+ if (mLocked.pointerAlpha >= 1.0f) {
+ mLocked.pointerAlpha = 1.0f;
+ mLocked.pointerFadeDirection = 0;
+ } else {
+ keepAnimating = true;
+ }
+ updatePointerLocked();
+ }
+
+ return keepAnimating;
+}
+
+bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) {
+ std::scoped_lock lock(mLock);
+
+ std::map<int32_t, PointerAnimation>::const_iterator iter =
+ mLocked.animationResources.find(mLocked.requestedPointerType);
+ if (iter == mLocked.animationResources.end()) {
+ return false;
+ }
+
+ if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
+ sp<SpriteController> spriteController = mContext.getSpriteController();
+ spriteController->openTransaction();
+
+ int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
+ mLocked.animationFrameIndex += incr;
+ mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
+ while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
+ mLocked.animationFrameIndex -= iter->second.animationFrames.size();
+ }
+ mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
+
+ spriteController->closeTransaction();
+ }
+
+ // Keep animating.
+ return true;
+}
+
+void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
+ sp<SpriteController> spriteController = mContext.getSpriteController();
+ spriteController->openTransaction();
+
+ mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
+ mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
+ mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
+
+ if (mLocked.pointerAlpha > 0) {
+ mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
+ mLocked.pointerSprite->setVisible(true);
+ } else {
+ mLocked.pointerSprite->setVisible(false);
+ }
+
+ if (mLocked.updatePointerIcon) {
+ if (mLocked.requestedPointerType == mContext.getPolicy()->getDefaultPointerIconId()) {
+ mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+ } else {
+ std::map<int32_t, SpriteIcon>::const_iterator iter =
+ mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
+ if (iter != mLocked.additionalMouseResources.end()) {
+ std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
+ mLocked.animationResources.find(mLocked.requestedPointerType);
+ if (anim_iter != mLocked.animationResources.end()) {
+ mLocked.animationFrameIndex = 0;
+ mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ mContext.startAnimation();
+ }
+ mLocked.pointerSprite->setIcon(iter->second);
+ } else {
+ ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
+ mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+ }
+ }
+ mLocked.updatePointerIcon = false;
+ }
+
+ spriteController->closeTransaction();
+}
+
+void MouseCursorController::loadResourcesLocked(bool getAdditionalMouseResources) REQUIRES(mLock) {
+ if (!mLocked.viewport.isValid()) {
+ return;
+ }
+
+ if (!mLocked.resourcesLoaded) mLocked.resourcesLoaded = true;
+
+ sp<PointerControllerPolicyInterface> policy = mContext.getPolicy();
+ policy->loadPointerResources(&mResources, mLocked.viewport.displayId);
+ policy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
+
+ mLocked.additionalMouseResources.clear();
+ mLocked.animationResources.clear();
+ if (getAdditionalMouseResources) {
+ policy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
+ &mLocked.animationResources,
+ mLocked.viewport.displayId);
+ }
+
+ mLocked.updatePointerIcon = true;
+}
+
+bool MouseCursorController::isViewportValid() {
+ std::scoped_lock lock(mLock);
+ return mLocked.viewport.isValid();
+}
+
+void MouseCursorController::getAdditionalMouseResources() {
+ std::scoped_lock lock(mLock);
+
+ if (mLocked.additionalMouseResources.empty()) {
+ mContext.getPolicy()->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
+ &mLocked.animationResources,
+ mLocked.viewport.displayId);
+ }
+ mLocked.updatePointerIcon = true;
+ updatePointerLocked();
+}
+
+bool MouseCursorController::resourcesLoaded() {
+ std::scoped_lock lock(mLock);
+ return mLocked.resourcesLoaded;
+}
+
+} // namespace android
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
new file mode 100644
index 000000000000..448165b5ac46
--- /dev/null
+++ b/libs/input/MouseCursorController.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_MOUSE_CURSOR_CONTROLLER_H
+#define _UI_MOUSE_CURSOR_CONTROLLER_H
+
+#include <gui/DisplayEventReceiver.h>
+#include <input/DisplayViewport.h>
+#include <input/Input.h>
+#include <ui/DisplayInfo.h>
+#include <utils/BitSet.h>
+#include <utils/Looper.h>
+#include <utils/RefBase.h>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "PointerControllerContext.h"
+#include "SpriteController.h"
+
+namespace android {
+
+/*
+ * Helper class for PointerController that specifically handles
+ * mouse cursor resources and actions.
+ */
+class MouseCursorController {
+public:
+ MouseCursorController(PointerControllerContext& context);
+ ~MouseCursorController();
+
+ bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+ void move(float deltaX, float deltaY);
+ void setButtonState(int32_t buttonState);
+ int32_t getButtonState() const;
+ void setPosition(float x, float y);
+ void getPosition(float* outX, float* outY) const;
+ int32_t getDisplayId() const;
+ void fade(PointerControllerInterface::Transition transition);
+ void unfade(PointerControllerInterface::Transition transition);
+ void setDisplayViewport(const DisplayViewport& viewport, bool getAdditionalMouseResources);
+
+ void updatePointerIcon(int32_t iconId);
+ void setCustomPointerIcon(const SpriteIcon& icon);
+ void reloadPointerResources(bool getAdditionalMouseResources);
+
+ void getAdditionalMouseResources();
+ bool isViewportValid();
+
+ bool doBitmapAnimation(nsecs_t timestamp);
+ bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating);
+
+ bool resourcesLoaded();
+
+private:
+ mutable std::mutex mLock;
+
+ PointerResources mResources;
+
+ PointerControllerContext& mContext;
+
+ struct Locked {
+ DisplayViewport viewport;
+
+ size_t animationFrameIndex;
+ nsecs_t lastFrameUpdatedTime;
+
+ int32_t pointerFadeDirection;
+ float pointerX;
+ float pointerY;
+ float pointerAlpha;
+ sp<Sprite> pointerSprite;
+ SpriteIcon pointerIcon;
+ bool updatePointerIcon;
+
+ bool resourcesLoaded;
+
+ std::map<int32_t, SpriteIcon> additionalMouseResources;
+ std::map<int32_t, PointerAnimation> animationResources;
+
+ int32_t requestedPointerType;
+
+ int32_t buttonState;
+
+ } mLocked GUARDED_BY(mLock);
+
+ bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+ void setPositionLocked(float x, float y);
+
+ void updatePointerLocked();
+
+ void loadResourcesLocked(bool getAdditionalMouseResources);
+};
+
+} // namespace android
+
+#endif // _UI_MOUSE_CURSOR_CONTROLLER_H
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 5e480a66c355..14c96cefd462 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -21,31 +21,26 @@
#define DEBUG_POINTER_UPDATES 0
#include "PointerController.h"
+#include "MouseCursorController.h"
+#include "PointerControllerContext.h"
+#include "TouchSpotController.h"
#include <log/log.h>
-#include <memory>
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
namespace android {
// --- PointerController ---
-// Time to wait before starting the fade when the pointer is inactive.
-static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
-static const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
-
-// Time to spend fading out the spot completely.
-static const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
-
-// Time to spend fading out the pointer completely.
-static const nsecs_t POINTER_FADE_DURATION = 500 * 1000000LL; // 500 ms
-
-// The number of events to be read at once for DisplayEventReceiver.
-static const int EVENT_BUFFER_SIZE = 100;
-
std::shared_ptr<PointerController> PointerController::create(
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController) {
+ // using 'new' to access non-public constructor
std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
new PointerController(policy, looper, spriteController));
@@ -60,758 +55,175 @@ std::shared_ptr<PointerController> PointerController::create(
* weak_ptr's which themselves cannot be constructed until there's at least one shared_ptr.
*/
- controller->mHandler->pointerController = controller;
- controller->mCallback->pointerController = controller;
- if (controller->mDisplayEventReceiver.initCheck() == NO_ERROR) {
- controller->mLooper->addFd(controller->mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
- Looper::EVENT_INPUT, controller->mCallback, nullptr);
- } else {
- ALOGE("Failed to initialize DisplayEventReceiver.");
- }
+ controller->mContext.setHandlerController(controller);
+ controller->mContext.setCallbackController(controller);
+ controller->mContext.initializeDisplayEventReceiver();
return controller;
}
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
const sp<SpriteController>& spriteController)
- : mPolicy(policy),
- mLooper(looper),
- mSpriteController(spriteController),
- mHandler(new MessageHandler()),
- mCallback(new LooperCallback()) {
- AutoMutex _l(mLock);
-
- mLocked.animationPending = false;
-
- mLocked.presentation = Presentation::POINTER;
- mLocked.presentationChanged = false;
-
- mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
-
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
- mLocked.pointerAlpha = 0.0f; // pointer is initially faded
- mLocked.pointerSprite = mSpriteController->createSprite();
- mLocked.pointerIconChanged = false;
- mLocked.requestedPointerType = mPolicy->getDefaultPointerIconId();
-
- mLocked.animationFrameIndex = 0;
- mLocked.lastFrameUpdatedTime = 0;
-
- mLocked.buttonState = 0;
+ : mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
+ std::scoped_lock lock(mLock);
+ mLocked.presentation = Presentation::SPOT;
}
-PointerController::~PointerController() {
- mLooper->removeMessages(mHandler);
-
- AutoMutex _l(mLock);
-
- mLocked.pointerSprite.clear();
-
- for (auto& it : mLocked.spotsByDisplay) {
- const std::vector<Spot*>& spots = it.second;
- size_t numSpots = spots.size();
- for (size_t i = 0; i < numSpots; i++) {
- delete spots[i];
- }
- }
- mLocked.spotsByDisplay.clear();
- mLocked.recycledSprites.clear();
-}
-
-bool PointerController::getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const {
- AutoMutex _l(mLock);
-
- return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
-}
-
-bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const {
-
- if (!mLocked.viewport.isValid()) {
- return false;
- }
-
- *outMinX = mLocked.viewport.logicalLeft;
- *outMinY = mLocked.viewport.logicalTop;
- *outMaxX = mLocked.viewport.logicalRight - 1;
- *outMaxY = mLocked.viewport.logicalBottom - 1;
- return true;
+bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
+ float* outMaxY) const {
+ return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY);
}
void PointerController::move(float deltaX, float deltaY) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
-#endif
- if (deltaX == 0.0f && deltaY == 0.0f) {
- return;
- }
-
- AutoMutex _l(mLock);
-
- setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
+ mCursorController.move(deltaX, deltaY);
}
void PointerController::setButtonState(int32_t buttonState) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Set button state 0x%08x", buttonState);
-#endif
- AutoMutex _l(mLock);
-
- if (mLocked.buttonState != buttonState) {
- mLocked.buttonState = buttonState;
- }
+ mCursorController.setButtonState(buttonState);
}
int32_t PointerController::getButtonState() const {
- AutoMutex _l(mLock);
-
- return mLocked.buttonState;
+ return mCursorController.getButtonState();
}
void PointerController::setPosition(float x, float y) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
-#endif
- AutoMutex _l(mLock);
-
- setPositionLocked(x, y);
-}
-
-void PointerController::setPositionLocked(float x, float y) {
- float minX, minY, maxX, maxY;
- if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
- if (x <= minX) {
- mLocked.pointerX = minX;
- } else if (x >= maxX) {
- mLocked.pointerX = maxX;
- } else {
- mLocked.pointerX = x;
- }
- if (y <= minY) {
- mLocked.pointerY = minY;
- } else if (y >= maxY) {
- mLocked.pointerY = maxY;
- } else {
- mLocked.pointerY = y;
- }
- updatePointerLocked();
- }
+ std::scoped_lock lock(mLock);
+ mCursorController.setPosition(x, y);
}
void PointerController::getPosition(float* outX, float* outY) const {
- AutoMutex _l(mLock);
-
- *outX = mLocked.pointerX;
- *outY = mLocked.pointerY;
+ mCursorController.getPosition(outX, outY);
}
int32_t PointerController::getDisplayId() const {
- AutoMutex _l(mLock);
-
- return mLocked.viewport.displayId;
+ return mCursorController.getDisplayId();
}
void PointerController::fade(Transition transition) {
- AutoMutex _l(mLock);
-
- // Remove the inactivity timeout, since we are fading now.
- removeInactivityTimeoutLocked();
-
- // Start fading.
- if (transition == Transition::IMMEDIATE) {
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerAlpha = 0.0f;
- updatePointerLocked();
- } else {
- mLocked.pointerFadeDirection = -1;
- startAnimationLocked();
- }
+ std::scoped_lock lock(mLock);
+ mCursorController.fade(transition);
}
void PointerController::unfade(Transition transition) {
- AutoMutex _l(mLock);
-
- // Always reset the inactivity timer.
- resetInactivityTimeoutLocked();
-
- // Start unfading.
- if (transition == Transition::IMMEDIATE) {
- mLocked.pointerFadeDirection = 0;
- mLocked.pointerAlpha = 1.0f;
- updatePointerLocked();
- } else {
- mLocked.pointerFadeDirection = 1;
- startAnimationLocked();
- }
+ std::scoped_lock lock(mLock);
+ mCursorController.unfade(transition);
}
void PointerController::setPresentation(Presentation presentation) {
- AutoMutex _l(mLock);
+ std::scoped_lock lock(mLock);
if (mLocked.presentation == presentation) {
return;
}
mLocked.presentation = presentation;
- mLocked.presentationChanged = true;
- if (!mLocked.viewport.isValid()) {
+ if (!mCursorController.isViewportValid()) {
return;
}
if (presentation == Presentation::POINTER) {
- if (mLocked.additionalMouseResources.empty()) {
- mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources,
- mLocked.viewport.displayId);
- }
- fadeOutAndReleaseAllSpotsLocked();
- updatePointerLocked();
+ mCursorController.getAdditionalMouseResources();
+ clearSpotsLocked();
}
}
-void PointerController::setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
-#if DEBUG_POINTER_UPDATES
- ALOGD("setSpots: idBits=%08x", spotIdBits.value);
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.firstMarkedBit();
- idBits.clearBit(id);
- const PointerCoords& c = spotCoords[spotIdToIndex[id]];
- ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
- c.getAxisValue(AMOTION_EVENT_AXIS_X),
- c.getAxisValue(AMOTION_EVENT_AXIS_Y),
- c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- displayId);
+void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+ BitSet32 spotIdBits, int32_t displayId) {
+ std::scoped_lock lock(mLock);
+ auto it = mLocked.spotControllers.find(displayId);
+ if (it == mLocked.spotControllers.end()) {
+ mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
}
-#endif
-
- AutoMutex _l(mLock);
- if (!mLocked.viewport.isValid()) {
- return;
- }
-
- std::vector<Spot*> newSpots;
- std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
- mLocked.spotsByDisplay.find(displayId);
- if (iter != mLocked.spotsByDisplay.end()) {
- newSpots = iter->second;
- }
-
- mSpriteController->openTransaction();
-
- // Add or move spots for fingers that are down.
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const PointerCoords& c = spotCoords[spotIdToIndex[id]];
- const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
- ? mResources.spotTouch : mResources.spotHover;
- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
-
- Spot* spot = getSpot(id, newSpots);
- if (!spot) {
- spot = createAndAddSpotLocked(id, newSpots);
- }
-
- spot->updateSprite(&icon, x, y, displayId);
- }
-
- // Remove spots for fingers that went up.
- for (size_t i = 0; i < newSpots.size(); i++) {
- Spot* spot = newSpots[i];
- if (spot->id != Spot::INVALID_ID
- && !spotIdBits.hasBit(spot->id)) {
- fadeOutAndReleaseSpotLocked(spot);
- }
- }
-
- mSpriteController->closeTransaction();
- mLocked.spotsByDisplay[displayId] = newSpots;
+ mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
}
void PointerController::clearSpots() {
-#if DEBUG_POINTER_UPDATES
- ALOGD("clearSpots");
-#endif
+ std::scoped_lock lock(mLock);
+ clearSpotsLocked();
+}
- AutoMutex _l(mLock);
- if (!mLocked.viewport.isValid()) {
- return;
+void PointerController::clearSpotsLocked() REQUIRES(mLock) {
+ for (auto& [displayID, spotController] : mLocked.spotControllers) {
+ spotController.clearSpots();
}
-
- fadeOutAndReleaseAllSpotsLocked();
}
void PointerController::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
- AutoMutex _l(mLock);
-
- if (mLocked.inactivityTimeout != inactivityTimeout) {
- mLocked.inactivityTimeout = inactivityTimeout;
- resetInactivityTimeoutLocked();
- }
+ mContext.setInactivityTimeout(inactivityTimeout);
}
void PointerController::reloadPointerResources() {
- AutoMutex _l(mLock);
+ std::scoped_lock lock(mLock);
- loadResourcesLocked();
- updatePointerLocked();
-}
-
-/**
- * The viewport values for deviceHeight and deviceWidth have already been adjusted for rotation,
- * so here we are getting the dimensions in the original, unrotated orientation (orientation 0).
- */
-static void getNonRotatedSize(const DisplayViewport& viewport, int32_t& width, int32_t& height) {
- width = viewport.deviceWidth;
- height = viewport.deviceHeight;
+ for (auto& [displayID, spotController] : mLocked.spotControllers) {
+ spotController.reloadSpotResources();
+ }
- if (viewport.orientation == DISPLAY_ORIENTATION_90
- || viewport.orientation == DISPLAY_ORIENTATION_270) {
- std::swap(width, height);
+ if (mCursorController.resourcesLoaded()) {
+ bool getAdditionalMouseResources = false;
+ if (mLocked.presentation == PointerController::Presentation::POINTER) {
+ getAdditionalMouseResources = true;
+ }
+ mCursorController.reloadPointerResources(getAdditionalMouseResources);
}
}
void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
- AutoMutex _l(mLock);
- if (viewport == mLocked.viewport) {
- return;
- }
-
- const DisplayViewport oldViewport = mLocked.viewport;
- mLocked.viewport = viewport;
-
- int32_t oldDisplayWidth, oldDisplayHeight;
- getNonRotatedSize(oldViewport, oldDisplayWidth, oldDisplayHeight);
- int32_t newDisplayWidth, newDisplayHeight;
- getNonRotatedSize(viewport, newDisplayWidth, newDisplayHeight);
-
- // Reset cursor position to center if size or display changed.
- if (oldViewport.displayId != viewport.displayId
- || oldDisplayWidth != newDisplayWidth
- || oldDisplayHeight != newDisplayHeight) {
-
- float minX, minY, maxX, maxY;
- if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
- mLocked.pointerX = (minX + maxX) * 0.5f;
- mLocked.pointerY = (minY + maxY) * 0.5f;
- // Reload icon resources for density may be changed.
- loadResourcesLocked();
- } else {
- mLocked.pointerX = 0;
- mLocked.pointerY = 0;
- }
+ std::scoped_lock lock(mLock);
- fadeOutAndReleaseAllSpotsLocked();
- } else if (oldViewport.orientation != viewport.orientation) {
- // Apply offsets to convert from the pixel top-left corner position to the pixel center.
- // This creates an invariant frame of reference that we can easily rotate when
- // taking into account that the pointer may be located at fractional pixel offsets.
- float x = mLocked.pointerX + 0.5f;
- float y = mLocked.pointerY + 0.5f;
- float temp;
-
- // Undo the previous rotation.
- switch (oldViewport.orientation) {
- case DISPLAY_ORIENTATION_90:
- temp = x;
- x = oldViewport.deviceHeight - y;
- y = temp;
- break;
- case DISPLAY_ORIENTATION_180:
- x = oldViewport.deviceWidth - x;
- y = oldViewport.deviceHeight - y;
- break;
- case DISPLAY_ORIENTATION_270:
- temp = x;
- x = y;
- y = oldViewport.deviceWidth - temp;
- break;
- }
-
- // Perform the new rotation.
- switch (viewport.orientation) {
- case DISPLAY_ORIENTATION_90:
- temp = x;
- x = y;
- y = viewport.deviceHeight - temp;
- break;
- case DISPLAY_ORIENTATION_180:
- x = viewport.deviceWidth - x;
- y = viewport.deviceHeight - y;
- break;
- case DISPLAY_ORIENTATION_270:
- temp = x;
- x = viewport.deviceWidth - y;
- y = temp;
- break;
- }
-
- // Apply offsets to convert from the pixel center to the pixel top-left corner position
- // and save the results.
- mLocked.pointerX = x - 0.5f;
- mLocked.pointerY = y - 0.5f;
+ bool getAdditionalMouseResources = false;
+ if (mLocked.presentation == PointerController::Presentation::POINTER) {
+ getAdditionalMouseResources = true;
}
-
- updatePointerLocked();
+ mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
}
void PointerController::updatePointerIcon(int32_t iconId) {
- AutoMutex _l(mLock);
- if (mLocked.requestedPointerType != iconId) {
- mLocked.requestedPointerType = iconId;
- mLocked.presentationChanged = true;
- updatePointerLocked();
- }
+ std::scoped_lock lock(mLock);
+ mCursorController.updatePointerIcon(iconId);
}
void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
- AutoMutex _l(mLock);
-
- const int32_t iconId = mPolicy->getCustomPointerIconId();
- mLocked.additionalMouseResources[iconId] = icon;
- mLocked.requestedPointerType = iconId;
- mLocked.presentationChanged = true;
-
- updatePointerLocked();
-}
-
-void PointerController::MessageHandler::handleMessage(const Message& message) {
- std::shared_ptr<PointerController> controller = pointerController.lock();
-
- if (controller == nullptr) {
- ALOGE("PointerController instance was released before processing message: what=%d",
- message.what);
- return;
- }
- switch (message.what) {
- case MSG_INACTIVITY_TIMEOUT:
- controller->doInactivityTimeout();
- break;
- }
-}
-
-int PointerController::LooperCallback::handleEvent(int /* fd */, int events, void* /* data */) {
- std::shared_ptr<PointerController> controller = pointerController.lock();
- if (controller == nullptr) {
- ALOGW("PointerController instance was released with pending callbacks. events=0x%x",
- events);
- return 0; // Remove the callback, the PointerController is gone anyways
- }
- if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
- ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events);
- return 0; // remove the callback
- }
-
- if (!(events & Looper::EVENT_INPUT)) {
- ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events);
- return 1; // keep the callback
- }
-
- bool gotVsync = false;
- ssize_t n;
- nsecs_t timestamp;
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- while ((n = controller->mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
- if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- timestamp = buf[i].header.timestamp;
- gotVsync = true;
- }
- }
- }
- if (gotVsync) {
- controller->doAnimate(timestamp);
- }
- return 1; // keep the callback
+ std::scoped_lock lock(mLock);
+ mCursorController.setCustomPointerIcon(icon);
}
void PointerController::doAnimate(nsecs_t timestamp) {
- AutoMutex _l(mLock);
-
- mLocked.animationPending = false;
+ std::scoped_lock lock(mLock);
- bool keepFading = doFadingAnimationLocked(timestamp);
- bool keepBitmapFlipping = doBitmapAnimationLocked(timestamp);
- if (keepFading || keepBitmapFlipping) {
- startAnimationLocked();
- }
-}
+ mContext.setAnimationPending(false);
-bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
- bool keepAnimating = false;
- nsecs_t frameDelay = timestamp - mLocked.animationTime;
+ bool keepFading = false;
+ keepFading = mCursorController.doFadingAnimation(timestamp, keepFading);
- // Animate pointer fade.
- if (mLocked.pointerFadeDirection < 0) {
- mLocked.pointerAlpha -= float(frameDelay) / POINTER_FADE_DURATION;
- if (mLocked.pointerAlpha <= 0.0f) {
- mLocked.pointerAlpha = 0.0f;
- mLocked.pointerFadeDirection = 0;
- } else {
- keepAnimating = true;
- }
- updatePointerLocked();
- } else if (mLocked.pointerFadeDirection > 0) {
- mLocked.pointerAlpha += float(frameDelay) / POINTER_FADE_DURATION;
- if (mLocked.pointerAlpha >= 1.0f) {
- mLocked.pointerAlpha = 1.0f;
- mLocked.pointerFadeDirection = 0;
- } else {
- keepAnimating = true;
- }
- updatePointerLocked();
+ for (auto& [displayID, spotController] : mLocked.spotControllers) {
+ keepFading = spotController.doFadingAnimation(timestamp, keepFading);
}
- // Animate spots that are fading out and being removed.
- for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
- std::vector<Spot*>& spots = it->second;
- size_t numSpots = spots.size();
- for (size_t i = 0; i < numSpots;) {
- Spot* spot = spots[i];
- if (spot->id == Spot::INVALID_ID) {
- spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
- if (spot->alpha <= 0) {
- spots.erase(spots.begin() + i);
- releaseSpotLocked(spot);
- numSpots--;
- continue;
- } else {
- spot->sprite->setAlpha(spot->alpha);
- keepAnimating = true;
- }
- }
- ++i;
- }
-
- if (spots.size() == 0) {
- it = mLocked.spotsByDisplay.erase(it);
- } else {
- ++it;
- }
- }
-
- return keepAnimating;
-}
-
-bool PointerController::doBitmapAnimationLocked(nsecs_t timestamp) {
- std::map<int32_t, PointerAnimation>::const_iterator iter = mLocked.animationResources.find(
- mLocked.requestedPointerType);
- if (iter == mLocked.animationResources.end()) {
- return false;
- }
-
- if (timestamp - mLocked.lastFrameUpdatedTime > iter->second.durationPerFrame) {
- mSpriteController->openTransaction();
-
- int incr = (timestamp - mLocked.lastFrameUpdatedTime) / iter->second.durationPerFrame;
- mLocked.animationFrameIndex += incr;
- mLocked.lastFrameUpdatedTime += iter->second.durationPerFrame * incr;
- while (mLocked.animationFrameIndex >= iter->second.animationFrames.size()) {
- mLocked.animationFrameIndex -= iter->second.animationFrames.size();
- }
- mLocked.pointerSprite->setIcon(iter->second.animationFrames[mLocked.animationFrameIndex]);
-
- mSpriteController->closeTransaction();
+ bool keepBitmapFlipping = mCursorController.doBitmapAnimation(timestamp);
+ if (keepFading || keepBitmapFlipping) {
+ mContext.startAnimation();
}
-
- // Keep animating.
- return true;
}
void PointerController::doInactivityTimeout() {
fade(Transition::GRADUAL);
}
-void PointerController::startAnimationLocked() {
- if (!mLocked.animationPending) {
- mLocked.animationPending = true;
- mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
- mDisplayEventReceiver.requestNextVsync();
- }
-}
-
-void PointerController::resetInactivityTimeoutLocked() {
- mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
-
- nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
- ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
- : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
- mLooper->sendMessageDelayed(timeout, mHandler, MSG_INACTIVITY_TIMEOUT);
-}
-
-void PointerController::removeInactivityTimeoutLocked() {
- mLooper->removeMessages(mHandler, MSG_INACTIVITY_TIMEOUT);
-}
-
-void PointerController::updatePointerLocked() REQUIRES(mLock) {
- if (!mLocked.viewport.isValid()) {
- return;
- }
-
- mSpriteController->openTransaction();
-
- mLocked.pointerSprite->setLayer(Sprite::BASE_LAYER_POINTER);
- mLocked.pointerSprite->setPosition(mLocked.pointerX, mLocked.pointerY);
- mLocked.pointerSprite->setDisplayId(mLocked.viewport.displayId);
-
- if (mLocked.pointerAlpha > 0) {
- mLocked.pointerSprite->setAlpha(mLocked.pointerAlpha);
- mLocked.pointerSprite->setVisible(true);
- } else {
- mLocked.pointerSprite->setVisible(false);
- }
-
- if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
- if (mLocked.presentation == Presentation::POINTER) {
- if (mLocked.requestedPointerType == mPolicy->getDefaultPointerIconId()) {
- mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
- } else {
- std::map<int32_t, SpriteIcon>::const_iterator iter =
- mLocked.additionalMouseResources.find(mLocked.requestedPointerType);
- if (iter != mLocked.additionalMouseResources.end()) {
- std::map<int32_t, PointerAnimation>::const_iterator anim_iter =
- mLocked.animationResources.find(mLocked.requestedPointerType);
- if (anim_iter != mLocked.animationResources.end()) {
- mLocked.animationFrameIndex = 0;
- mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
- startAnimationLocked();
- }
- mLocked.pointerSprite->setIcon(iter->second);
- } else {
- ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerType);
- mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
- }
- }
- } else {
- mLocked.pointerSprite->setIcon(mResources.spotAnchor);
- }
- mLocked.pointerIconChanged = false;
- mLocked.presentationChanged = false;
- }
-
- mSpriteController->closeTransaction();
-}
-
-PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
- for (size_t i = 0; i < spots.size(); i++) {
- Spot* spot = spots[i];
- if (spot->id == id) {
- return spot;
- }
+void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
+ std::unordered_set<int32_t> displayIdSet;
+ for (DisplayViewport viewport : viewports) {
+ displayIdSet.insert(viewport.displayId);
}
- return nullptr;
-}
-
-PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
- std::vector<Spot*>& spots) {
- // Remove spots until we have fewer than MAX_SPOTS remaining.
- while (spots.size() >= MAX_SPOTS) {
- Spot* spot = removeFirstFadingSpotLocked(spots);
- if (!spot) {
- spot = spots[0];
- spots.erase(spots.begin());
- }
- releaseSpotLocked(spot);
- }
-
- // Obtain a sprite from the recycled pool.
- sp<Sprite> sprite;
- if (! mLocked.recycledSprites.empty()) {
- sprite = mLocked.recycledSprites.back();
- mLocked.recycledSprites.pop_back();
- } else {
- sprite = mSpriteController->createSprite();
- }
-
- // Return the new spot.
- Spot* spot = new Spot(id, sprite);
- spots.push_back(spot);
- return spot;
-}
-
-PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
- for (size_t i = 0; i < spots.size(); i++) {
- Spot* spot = spots[i];
- if (spot->id == Spot::INVALID_ID) {
- spots.erase(spots.begin() + i);
- return spot;
- }
- }
- return nullptr;
-}
-
-void PointerController::releaseSpotLocked(Spot* spot) {
- spot->sprite->clearIcon();
-
- if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
- mLocked.recycledSprites.push_back(spot->sprite);
- }
-
- delete spot;
-}
-
-void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
- if (spot->id != Spot::INVALID_ID) {
- spot->id = Spot::INVALID_ID;
- startAnimationLocked();
- }
-}
-
-void PointerController::fadeOutAndReleaseAllSpotsLocked() {
- for (auto& it : mLocked.spotsByDisplay) {
- const std::vector<Spot*>& spots = it.second;
- size_t numSpots = spots.size();
- for (size_t i = 0; i < numSpots; i++) {
- Spot* spot = spots[i];
- fadeOutAndReleaseSpotLocked(spot);
- }
- }
-}
-
-void PointerController::loadResourcesLocked() REQUIRES(mLock) {
- if (!mLocked.viewport.isValid()) {
- return;
- }
-
- mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId);
- mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId);
-
- mLocked.additionalMouseResources.clear();
- mLocked.animationResources.clear();
- if (mLocked.presentation == Presentation::POINTER) {
- mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources,
- &mLocked.animationResources, mLocked.viewport.displayId);
- }
-
- mLocked.pointerIconChanged = true;
-}
-
-
-// --- PointerController::Spot ---
-
-void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
- int32_t displayId) {
- sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
- sprite->setAlpha(alpha);
- sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
- sprite->setPosition(x, y);
- sprite->setDisplayId(displayId);
- this->x = x;
- this->y = y;
-
- if (icon != lastIcon) {
- lastIcon = icon;
- if (icon) {
- sprite->setIcon(*icon);
- sprite->setVisible(true);
+ std::scoped_lock lock(mLock);
+ for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
+ int32_t displayID = it->first;
+ if (!displayIdSet.count(displayID)) {
+ it = mLocked.spotControllers.erase(it);
} else {
- sprite->setVisible(false);
+ ++it;
}
}
}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 14c0679654c6..1f561da333b1 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -30,48 +30,14 @@
#include <memory>
#include <vector>
+#include "MouseCursorController.h"
+#include "PointerControllerContext.h"
#include "SpriteController.h"
+#include "TouchSpotController.h"
namespace android {
/*
- * Pointer resources.
- */
-struct PointerResources {
- SpriteIcon spotHover;
- SpriteIcon spotTouch;
- SpriteIcon spotAnchor;
-};
-
-struct PointerAnimation {
- std::vector<SpriteIcon> animationFrames;
- nsecs_t durationPerFrame;
-};
-
-/*
- * Pointer controller policy interface.
- *
- * The pointer controller policy is used by the pointer controller to interact with
- * the Window Manager and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI. This interface is also mocked in the unit tests.
- */
-class PointerControllerPolicyInterface : public virtual RefBase {
-protected:
- PointerControllerPolicyInterface() { }
- virtual ~PointerControllerPolicyInterface() { }
-
-public:
- virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0;
- virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0;
- virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
- std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0;
- virtual int32_t getDefaultPointerIconId() = 0;
- virtual int32_t getCustomPointerIconId() = 0;
-};
-
-/*
* Tracks pointer movements and draws the pointer sprite to a surface.
*
* Handles pointer acceleration and animation.
@@ -81,15 +47,10 @@ public:
static std::shared_ptr<PointerController> create(
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController);
- enum class InactivityTimeout {
- NORMAL = 0,
- SHORT = 1,
- };
- virtual ~PointerController();
+ virtual ~PointerController() = default;
- virtual bool getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const;
+ virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
virtual void move(float deltaX, float deltaY);
virtual void setButtonState(int32_t buttonState);
virtual int32_t getButtonState() const;
@@ -101,129 +62,37 @@ public:
virtual void setDisplayViewport(const DisplayViewport& viewport);
virtual void setPresentation(Presentation presentation);
- virtual void setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId);
+ virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+ BitSet32 spotIdBits, int32_t displayId);
virtual void clearSpots();
void updatePointerIcon(int32_t iconId);
void setCustomPointerIcon(const SpriteIcon& icon);
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
+ void doInactivityTimeout();
+ void doAnimate(nsecs_t timestamp);
void reloadPointerResources();
+ void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);
private:
- static constexpr size_t MAX_RECYCLED_SPRITES = 12;
- static constexpr size_t MAX_SPOTS = 12;
-
- enum {
- MSG_INACTIVITY_TIMEOUT,
- };
-
- struct Spot {
- static const uint32_t INVALID_ID = 0xffffffff;
-
- uint32_t id;
- sp<Sprite> sprite;
- float alpha;
- float scale;
- float x, y;
-
- inline Spot(uint32_t id, const sp<Sprite>& sprite)
- : id(id),
- sprite(sprite),
- alpha(1.0f),
- scale(1.0f),
- x(0.0f),
- y(0.0f),
- lastIcon(nullptr) {}
-
- void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId);
+ friend PointerControllerContext::LooperCallback;
+ friend PointerControllerContext::MessageHandler;
- private:
- const SpriteIcon* lastIcon;
- };
+ mutable std::mutex mLock;
- class MessageHandler : public virtual android::MessageHandler {
- public:
- void handleMessage(const Message& message) override;
- std::weak_ptr<PointerController> pointerController;
- };
+ PointerControllerContext mContext;
- class LooperCallback : public virtual android::LooperCallback {
- public:
- int handleEvent(int fd, int events, void* data) override;
- std::weak_ptr<PointerController> pointerController;
- };
-
- mutable Mutex mLock;
-
- sp<PointerControllerPolicyInterface> mPolicy;
- sp<Looper> mLooper;
- sp<SpriteController> mSpriteController;
- sp<MessageHandler> mHandler;
- sp<LooperCallback> mCallback;
-
- DisplayEventReceiver mDisplayEventReceiver;
-
- PointerResources mResources;
+ MouseCursorController mCursorController;
struct Locked {
- bool animationPending;
- nsecs_t animationTime;
-
- size_t animationFrameIndex;
- nsecs_t lastFrameUpdatedTime;
-
- DisplayViewport viewport;
-
- InactivityTimeout inactivityTimeout;
-
Presentation presentation;
- bool presentationChanged;
-
- int32_t pointerFadeDirection;
- float pointerX;
- float pointerY;
- float pointerAlpha;
- sp<Sprite> pointerSprite;
- SpriteIcon pointerIcon;
- bool pointerIconChanged;
-
- std::map<int32_t, SpriteIcon> additionalMouseResources;
- std::map<int32_t, PointerAnimation> animationResources;
- int32_t requestedPointerType;
-
- int32_t buttonState;
-
- std::map<int32_t /* displayId */, std::vector<Spot*>> spotsByDisplay;
- std::vector<sp<Sprite>> recycledSprites;
+ std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers;
} mLocked GUARDED_BY(mLock);
PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController);
-
- bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
- void setPositionLocked(float x, float y);
-
- void doAnimate(nsecs_t timestamp);
- bool doFadingAnimationLocked(nsecs_t timestamp);
- bool doBitmapAnimationLocked(nsecs_t timestamp);
- void doInactivityTimeout();
-
- void startAnimationLocked();
-
- void resetInactivityTimeoutLocked();
- void removeInactivityTimeoutLocked();
- void updatePointerLocked();
-
- Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots);
- Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots);
- Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots);
- void releaseSpotLocked(Spot* spot);
- void fadeOutAndReleaseSpotLocked(Spot* spot);
- void fadeOutAndReleaseAllSpotsLocked();
-
- void loadResourcesLocked();
+ void clearSpotsLocked();
};
} // namespace android
diff --git a/libs/input/PointerControllerContext.cpp b/libs/input/PointerControllerContext.cpp
new file mode 100644
index 000000000000..2d7e22b01112
--- /dev/null
+++ b/libs/input/PointerControllerContext.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#include "PointerControllerContext.h"
+#include "PointerController.h"
+
+namespace {
+// Time to wait before starting the fade when the pointer is inactive.
+const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
+const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
+
+// The number of events to be read at once for DisplayEventReceiver.
+const int EVENT_BUFFER_SIZE = 100;
+} // namespace
+
+namespace android {
+
+// --- PointerControllerContext ---
+
+PointerControllerContext::PointerControllerContext(
+ const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
+ const sp<SpriteController>& spriteController, PointerController& controller)
+ : mPolicy(policy),
+ mLooper(looper),
+ mSpriteController(spriteController),
+ mHandler(new MessageHandler()),
+ mCallback(new LooperCallback()),
+ mController(controller) {
+ std::scoped_lock lock(mLock);
+ mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
+ mLocked.animationPending = false;
+}
+
+PointerControllerContext::~PointerControllerContext() {
+ mLooper->removeMessages(mHandler);
+}
+
+void PointerControllerContext::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
+ std::scoped_lock lock(mLock);
+
+ if (mLocked.inactivityTimeout != inactivityTimeout) {
+ mLocked.inactivityTimeout = inactivityTimeout;
+ resetInactivityTimeoutLocked();
+ }
+}
+
+void PointerControllerContext::startAnimation() {
+ std::scoped_lock lock(mLock);
+ if (!mLocked.animationPending) {
+ mLocked.animationPending = true;
+ mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ mDisplayEventReceiver.requestNextVsync();
+ }
+}
+
+void PointerControllerContext::resetInactivityTimeout() {
+ std::scoped_lock lock(mLock);
+ resetInactivityTimeoutLocked();
+}
+
+void PointerControllerContext::resetInactivityTimeoutLocked() REQUIRES(mLock) {
+ mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
+
+ nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
+ ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
+ : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
+ mLooper->sendMessageDelayed(timeout, mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
+}
+
+void PointerControllerContext::removeInactivityTimeout() {
+ std::scoped_lock lock(mLock);
+ mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
+}
+
+void PointerControllerContext::setAnimationPending(bool animationPending) {
+ std::scoped_lock lock(mLock);
+ mLocked.animationPending = animationPending;
+}
+
+nsecs_t PointerControllerContext::getAnimationTime() {
+ std::scoped_lock lock(mLock);
+ return mLocked.animationTime;
+}
+
+void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
+ mHandler->pointerController = controller;
+}
+
+void PointerControllerContext::setCallbackController(
+ std::shared_ptr<PointerController> controller) {
+ mCallback->pointerController = controller;
+}
+
+sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() {
+ return mPolicy;
+}
+
+sp<SpriteController> PointerControllerContext::getSpriteController() {
+ return mSpriteController;
+}
+
+void PointerControllerContext::initializeDisplayEventReceiver() {
+ if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
+ mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, Looper::EVENT_INPUT,
+ mCallback, nullptr);
+ } else {
+ ALOGE("Failed to initialize DisplayEventReceiver.");
+ }
+}
+
+void PointerControllerContext::handleDisplayEvents() {
+ bool gotVsync = false;
+ ssize_t n;
+ nsecs_t timestamp;
+ DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+ while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+ for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
+ if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ timestamp = buf[i].header.timestamp;
+ gotVsync = true;
+ }
+ }
+ }
+ if (gotVsync) {
+ mController.doAnimate(timestamp);
+ }
+}
+
+void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
+ std::shared_ptr<PointerController> controller = pointerController.lock();
+
+ if (controller == nullptr) {
+ ALOGE("PointerController instance was released before processing message: what=%d",
+ message.what);
+ return;
+ }
+ switch (message.what) {
+ case MSG_INACTIVITY_TIMEOUT:
+ controller->doInactivityTimeout();
+ break;
+ }
+}
+
+int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int events,
+ void* /* data */) {
+ std::shared_ptr<PointerController> controller = pointerController.lock();
+ if (controller == nullptr) {
+ ALOGW("PointerController instance was released with pending callbacks. events=0x%x",
+ events);
+ return 0; // Remove the callback, the PointerController is gone anyways
+ }
+ if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+ ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events);
+ return 0; // remove the callback
+ }
+
+ if (!(events & Looper::EVENT_INPUT)) {
+ ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events);
+ return 1; // keep the callback
+ }
+
+ controller->mContext.handleDisplayEvents();
+ return 1; // keep the callback
+}
+
+} // namespace android
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
new file mode 100644
index 000000000000..92e1bda25f56
--- /dev/null
+++ b/libs/input/PointerControllerContext.h
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_POINTER_CONTROLLER_CONTEXT_H
+#define _UI_POINTER_CONTROLLER_CONTEXT_H
+
+#include <PointerControllerInterface.h>
+#include <gui/DisplayEventReceiver.h>
+#include <input/DisplayViewport.h>
+#include <input/Input.h>
+#include <ui/DisplayInfo.h>
+#include <utils/BitSet.h>
+#include <utils/Looper.h>
+#include <utils/RefBase.h>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "SpriteController.h"
+
+namespace android {
+
+class PointerController;
+
+/*
+ * Pointer resources.
+ */
+struct PointerResources {
+ SpriteIcon spotHover;
+ SpriteIcon spotTouch;
+ SpriteIcon spotAnchor;
+};
+
+struct PointerAnimation {
+ std::vector<SpriteIcon> animationFrames;
+ nsecs_t durationPerFrame;
+};
+
+enum class InactivityTimeout {
+ NORMAL = 0,
+ SHORT = 1,
+};
+
+/*
+ * Pointer controller policy interface.
+ *
+ * The pointer controller policy is used by the pointer controller to interact with
+ * the Window Manager and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This interface is also mocked in the unit tests.
+ */
+class PointerControllerPolicyInterface : public virtual RefBase {
+protected:
+ PointerControllerPolicyInterface() {}
+ virtual ~PointerControllerPolicyInterface() {}
+
+public:
+ virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0;
+ virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0;
+ virtual void loadAdditionalMouseResources(
+ std::map<int32_t, SpriteIcon>* outResources,
+ std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0;
+ virtual int32_t getDefaultPointerIconId() = 0;
+ virtual int32_t getCustomPointerIconId() = 0;
+};
+
+/*
+ * Contains logic and resources shared among PointerController,
+ * MouseCursorController, and TouchSpotController.
+ */
+
+class PointerControllerContext {
+public:
+ PointerControllerContext(const sp<PointerControllerPolicyInterface>& policy,
+ const sp<Looper>& looper, const sp<SpriteController>& spriteController,
+ PointerController& controller);
+ ~PointerControllerContext();
+
+ void removeInactivityTimeout();
+ void resetInactivityTimeout();
+ void startAnimation();
+ void setInactivityTimeout(InactivityTimeout inactivityTimeout);
+
+ void setAnimationPending(bool animationPending);
+ nsecs_t getAnimationTime();
+
+ void clearSpotsByDisplay(int32_t displayId);
+
+ void setHandlerController(std::shared_ptr<PointerController> controller);
+ void setCallbackController(std::shared_ptr<PointerController> controller);
+
+ sp<PointerControllerPolicyInterface> getPolicy();
+ sp<SpriteController> getSpriteController();
+
+ void initializeDisplayEventReceiver();
+ void handleDisplayEvents();
+
+ class MessageHandler : public virtual android::MessageHandler {
+ public:
+ enum {
+ MSG_INACTIVITY_TIMEOUT,
+ };
+
+ void handleMessage(const Message& message) override;
+ std::weak_ptr<PointerController> pointerController;
+ };
+
+ class LooperCallback : public virtual android::LooperCallback {
+ public:
+ int handleEvent(int fd, int events, void* data) override;
+ std::weak_ptr<PointerController> pointerController;
+ };
+
+private:
+ sp<PointerControllerPolicyInterface> mPolicy;
+ sp<Looper> mLooper;
+ sp<SpriteController> mSpriteController;
+ sp<MessageHandler> mHandler;
+ sp<LooperCallback> mCallback;
+
+ DisplayEventReceiver mDisplayEventReceiver;
+
+ PointerController& mController;
+
+ mutable std::mutex mLock;
+
+ struct Locked {
+ bool animationPending;
+ nsecs_t animationTime;
+
+ InactivityTimeout inactivityTimeout;
+ } mLocked GUARDED_BY(mLock);
+
+ void resetInactivityTimeoutLocked();
+};
+
+} // namespace android
+
+#endif // _UI_POINTER_CONTROLLER_CONTEXT_H
diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp
new file mode 100644
index 000000000000..c7430ceead41
--- /dev/null
+++ b/libs/input/TouchSpotController.cpp
@@ -0,0 +1,236 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "TouchSpotController"
+
+// Log debug messages about pointer updates
+#define DEBUG_SPOT_UPDATES 0
+
+#include "TouchSpotController.h"
+
+#include <log/log.h>
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
+
+namespace {
+// Time to spend fading out the spot completely.
+const nsecs_t SPOT_FADE_DURATION = 200 * 1000000LL; // 200 ms
+} // namespace
+
+namespace android {
+
+// --- Spot ---
+
+void TouchSpotController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
+ int32_t displayId) {
+ sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
+ sprite->setAlpha(alpha);
+ sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
+ sprite->setPosition(x, y);
+ sprite->setDisplayId(displayId);
+ this->x = x;
+ this->y = y;
+
+ if (icon != mLastIcon) {
+ mLastIcon = icon;
+ if (icon) {
+ sprite->setIcon(*icon);
+ sprite->setVisible(true);
+ } else {
+ sprite->setVisible(false);
+ }
+ }
+}
+
+// --- TouchSpotController ---
+
+TouchSpotController::TouchSpotController(int32_t displayId, PointerControllerContext& context)
+ : mDisplayId(displayId), mContext(context) {
+ mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId);
+}
+
+TouchSpotController::~TouchSpotController() {
+ std::scoped_lock lock(mLock);
+
+ size_t numSpots = mLocked.displaySpots.size();
+ for (size_t i = 0; i < numSpots; i++) {
+ delete mLocked.displaySpots[i];
+ }
+ mLocked.displaySpots.clear();
+}
+
+void TouchSpotController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+ BitSet32 spotIdBits) {
+#if DEBUG_SPOT_UPDATES
+ ALOGD("setSpots: idBits=%08x", spotIdBits.value);
+ for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
+ const PointerCoords& c = spotCoords[spotIdToIndex[id]];
+ ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
+ c.getAxisValue(AMOTION_EVENT_AXIS_X), c.getAxisValue(AMOTION_EVENT_AXIS_Y),
+ c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), displayId);
+ }
+#endif
+
+ std::scoped_lock lock(mLock);
+ sp<SpriteController> spriteController = mContext.getSpriteController();
+ spriteController->openTransaction();
+
+ // Add or move spots for fingers that are down.
+ for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const PointerCoords& c = spotCoords[spotIdToIndex[id]];
+ const SpriteIcon& icon = c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE) > 0
+ ? mResources.spotTouch
+ : mResources.spotHover;
+ float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
+ float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
+
+ Spot* spot = getSpot(id, mLocked.displaySpots);
+ if (!spot) {
+ spot = createAndAddSpotLocked(id, mLocked.displaySpots);
+ }
+
+ spot->updateSprite(&icon, x, y, mDisplayId);
+ }
+
+ for (Spot* spot : mLocked.displaySpots) {
+ if (spot->id != Spot::INVALID_ID && !spotIdBits.hasBit(spot->id)) {
+ fadeOutAndReleaseSpotLocked(spot);
+ }
+ }
+
+ spriteController->closeTransaction();
+}
+
+void TouchSpotController::clearSpots() {
+#if DEBUG_SPOT_UPDATES
+ ALOGD("clearSpots");
+#endif
+
+ std::scoped_lock lock(mLock);
+ fadeOutAndReleaseAllSpotsLocked();
+}
+
+TouchSpotController::Spot* TouchSpotController::getSpot(uint32_t id,
+ const std::vector<Spot*>& spots) {
+ for (size_t i = 0; i < spots.size(); i++) {
+ Spot* spot = spots[i];
+ if (spot->id == id) {
+ return spot;
+ }
+ }
+ return nullptr;
+}
+
+TouchSpotController::Spot* TouchSpotController::createAndAddSpotLocked(uint32_t id,
+ std::vector<Spot*>& spots) {
+ // Remove spots until we have fewer than MAX_SPOTS remaining.
+ while (spots.size() >= MAX_SPOTS) {
+ Spot* spot = removeFirstFadingSpotLocked(spots);
+ if (!spot) {
+ spot = spots[0];
+ spots.erase(spots.begin());
+ }
+ releaseSpotLocked(spot);
+ }
+
+ // Obtain a sprite from the recycled pool.
+ sp<Sprite> sprite;
+ if (!mLocked.recycledSprites.empty()) {
+ sprite = mLocked.recycledSprites.back();
+ mLocked.recycledSprites.pop_back();
+ } else {
+ sprite = mContext.getSpriteController()->createSprite();
+ }
+
+ // Return the new spot.
+ Spot* spot = new Spot(id, sprite);
+ spots.push_back(spot);
+ return spot;
+}
+
+TouchSpotController::Spot* TouchSpotController::removeFirstFadingSpotLocked(
+ std::vector<Spot*>& spots) REQUIRES(mLock) {
+ for (size_t i = 0; i < spots.size(); i++) {
+ Spot* spot = spots[i];
+ if (spot->id == Spot::INVALID_ID) {
+ spots.erase(spots.begin() + i);
+ return spot;
+ }
+ }
+ return NULL;
+}
+
+void TouchSpotController::releaseSpotLocked(Spot* spot) REQUIRES(mLock) {
+ spot->sprite->clearIcon();
+
+ if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
+ mLocked.recycledSprites.push_back(spot->sprite);
+ }
+
+ delete spot;
+}
+
+void TouchSpotController::fadeOutAndReleaseSpotLocked(Spot* spot) REQUIRES(mLock) {
+ if (spot->id != Spot::INVALID_ID) {
+ spot->id = Spot::INVALID_ID;
+ mContext.startAnimation();
+ }
+}
+
+void TouchSpotController::fadeOutAndReleaseAllSpotsLocked() REQUIRES(mLock) {
+ size_t numSpots = mLocked.displaySpots.size();
+ for (size_t i = 0; i < numSpots; i++) {
+ Spot* spot = mLocked.displaySpots[i];
+ fadeOutAndReleaseSpotLocked(spot);
+ }
+}
+
+void TouchSpotController::reloadSpotResources() {
+ mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId);
+}
+
+bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) {
+ std::scoped_lock lock(mLock);
+ nsecs_t animationTime = mContext.getAnimationTime();
+ nsecs_t frameDelay = timestamp - animationTime;
+ size_t numSpots = mLocked.displaySpots.size();
+ for (size_t i = 0; i < numSpots;) {
+ Spot* spot = mLocked.displaySpots[i];
+ if (spot->id == Spot::INVALID_ID) {
+ spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
+ if (spot->alpha <= 0) {
+ mLocked.displaySpots.erase(mLocked.displaySpots.begin() + i);
+ releaseSpotLocked(spot);
+ numSpots--;
+ continue;
+ } else {
+ spot->sprite->setAlpha(spot->alpha);
+ keepAnimating = true;
+ }
+ }
+ ++i;
+ }
+ return keepAnimating;
+}
+
+} // namespace android
diff --git a/libs/input/TouchSpotController.h b/libs/input/TouchSpotController.h
new file mode 100644
index 000000000000..f3b355010bee
--- /dev/null
+++ b/libs/input/TouchSpotController.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_TOUCH_SPOT_CONTROLLER_H
+#define _UI_TOUCH_SPOT_CONTROLLER_H
+
+#include "PointerControllerContext.h"
+
+namespace android {
+
+/*
+ * Helper class for PointerController that specifically handles
+ * touch spot resources and actions for a single display.
+ */
+class TouchSpotController {
+public:
+ TouchSpotController(int32_t displayId, PointerControllerContext& context);
+ ~TouchSpotController();
+ void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+ BitSet32 spotIdBits);
+ void clearSpots();
+
+ void reloadSpotResources();
+ bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating);
+
+private:
+ struct Spot {
+ static const uint32_t INVALID_ID = 0xffffffff;
+
+ uint32_t id;
+ sp<Sprite> sprite;
+ float alpha;
+ float scale;
+ float x, y;
+
+ inline Spot(uint32_t id, const sp<Sprite>& sprite)
+ : id(id),
+ sprite(sprite),
+ alpha(1.0f),
+ scale(1.0f),
+ x(0.0f),
+ y(0.0f),
+ mLastIcon(nullptr) {}
+
+ void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId);
+
+ private:
+ const SpriteIcon* mLastIcon;
+ };
+
+ int32_t mDisplayId;
+
+ mutable std::mutex mLock;
+
+ PointerResources mResources;
+
+ PointerControllerContext& mContext;
+
+ static constexpr size_t MAX_RECYCLED_SPRITES = 12;
+ static constexpr size_t MAX_SPOTS = 12;
+
+ struct Locked {
+ std::vector<Spot*> displaySpots;
+ std::vector<sp<Sprite>> recycledSprites;
+
+ } mLocked GUARDED_BY(mLock);
+
+ Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots);
+ Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots);
+ Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots);
+ void releaseSpotLocked(Spot* spot);
+ void fadeOutAndReleaseSpotLocked(Spot* spot);
+ void fadeOutAndReleaseAllSpotsLocked();
+};
+
+} // namespace android
+
+#endif // _UI_TOUCH_SPOT_CONTROLLER_H
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index 6e129a064385..b67088a389b6 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -178,9 +178,6 @@ void PointerControllerTest::ensureDisplayViewportIsSet() {
viewport.deviceWidth = 400;
viewport.deviceHeight = 300;
mPointerController->setDisplayViewport(viewport);
-
- // The first call to setDisplayViewport should trigger the loading of the necessary resources.
- EXPECT_TRUE(mPolicy->allResourcesAreLoaded());
}
void PointerControllerTest::loopThread() {
@@ -208,6 +205,7 @@ TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) {
TEST_F(PointerControllerTest, updatePointerIcon) {
ensureDisplayViewportIsSet();
+ mPointerController->setPresentation(PointerController::Presentation::POINTER);
mPointerController->unfade(PointerController::Transition::IMMEDIATE);
int32_t type = CURSOR_TYPE_ADDITIONAL;
@@ -247,8 +245,6 @@ TEST_F(PointerControllerTest, setCustomPointerIcon) {
TEST_F(PointerControllerTest, doesNotGetResourcesBeforeSettingViewport) {
mPointerController->setPresentation(PointerController::Presentation::POINTER);
- mPointerController->setSpots(nullptr, nullptr, BitSet32(), -1);
- mPointerController->clearSpots();
mPointerController->setPosition(1.0f, 1.0f);
mPointerController->move(1.0f, 1.0f);
mPointerController->unfade(PointerController::Transition::IMMEDIATE);
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 6e3fb1991acc..d4fb1be56890 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -147,6 +147,19 @@ public final class AudioDeviceInfo {
// {@link android.media.audiopolicy.AudioMix#ROUTE_FLAG_LOOP_BACK} flag.
public static final int TYPE_REMOTE_SUBMIX = 25;
+ /**
+ * A device type describing a Bluetooth Low Energy (BLE) audio headset or headphones.
+ * Headphones are grouped with headsets when the device is a sink:
+ * the features of headsets and headphones with regard to playback are the same.
+ */
+ public static final int TYPE_BLE_HEADSET = 26;
+
+ /**
+ * A device type describing a Bluetooth Low Energy (BLE) audio speaker.
+ */
+ public static final int TYPE_BLE_SPEAKER = 27;
+
+
/** @hide */
@IntDef(flag = false, prefix = "TYPE", value = {
TYPE_BUILTIN_EARPIECE,
@@ -171,7 +184,9 @@ public final class AudioDeviceInfo {
TYPE_HEARING_AID,
TYPE_BUILTIN_MIC,
TYPE_FM_TUNER,
- TYPE_TV_TUNER }
+ TYPE_TV_TUNER,
+ TYPE_BLE_HEADSET,
+ TYPE_BLE_SPEAKER}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceType {}
@@ -193,7 +208,8 @@ public final class AudioDeviceInfo {
TYPE_LINE_ANALOG,
TYPE_LINE_DIGITAL,
TYPE_IP,
- TYPE_BUS }
+ TYPE_BUS,
+ TYPE_BLE_HEADSET}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeIn {}
@@ -219,7 +235,9 @@ public final class AudioDeviceInfo {
TYPE_AUX_LINE,
TYPE_IP,
TYPE_BUS,
- TYPE_HEARING_AID }
+ TYPE_HEARING_AID,
+ TYPE_BLE_HEADSET,
+ TYPE_BLE_SPEAKER}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeOut {}
@@ -248,7 +266,8 @@ public final class AudioDeviceInfo {
case TYPE_BUS:
case TYPE_HEARING_AID:
case TYPE_BUILTIN_SPEAKER_SAFE:
- case TYPE_REMOTE_SUBMIX:
+ case TYPE_BLE_HEADSET:
+ case TYPE_BLE_SPEAKER:
return true;
default:
return false;
@@ -275,6 +294,7 @@ public final class AudioDeviceInfo {
case TYPE_IP:
case TYPE_BUS:
case TYPE_REMOTE_SUBMIX:
+ case TYPE_BLE_HEADSET:
return true;
default:
return false;
@@ -527,6 +547,8 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER_SAFE,
TYPE_BUILTIN_SPEAKER_SAFE);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -547,6 +569,7 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET);
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
@@ -576,6 +599,8 @@ public final class AudioDeviceInfo {
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER_SAFE,
AudioSystem.DEVICE_OUT_SPEAKER_SAFE);
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);
}
}
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 42d0f0cc13c5..f6b04540c5c7 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -70,7 +70,9 @@ public class AudioDevicePort extends AudioPort {
* {@link AudioManager#DEVICE_IN_USB_DEVICE}) use an address composed of the ALSA card number
* and device number: "card=2;device=1"
* - Bluetooth devices ({@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
- * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO}, {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP})
+ * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
+ * {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP}),
+ * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER})
* use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by
* {@link BluetoothDevice#getAddress()}.
* - Deivces that do not have an address will indicate an empty string "".
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 408f34be6b65..b2e0538fd4b8 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4413,6 +4413,18 @@ public class AudioManager {
*/
public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
/** @hide
+ * The audio output device code for echo reference injection point.
+ */
+ public static final int DEVICE_OUT_ECHO_CANCELLER = AudioSystem.DEVICE_OUT_ECHO_CANCELLER;
+ /** @hide
+ * The audio output device code for a BLE audio headset.
+ */
+ public static final int DEVICE_OUT_BLE_HEADSET = AudioSystem.DEVICE_OUT_BLE_HEADSET;
+ /** @hide
+ * The audio output device code for a BLE audio speaker.
+ */
+ public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER;
+ /** @hide
* This is not used as a returned value from {@link #getDevicesForStream}, but could be
* used in the future in a set method to select whatever default device is chosen by the
* platform-specific implementation.
@@ -4496,6 +4508,14 @@ public class AudioManager {
* The audio input device code for audio loopback
*/
public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK;
+ /** @hide
+ * The audio input device code for an echo reference capture point.
+ */
+ public static final int DEVICE_IN_ECHO_REFERENCE = AudioSystem.DEVICE_IN_ECHO_REFERENCE;
+ /** @hide
+ * The audio input device code for a BLE audio headset.
+ */
+ public static final int DEVICE_IN_BLE_HEADSET = AudioSystem.DEVICE_IN_BLE_HEADSET;
/**
* Return true if the device code corresponds to an output device.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index da52cfef6bc6..5fe5c0580b0c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -866,6 +866,12 @@ public class AudioSystem
public static final int DEVICE_OUT_USB_HEADSET = 0x4000000;
/** @hide */
public static final int DEVICE_OUT_HEARING_AID = 0x8000000;
+ /** @hide */
+ public static final int DEVICE_OUT_ECHO_CANCELLER = 0x10000000;
+ /** @hide */
+ public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000;
+ /** @hide */
+ public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001;
/** @hide */
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -890,6 +896,8 @@ public class AudioSystem
public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
/** @hide */
public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
+ /** @hide */
+ public static final Set<Integer> DEVICE_OUT_ALL_BLE_SET;
static {
DEVICE_OUT_ALL_SET = new HashSet<>();
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE);
@@ -920,6 +928,9 @@ public class AudioSystem
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
@@ -945,6 +956,10 @@ public class AudioSystem
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>();
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET);
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER);
+
+ DEVICE_OUT_ALL_BLE_SET = new HashSet<>();
+ DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET);
+ DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER);
}
// input devices
@@ -1019,6 +1034,8 @@ public class AudioSystem
/** @hide */
public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000;
/** @hide */
+ public static final int DEVICE_IN_BLE_HEADSET = DEVICE_BIT_IN | 0x20000000;
+ /** @hide */
@UnsupportedAppUsage
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
@@ -1056,6 +1073,7 @@ public class AudioSystem
DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE);
DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC);
DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BLE_HEADSET);
DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT);
DEVICE_IN_ALL_SCO_SET = new HashSet<>();
@@ -1118,6 +1136,9 @@ public class AudioSystem
/** @hide */ public static final String DEVICE_OUT_PROXY_NAME = "proxy";
/** @hide */ public static final String DEVICE_OUT_USB_HEADSET_NAME = "usb_headset";
/** @hide */ public static final String DEVICE_OUT_HEARING_AID_NAME = "hearing_aid_out";
+ /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller";
+ /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset";
+ /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker";
/** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
/** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -1145,6 +1166,7 @@ public class AudioSystem
/** @hide */ public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble";
/** @hide */ public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference";
/** @hide */ public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc";
+ /** @hide */ public static final String DEVICE_IN_BLE_HEADSET_NAME = "ble_headset";
/** @hide */
@UnsupportedAppUsage
@@ -1207,6 +1229,12 @@ public class AudioSystem
return DEVICE_OUT_USB_HEADSET_NAME;
case DEVICE_OUT_HEARING_AID:
return DEVICE_OUT_HEARING_AID_NAME;
+ case DEVICE_OUT_ECHO_CANCELLER:
+ return DEVICE_OUT_ECHO_CANCELLER_NAME;
+ case DEVICE_OUT_BLE_HEADSET:
+ return DEVICE_OUT_BLE_HEADSET_NAME;
+ case DEVICE_OUT_BLE_SPEAKER:
+ return DEVICE_OUT_BLE_SPEAKER_NAME;
case DEVICE_OUT_DEFAULT:
default:
return Integer.toString(device);
@@ -1269,6 +1297,8 @@ public class AudioSystem
return DEVICE_IN_ECHO_REFERENCE_NAME;
case DEVICE_IN_HDMI_ARC:
return DEVICE_IN_HDMI_ARC_NAME;
+ case DEVICE_IN_BLE_HEADSET:
+ return DEVICE_IN_BLE_HEADSET_NAME;
case DEVICE_IN_DEFAULT:
default:
return Integer.toString(device);
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index e959e8e36b42..5d4404036102 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -225,13 +225,35 @@ public final class MediaTranscodeManager {
job.updateStatusAndResult(TranscodingJob.STATUS_FINISHED,
TranscodingJob.RESULT_ERROR);
- // Notifies client the job is done.
+ // Notifies client the job failed.
if (job.mListener != null && job.mListenerExecutor != null) {
job.mListenerExecutor.execute(() -> job.mListener.onTranscodingFinished(job));
}
}
}
+ private void handleTranscodingProgressUpdate(int jobId, int newProgress) {
+ synchronized (mPendingTranscodingJobs) {
+ // Gets the job associated with the jobId.
+ final TranscodingJob job = mPendingTranscodingJobs.get(jobId);
+
+ if (job == null) {
+ // This should not happen in reality.
+ Log.e(TAG, "Job " + jobId + " is not in PendingJobs");
+ return;
+ }
+
+ // Updates the job progress.
+ job.setJobProgress(newProgress);
+
+ // Notifies client the progress update.
+ if (job.mProgressUpdateExecutor != null && job.mProgressUpdateListener != null) {
+ job.mProgressUpdateExecutor.execute(
+ () -> job.mProgressUpdateListener.onProgressUpdate(newProgress));
+ }
+ }
+ }
+
// Just forwards all the events to the event handler.
private ITranscodingClientCallback mTranscodingClientCallback =
new ITranscodingClientCallback.Stub() {
@@ -294,8 +316,8 @@ public final class MediaTranscodeManager {
}
@Override
- public void onProgressUpdate(int jobId, int progress) throws RemoteException {
- //TODO(hkuang): Implement this.
+ public void onProgressUpdate(int jobId, int newProgress) throws RemoteException {
+ handleTranscodingProgressUpdate(jobId, newProgress);
}
};
@@ -821,17 +843,8 @@ public final class MediaTranscodeManager {
return mResult;
}
- private void setJobProgress(int newProgress) {
- synchronized (this) {
- mProgress = newProgress;
- }
-
- // Notify listener.
- OnProgressUpdateListener onProgressUpdateListener = mProgressUpdateListener;
- if (mProgressUpdateListener != null) {
- mProgressUpdateExecutor.execute(
- () -> onProgressUpdateListener.onProgressUpdate(mProgress));
- }
+ private synchronized void setJobProgress(int newProgress) {
+ mProgress = newProgress;
}
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 561a8847feed..697d80c6b78e 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -220,6 +220,34 @@ public class AudioPolicyConfig implements Parcelable {
return textDump;
}
+ /**
+ * Very short dump of configuration
+ * @return a condensed dump of configuration, uniquely identifies a policy in a log
+ */
+ public String toCompactLogString() {
+ String compactDump = "reg:" + mRegistrationId;
+ int mixNum = 0;
+ for (AudioMix mix : mMixes) {
+ compactDump += " Mix:" + mixNum + "-Typ:" + mixTypePrefix(mix.getMixType())
+ + "-Rul:" + mix.getRule().getCriteria().size();
+ mixNum++;
+ }
+ return compactDump;
+ }
+
+ private static String mixTypePrefix(int mixType) {
+ switch (mixType) {
+ case AudioMix.MIX_TYPE_PLAYERS:
+ return "p";
+ case AudioMix.MIX_TYPE_RECORDERS:
+ return "r";
+ case AudioMix.MIX_TYPE_INVALID:
+ default:
+ return "#";
+
+ }
+ }
+
protected void reset() {
mMixCounter = 0;
}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
index 3a5e69293a02..8e4153078174 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
@@ -37,6 +37,7 @@ 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;
/*
* Functional tests for MediaTranscodeManager in the media framework.
@@ -230,5 +231,63 @@ public class MediaTranscodeManagerTest
30, TimeUnit.MILLISECONDS);
assertTrue("Fails to cancel transcoding", finishedOnTime);
}
+
+
+ @Test
+ public void testTranscodingProgressUpdate() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+
+ // 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() + "/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_SUCCESS);
+ 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() {
+ int mPreviousProgress = 0;
+
+ @Override
+ public void onProgressUpdate(int newProgress) {
+ assertTrue("Invalid proress update", newProgress > mPreviousProgress);
+ assertTrue("Invalid proress update", newProgress <= 100);
+ mPreviousProgress = newProgress;
+ progressUpdateCount.getAndIncrement();
+ Log.i(TAG, "Get progress update " + newProgress);
+ }
+ });
+
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Transcode failed to complete in time.", finishedOnTime);
+ assertTrue("Failed to receive at least 10 progress updates",
+ progressUpdateCount.get() > 10);
+ }
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 70ef69d8ce72..e06cf945ddaa 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -24047,6 +24047,8 @@ package android.media {
method public boolean isSink();
method public boolean isSource();
field public static final int TYPE_AUX_LINE = 19; // 0x13
+ field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+ field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 86ac3e477dc4..35b483b9fb84 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -54,6 +54,7 @@ package android.os {
}
public interface Parcelable {
+ method public default int getStability();
field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 10887fabb5c7..0906a060c40f 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -9357,7 +9357,7 @@ package android.telecom {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
method @Deprecated public android.content.ComponentName getDefaultPhoneApp();
- method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
+ method @Deprecated public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
diff --git a/packages/CarSystemUI/samples/sample1/rro/Android.bp b/packages/CarSystemUI/samples/sample1/rro/Android.bp
new file mode 100644
index 000000000000..5b0347ff73fd
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+ name: "CarSystemUISampleOneRRO",
+ resource_dirs: ["res"],
+ certificate: "platform",
+ platform_apis: true,
+ manifest: "AndroidManifest.xml",
+ aaptflags: [
+ "--no-resource-deduping",
+ "--no-resource-removal",
+ ]
+} \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml
new file mode 100644
index 000000000000..5c25056f7915
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.rro">
+ <overlay
+ android:targetPackage="com.android.systemui"
+ android:isStatic="false"
+ android:resourcesMap="@xml/car_sysui_overlays"
+ />
+</manifest> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml
new file mode 100644
index 000000000000..854ab7d7e49b
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml
@@ -0,0 +1,47 @@
+<?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>
+ <!-- Configure which system bars should be displayed. -->
+ <bool name="config_enableTopNavigationBar">true</bool>
+ <bool name="config_enableLeftNavigationBar">true</bool>
+ <bool name="config_enableRightNavigationBar">true</bool>
+ <bool name="config_enableBottomNavigationBar">true</bool>
+
+ <!-- Configure the type of each system bar. Each system bar must have a unique type. -->
+ <!-- STATUS_BAR = 0-->
+ <!-- NAVIGATION_BAR = 1-->
+ <!-- STATUS_BAR_EXTRA = 2-->
+ <!-- NAVIGATION_BAR_EXTRA = 3-->
+ <integer name="config_topSystemBarType">0</integer>
+ <integer name="config_leftSystemBarType">2</integer>
+ <integer name="config_rightSystemBarType">3</integer>
+ <integer name="config_bottomSystemBarType">1</integer>
+
+ <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g.
+ if both top bar and left bar are enabled, it creates an overlapping space in the upper left
+ corner), the system bar with the higher z-order takes the overlapping space and padding is
+ applied to the other bar.-->
+ <!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a
+ RuntimeException, since their placing order cannot be determined. Bars that do not overlap
+ are allowed to have the same z-order. -->
+ <!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's. -->
+ <integer name="config_topSystemBarZOrder">1</integer>
+ <integer name="config_leftSystemBarZOrder">0</integer>
+ <integer name="config_rightSystemBarZOrder">0</integer>
+ <integer name="config_bottomSystemBarZOrder">10</integer>
+</resources> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml
new file mode 100644
index 000000000000..7bcb8e1b43dd
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml
@@ -0,0 +1,33 @@
+
+<!--
+ ~ 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.
+ -->
+
+<overlay>
+ <item target="bool/config_enableTopNavigationBar" value="@bool/config_enableTopNavigationBar"/>
+ <item target="bool/config_enableLeftNavigationBar" value="@bool/config_enableLeftNavigationBar"/>
+ <item target="bool/config_enableRightNavigationBar" value="@bool/config_enableRightNavigationBar"/>
+ <item target="bool/config_enableBottomNavigationBar" value="@bool/config_enableBottomNavigationBar"/>
+
+ <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/>
+ <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/>
+ <item target="integer/config_rightSystemBarType" value="@integer/config_rightSystemBarType"/>
+ <item target="integer/config_bottomSystemBarType" value="@integer/config_bottomSystemBarType"/>
+
+ <item target="integer/config_topSystemBarZOrder" value="@integer/config_topSystemBarZOrder"/>
+ <item target="integer/config_leftSystemBarZOrder" value="@integer/config_leftSystemBarZOrder"/>
+ <item target="integer/config_rightSystemBarZOrder" value="@integer/config_rightSystemBarZOrder"/>
+ <item target="integer/config_bottomSystemBarZOrder" value="@integer/config_bottomSystemBarZOrder"/>
+</overlay> \ No newline at end of file
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index 8efbad64f3d2..2c4545e7b265 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -155,41 +155,6 @@ public class FusedLocationServiceTest {
assertThat(mManager.getNextLocation(TIMEOUT_MS)).isEqualTo(location);
}
- @Test
- public void testBypassRequest() throws Exception {
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(FUSED_PROVIDER, 1000,
- 0, false).setQuality(LocationRequest.POWER_HIGH).setLocationSettingsIgnored(true);
-
- mProvider.setRequest(
- new ProviderRequest.Builder()
- .setInterval(1000)
- .setLocationSettingsIgnored(true)
- .setLocationRequests(Collections.singletonList(request))
- .build(),
- new WorkSource());
-
- boolean containsNetworkBypass = false;
- for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests(
- NETWORK_PROVIDER)) {
- if (iRequest.isLocationSettingsIgnored()) {
- containsNetworkBypass = true;
- break;
- }
- }
-
- boolean containsGpsBypass = false;
- for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests(
- GPS_PROVIDER)) {
- if (iRequest.isLocationSettingsIgnored()) {
- containsGpsBypass = true;
- break;
- }
- }
-
- assertThat(containsNetworkBypass).isTrue();
- assertThat(containsGpsBypass).isTrue();
- }
-
private static class LocationProviderManagerCapture extends ILocationProviderManager.Stub {
private final LinkedBlockingQueue<Location> mLocations;
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
index 1e4c7cac4404..52d2b3c919d9 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -376,8 +376,12 @@ public abstract class Tile implements Parcelable {
* Check whether tile only has primary profile.
*/
public boolean isPrimaryProfileOnly() {
- String profile = mMetaData != null
- ? mMetaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+ return isPrimaryProfileOnly(mMetaData);
+ }
+
+ static boolean isPrimaryProfileOnly(Bundle metaData) {
+ String profile = metaData != null
+ ? metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
profile = (profile != null ? profile : PROFILE_ALL);
return TextUtils.equals(profile, PROFILE_PRIMARY);
}
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index ace50f30663d..49f6bd8c3334 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -339,6 +339,16 @@ public class TileUtils {
private static void loadTile(UserHandle user, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, List<Tile> outTiles, Intent intent, Bundle metaData,
ComponentInfo componentInfo) {
+ // Skip loading tile if the component is tagged primary_profile_only but not running on
+ // the current user.
+ if (user.getIdentifier() != ActivityManager.getCurrentUser()
+ && Tile.isPrimaryProfileOnly(componentInfo.metaData)) {
+ Log.w(LOG_TAG, "Found " + componentInfo.name + " for intent "
+ + intent + " is primary profile only, skip loading tile for uid "
+ + user.getIdentifier());
+ return;
+ }
+
String categoryKey = defaultCategory;
// Load category
if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ddf2bc0991a4..5f5be97c322c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -165,7 +165,7 @@
<string name="tts_lang_not_selected" msgid="7927823081096056147">"Langue non sélectionnée"</string>
<string name="tts_default_lang_summary" msgid="9042620014800063470">"Définir la langue utilisée par la synthèse vocale"</string>
<string name="tts_play_example_title" msgid="1599468547216481684">"Écouter un échantillon"</string>
- <string name="tts_play_example_summary" msgid="634044730710636383">"Lire une courte démonstration de la synthèse vocale"</string>
+ <string name="tts_play_example_summary" msgid="634044730710636383">"Écoutez une courte démonstration de la synthèse vocale"</string>
<string name="tts_install_data_title" msgid="1829942496472751703">"Installer les données vocales"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"Installer les données nécessaires à la synthèse vocale"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"Ce moteur de synthèse vocale est susceptible de collecter tout ce qui sera lu, y compris les données personnelles comme les mots de passe et les numéros de carte de paiement. Il provient du moteur <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Voulez-vous activer son utilisation ?"</string>
@@ -189,8 +189,8 @@
<item msgid="1158955023692670059">"Rapide"</item>
<item msgid="5664310435707146591">"Plus rapide"</item>
<item msgid="5491266922147715962">"Très rapide"</item>
- <item msgid="7659240015901486196">"Rapide"</item>
- <item msgid="7147051179282410945">"Très rapide"</item>
+ <item msgid="7659240015901486196">"Beaucoup plus rapide"</item>
+ <item msgid="7147051179282410945">"Extrêmement rapide"</item>
<item msgid="581904787661470707">"La plus rapide"</item>
</string-array>
<string name="choose_profile" msgid="343803890897657450">"Sélectionner un profil"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index 2fb2481ac117..df98b1717b9b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -108,8 +108,8 @@ public class TestAccessPointBuilder {
public TestAccessPointBuilder setActive(boolean active) {
if (active) {
mNetworkInfo = new NetworkInfo(
- ConnectivityManager.TYPE_DUMMY,
- ConnectivityManager.TYPE_DUMMY,
+ ConnectivityManager.TYPE_WIFI,
+ ConnectivityManager.TYPE_WIFI,
"TestNetwork",
"TestNetwork");
} else {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 9b4b97e7f55d..176905305506 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -17,11 +17,14 @@
package com.android.settingslib.drawer;
import static com.android.settingslib.drawer.TileUtils.IA_SETTINGS_ACTION;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
+import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
+import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
import static com.google.common.truth.Truth.assertThat;
@@ -189,7 +192,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, "my title", 0);
+ URI_GET_SUMMARY, "my title", 0, PROFILE_ALL);
info.add(resolveInfo);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
@@ -211,7 +214,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
info.add(resolveInfo);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
@@ -235,7 +238,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.packageName = "com.android.settings";
resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
info.add(resolveInfo);
@@ -258,7 +261,7 @@ public class TileUtilsTest {
final List<Tile> outTiles = new ArrayList<>();
final List<ResolveInfo> info = new ArrayList<>();
final ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.packageName = "com.android.settings";
resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
info.add(resolveInfo);
@@ -290,7 +293,7 @@ public class TileUtilsTest {
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
- URI_GET_SUMMARY, null, 123);
+ URI_GET_SUMMARY, null, 123, PROFILE_ALL);
resolveInfo.activityInfo.metaData
.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
info.add(resolveInfo);
@@ -327,6 +330,26 @@ public class TileUtilsTest {
assertThat(outTiles).hasSize(2);
}
+ @Test
+ public void loadTilesForAction_isPrimaryProfileOnly_shouldSkipNonPrimaryUserTiles() {
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123, PROFILE_PRIMARY);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+ .thenReturn(info);
+ when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(),
+ anyInt())).thenReturn(info);
+
+ TileUtils.loadTilesForAction(mContext, new UserHandle(10), IA_SETTINGS_ACTION,
+ addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
+
+ assertThat(outTiles).isEmpty();
+ }
+
public static ResolveInfo newInfo(boolean systemApp, String category) {
return newInfo(systemApp, category, null);
}
@@ -337,14 +360,14 @@ public class TileUtilsTest {
private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
String iconUri, String summaryUri) {
- return newInfo(systemApp, category, keyHint, iconUri, summaryUri, null, 0);
+ return newInfo(systemApp, category, keyHint, iconUri, summaryUri, null, 0, PROFILE_ALL);
}
private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
- String iconUri, String summaryUri, String title, int titleResId) {
+ String iconUri, String summaryUri, String title, int titleResId, String profile) {
final Bundle metaData = newMetaData(category, keyHint, iconUri, summaryUri, title,
- titleResId);
+ titleResId, profile);
final ResolveInfo info = new ResolveInfo();
info.system = systemApp;
@@ -358,6 +381,7 @@ public class TileUtilsTest {
info.providerInfo.packageName = "abc";
info.providerInfo.name = "456";
info.providerInfo.authority = "auth";
+ info.providerInfo.metaData = metaData;
ShadowTileUtils.setMetaData(metaData);
info.providerInfo.applicationInfo = new ApplicationInfo();
@@ -369,7 +393,7 @@ public class TileUtilsTest {
}
private static Bundle newMetaData(String category, String keyHint, String iconUri,
- String summaryUri, String title, int titleResId) {
+ String summaryUri, String title, int titleResId, String profile) {
final Bundle metaData = new Bundle();
metaData.putString("com.android.settings.category", category);
metaData.putInt(META_DATA_PREFERENCE_ICON, 314159);
@@ -388,6 +412,9 @@ public class TileUtilsTest {
} else if (title != null) {
metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
}
+ if (profile != null) {
+ metaData.putString(META_DATA_KEY_PROFILE, profile);
+ }
return metaData;
}
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 8e0161961a49..85f25528f07e 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -17,11 +17,8 @@
package com.android.shell;
import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
import android.util.Log;
-import android.view.Display;
import android.view.SurfaceControl;
/**
@@ -40,22 +37,17 @@ final class Screenshooter {
* @return The screenshot bitmap on success, null otherwise.
*/
static Bitmap takeScreenshot() {
- Display display = DisplayManagerGlobal.getInstance()
- .getRealDisplay(Display.DEFAULT_DISPLAY);
- Point displaySize = new Point();
- display.getRealSize(displaySize);
- final int displayWidth = displaySize.x;
- final int displayHeight = displaySize.y;
-
- int rotation = display.getRotation();
- Rect crop = new Rect(0, 0, displayWidth, displayHeight);
- Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight);
+ Log.d(TAG, "Taking fullscreen screenshot");
// Take the screenshot
- Bitmap screenShot =
- SurfaceControl.screenshot(crop, displayWidth, displayHeight, rotation);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap screenShot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (screenShot == null) {
- Log.e(TAG, "Failed to take screenshot of dimensions " + displayWidth + " x "
- + displayHeight);
+ Log.e(TAG, "Failed to take fullscreen screenshot");
return null;
}
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 53eb2343d26a..401f3e3e0685 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -27,6 +27,7 @@
<item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
<item name="android:textSize">14dp</item>
<item name="android:background">@drawable/kg_emergency_button_background</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:paddingLeft">12dp</item>
<item name="android:paddingRight">12dp</item>
</style>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media.xml b/packages/SystemUI/res/drawable-television/ic_volume_media.xml
new file mode 100644
index 000000000000..e43c4b471db4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media.xml
@@ -0,0 +1,26 @@
+<?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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
new file mode 100644
index 000000000000..0f6dc9517f53
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
@@ -0,0 +1,26 @@
+<?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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M3,15V9H7L12,4V20L7,15H3ZM14,7.97C15.48,8.71 16.5,10.23 16.5,12C16.5,13.77 15.48,15.29 14,16.02V7.97Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
new file mode 100644
index 000000000000..4b59e13516d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
@@ -0,0 +1,27 @@
+<?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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_low.xml b/packages/SystemUI/res/drawable/ic_volume_media_low.xml
new file mode 100644
index 000000000000..87591de39d54
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_media_low.xml
@@ -0,0 +1,18 @@
+<!--
+ 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/ic_volume_media" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/tv_ring_white.xml b/packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml
index 0f7cc1082f71..93f8724b22a9 100644
--- a/packages/SystemUI/res/drawable/tv_ring_white.xml
+++ b/packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml
@@ -16,10 +16,10 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
+ android:shape="rectangle">
- <stroke
- android:width="1dp"
- android:color="@android:color/white" />
+ <corners android:radius="20dp"/>
+ <solid android:color="@color/tv_audio_recording_indicator_icon_background"/>
+ <stroke android:width="1dp" android:color="@color/tv_audio_recording_indicator_stroke"/>
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/tv_circle_dark.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml
index d1ba8e71ec31..fee6e57d2e86 100644
--- a/packages/SystemUI/res/drawable/tv_circle_dark.xml
+++ b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2019 The Android Open Source Project
+ ~ 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.
@@ -16,9 +16,9 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
+ android:shape="rectangle">
- <solid
- android:color="@color/tv_audio_recording_indicator_background" />
+ <solid android:color="@color/tv_volume_dialog_background" />
+ <corners android:radius="@dimen/tv_volume_dialog_corner_radius"/>
-</shape> \ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/drawable/tv_circle_white_translucent.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml
index 55d21de00ca3..3c4fc05914f8 100644
--- a/packages/SystemUI/res/drawable/tv_circle_white_translucent.xml
+++ b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2019 The Android Open Source Project
+ ~ 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.
@@ -17,8 +17,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
+ <solid android:color="@color/tv_volume_dialog_circle" />
- <solid
- android:color="@color/tv_audio_recording_indicator_pulse" />
-
-</shape> \ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog.xml b/packages/SystemUI/res/layout-land-television/volume_dialog.xml
index e0d158d757b3..56d847c6aa2e 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog.xml
@@ -20,7 +20,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<FrameLayout
android:id="@+id/volume_dialog"
@@ -46,7 +46,7 @@
android:translationZ="@dimen/volume_dialog_elevation"
android:clipChildren="false"
android:clipToPadding="false"
- android:background="@drawable/rounded_bg_full">
+ android:background="@drawable/tv_volume_dialog_background">
<LinearLayout
android:id="@+id/volume_dialog_rows"
@@ -54,9 +54,7 @@
android:layout_height="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:gravity="center"
- android:orientation="horizontal"
- android:paddingRight="@dimen/volume_dialog_stream_padding"
- android:paddingLeft="@dimen/volume_dialog_stream_padding">
+ android:orientation="horizontal">
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
@@ -98,4 +96,4 @@
</FrameLayout>
-</FrameLayout> \ No newline at end of file
+</FrameLayout>
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 08209ab09169..c0f0aa8bbc8d 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
@@ -21,11 +21,12 @@
android:background="@android:color/transparent"
android:clipChildren="false"
android:clipToPadding="false"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:padding="@dimen/tv_volume_dialog_row_padding"
android:background="@android:color/transparent"
android:gravity="center"
android:layout_gravity="center"
@@ -33,9 +34,9 @@
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/volume_row_icon"
style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_dialog_tap_target_size"
- android:layout_height="@dimen/volume_dialog_tap_target_size"
- android:background="@drawable/ripple_drawable_20dp"
+ android:layout_width="@dimen/tv_volume_dialog_bubble_size"
+ android:layout_height="@dimen/tv_volume_dialog_bubble_size"
+ android:background="@drawable/tv_volume_dialog_circle"
android:tint="@color/accent_tint_color_selector"
android:soundEffectsEnabled="false" />
<TextView
@@ -62,6 +63,15 @@
android:layout_gravity="center"
android:rotation="0" />
</FrameLayout>
+ <TextView
+ android:id="@+id/volume_number"
+ android:layout_width="@dimen/tv_volume_dialog_bubble_size"
+ android:layout_height="@dimen/tv_volume_dialog_bubble_size"
+ android:maxLength="2"
+ android:gravity="center"
+ android:background="@drawable/tv_volume_dialog_circle"
+ android:textSize="@dimen/tv_volume_number_text_size"
+ android:textColor="@color/accent_tint_color_selector"/>
</LinearLayout>
<include layout="@layout/volume_dnd_icon"/>
diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml
index 5da7819c3d76..c420117073c5 100644
--- a/packages/SystemUI/res/layout-land/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land/volume_dialog.xml
@@ -22,7 +22,7 @@
android:gravity="right"
android:layout_gravity="right"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<FrameLayout
android:id="@+id/volume_dialog"
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
index 1d2340dadb8a..f9336a540376 100644
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
@@ -19,7 +19,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:padding="32dp">
+ android:padding="12dp">
<FrameLayout
android:layout_width="wrap_content"
@@ -32,45 +32,25 @@
android:orientation="horizontal">
<FrameLayout
- android:layout_width="45dp"
- android:layout_height="47dp">
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
<View
android:id="@+id/icon_container_bg"
- android:layout_width="match_parent"
+ android:layout_width="50dp"
android:layout_height="match_parent"
android:background="@drawable/tv_rect_dark_left_rounded"/>
<FrameLayout
android:id="@+id/icon_mic"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:layout_marginStart="6dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp">
-
- <View
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_circle_dark"/>
-
- <ImageView
- android:id="@+id/pulsating_circle"
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_circle_white_translucent"/>
-
- <ImageView
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:src="@drawable/tv_ring_white"/>
+ android:layout_width="34dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center"
+ android:background="@drawable/tv_rect_shadow_rounded">
<ImageView
- android:layout_width="16dp"
- android:layout_height="16dp"
+ android:layout_width="13dp"
+ android:layout_height="13dp"
android:layout_gravity="center"
android:background="@drawable/tv_ic_mic_white"/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 7d6547b9cd42..a90b1eb471ff 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -22,7 +22,7 @@
android:gravity="right"
android:layout_gravity="right"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<!-- right-aligned to be physically near volume button -->
<LinearLayout
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 6128da8627a9..b9efc5be70c1 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -20,7 +20,7 @@
android:layout_width="@dimen/volume_dialog_panel_width"
android:clipChildren="false"
android:clipToPadding="false"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<LinearLayout
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ee8700261db5..bac915d854d8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Versteek die huidige sessie."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Versteek"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 03eb39659ef3..aedbded46298 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"የአሁኑን ክፍለ-ጊዜ ደብቅ።"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ደብቅ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 95d54a2386dd..fee86ca42fe6 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1093,7 +1093,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
<string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"إخفاء الجلسة الحالية"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"إخفاء"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 3023a27b15b4..3778df80197b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বৰ্তমানৰ ছেশ্বনটো লুকুৱাওক।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকুৱাওক"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্‌টো পৰীক্ষা কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 3c8e04b7ba35..874bf7465827 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Cari sessiyanı gizlədin."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizlədin"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 4b400eb479c9..2a120c57e955 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte aktuelnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index f1064fb7b1d7..e4bb67ae65c6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультымедыя"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Схаваць цяперашні сеанс."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Схаваць"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8ba2a1e51769..c51e58ccd6cf 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Скриване на текущата сесия."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скриване"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 5861c44c1cbb..3d00ca858ef5 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বর্তমান সেশন লুকান।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকান"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"নতুন কন্ট্রোল দেখতে পাওয়ার বোতাম টিপে ধরে থাকুন"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"\'এক হাতে ব্যবহার করার মোড\'-এর ব্যবহার"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"বেরিয়ে আসার জন্য, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন অথবা অ্যাপের আইকনের উপরে যেকোনও জায়গায় ট্যাপ করুন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 984cbebd42eb..14259840d503 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte trenutnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b8c41efa7813..b1501558f924 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Amaga la sessió actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Amaga"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f946cc4f9552..ae6cc13cd1df 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrýt aktuální relaci."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrýt"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a6de8a618f23..09f7f1a8762e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medie"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den aktuelle session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 372cc1166fce..2410e4785c8d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medien"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Du kannst die aktuelle Sitzung ausblenden."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ausblenden"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zum Anzeigen der Karten für neue Geräte Ein-/Aus-Taste gedrückt halten"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"Einhandmodus verwenden"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b4673476bad5..f66c5a88b102 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Απόκρυψη"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index f73dad3a8bef..acf087d51181 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 6140bf1eea3d..4f4238a5eb45 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎Loading recommendations‎‏‎‎‏‎"</string>
<string name="controls_media_title" msgid="1746947284862928133">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎Media‎‏‎‎‏‎"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎Hide the current session.‎‏‎‎‏‎"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎Hide‎‏‎‎‏‎"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎Dismiss‎‏‎‎‏‎"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎Resume‎‏‎‎‏‎"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎Settings‎‏‎‎‏‎"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎Inactive, check app‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6818116ec9b5..45e072496b25 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta la sesión actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f09a0d24b26e..f7ebbd02708a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar la sesión."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6236f251f55d..1e5e49e0a143 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Peidetakse praegune seanss."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Peida"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 167a09c71ce3..38b2103d7973 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ezkutatu"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
@@ -1085,5 +1085,5 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
<string name="one_handed_tutorial_title" msgid="6312198435090726656">"Esku bakarreko modua erabiltzea"</string>
- <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainean, edonon"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainaldea"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 055505200cc2..d39d0c3d5027 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیه‌ها"</string>
<string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"جلسه فعلی پنهان شود."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"پنهان کردن"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ec9bbc4a8929..fa076c4fc40e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Piilota nykyinen käyttökerta."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Piilota"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6c5387f63eda..9c418f79a075 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Commandes multimédias"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 3a2ae07bc64d..3e2f5fdbff1d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 25c7b4bfab59..9ecd75e80a4c 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta a sesión actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 17cc5a45aeb9..6e05a540a13e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"હાલનું સત્ર છુપાવો."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"છુપાવો"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"નવા નિયંત્રણ જોવા માટે પાવર બટનને દબાવી રાખો"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"એક-હાથે વાપરો મોડનો ઉપયોગ કરી રહ્યાં છીએ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"બહાર નીકળવા માટે, સ્ક્રીનની નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો અથવા ઍપના આઇકન પર ગમે ત્યાં ટૅપ કરો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 97ae7b6e8926..de4fc482a101 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1071,7 +1071,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"इस मीडिया सेशन को छिपाएं."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"छिपाएं"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
@@ -1086,6 +1086,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नए कंट्रोल देखने के लिए पावर बटन दबाकर रखें"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल मेन्यू में बदलाव करें"</string>
- <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करें"</string>
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करना"</string>
<string name="one_handed_tutorial_description" msgid="7674850272340517174">"इसे बंद करने के लिए, स्क्रीन के सबसे निचले हिस्से से ऊपर की ओर स्वाइप करें या ऐप्लिकेशन के आइकॉन के ऊपर कहीं भी टैप करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9e17735ef18d..4bebe79c3c44 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrij trenutačnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 804587f9bdcd..42e251fb39de 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Jelenlegi munkamenet elrejtése."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Elrejtés"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 08ef489901ee..e6b71395c42a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Մեդիա"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Թաքցրեք ընթացիկ աշխատաշրջանը"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Թաքցնել"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ba9eca3f0de9..fec4205ba7da 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Menyembunyikan sesi saat ini."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 629581346d46..3a9e63ba9f1a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fela núverandi lotu."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fela"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ef862cb0f919..3eca501b103c 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Nascondi la sessione attuale."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Nascondi"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 358946d69472..e88c951cf19e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string>
<string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"הסתרת הסשן הנוכחי."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"הסתרה"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 9cb872bf1fab..130f682daaf3 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string>
<string name="controls_media_title" msgid="1746947284862928133">"メディア"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"現在のセッションを非表示にします。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"非表示"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index ef6ff128ed09..d050875c35ce 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string>
<string name="controls_media_title" msgid="1746947284862928133">"მედია"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"დაიმალოს მიმდინარე სესია"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"დამალვა"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 08b1f6262f1f..36c726edb791 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультимедиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ағымдағы сеансты жасыру"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жасыру"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 6d80ee47413c..9d87c583c007 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុក​ការណែនាំ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"មេឌៀ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"លាក់វគ្គ​បច្ចុប្បន្ន។"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"លាក់"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើល​កម្មវិធី"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index db2086458286..901f024c5f71 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಿ."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ಮರೆಮಾಡಿ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index b43eb410c46d..8a6415566676 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string>
<string name="controls_media_title" msgid="1746947284862928133">"미디어"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"현재 세션을 숨깁니다."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"숨기기"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 02e468a4f311..3cf41264a4d4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Учурдагы сеансты жашыруу."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жашыруу"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
diff --git a/packages/SystemUI/res/values-land-television/dimens.xml b/packages/SystemUI/res/values-land-television/dimens.xml
index 499341c662b1..90fc652b05e9 100644
--- a/packages/SystemUI/res/values-land-television/dimens.xml
+++ b/packages/SystemUI/res/values-land-television/dimens.xml
@@ -17,5 +17,8 @@
<resources>
<!-- Width of volume bar -->
<dimen name="volume_dialog_row_width">252dp</dimen>
- <dimen name="volume_dialog_tap_target_size">36dp</dimen>
+ <dimen name="tv_volume_dialog_bubble_size">36dp</dimen>
+ <dimen name="tv_volume_dialog_corner_radius">40dp</dimen>
+ <dimen name="tv_volume_dialog_row_padding">5dp</dimen>
+ <dimen name="tv_volume_number_text_size">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 030bdc1ae120..b1c5a5cd887e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ເຊື່ອງ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6f487416b322..4e9b802f4916 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medija"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Slėpti dabartinį seansą."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Slėpti"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bdea26a1a202..a4c4666fafe3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Paslēpiet pašreizējo sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Paslēpt"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index c9f3777c6192..7e623ad5032f 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сокриј ја тековнава сесија."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сокриј"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index c968c2827437..35e642769981 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string>
<string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"നിലവിലെ സെഷൻ മറയ്‌ക്കുക."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"മറയ്‌ക്കുക"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്‌ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 9ce6779e9ae4..b4690d418480 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Одоогийн харилцан үйлдлийг нуугаарай."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Нуух"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d7126795089f..4ea965ad80fc 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"सध्याचे सेशन लपवा."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लपवा"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 01e918ade0ee..38ee25c7f3e4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sembunyikan sesi semasa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 23b0a06cca8f..150ed94eec38 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string>
<string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"လက်ရှိ စက်ရှင်ကို ဖျောက်ထားမည်။"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ဖျောက်ထားမည်"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ပယ်ရန်"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b0a593fe42f9..d872a89880c9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medier"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den nåværende økten."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 09462cf3ffcb..1974e8088971 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -731,11 +731,11 @@
<string name="see_more_title" msgid="7409317011708185729">"थप हेर्नुहोस्"</string>
<string name="appops_camera" msgid="5215967620896725715">"यो अनुप्रयोगले क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="appops_microphone" msgid="8805468338613070149">"यो अनुप्रयोगले माइक्रोफोनको प्रयोग गर्दै छ।"</string>
- <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्दै छ।"</string>
+ <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्दै छ।"</string>
<string name="appops_camera_mic" msgid="7032239823944420431">"यो अनुप्रयोगले माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
- <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string>
- <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string>
- <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
+ <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string>
+ <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string>
+ <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"सेटिङहरू"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ठिक छ"</string>
<string name="feedback_silenced" msgid="5382212321253328247">"सिस्टमले यो सूचना आउँदा बज्ने ध्वनि बन्द गरेको छ।"</string>
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"हालको सत्र लुकाउनुहोस्।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लुकाउनुहोस्"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नयाँ नियन्त्रण सुविधाहरू हेर्न पावर बटन थिचिराख्नुहोस्"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"नियन्त्रण सुविधाहरू सम्पादन गर्नु…"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"एक हाते मोड प्रयोग गरिँदै छ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"बाहिर निस्कन, स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस् वा एपभन्दा माथि जुनसुकै ठाउँमा ट्याप गर्नुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 2385017a0df7..9da8afa4d698 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"De huidige sessie verbergen."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Verbergen"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index d5c077b3ec1b..5b5cbc62fe21 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ବର୍ତ୍ତମାନର ସେସନ୍ ଲୁଚାନ୍ତୁ।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ଲୁଚାନ୍ତୁ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ନୂଆ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ଏକ-ହାତ ମୋଡ୍ ବ୍ୟବହାର କରି"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ବାହାରି ଯିବା ପାଇଁ, ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ କିମ୍ବା ଆପ୍ ଆଇକନର ଉପରେ ଯେ କୌଣସି ସ୍ଥାନରେ ଟାପ୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 11567821397a..5c31ce71ef98 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਓ।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ਲੁਕਾਓ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ਨਵੇਂ ਕੰਟਰੋਲ ਦੇਖਣ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ਇੱਕ ਹੱਥ ਮੋਡ ਵਰਤਣਾ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ਬਾਹਰ ਜਾਣ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਜਾਂ ਐਪ \'ਤੇ ਕਿਤੇ ਵੀ ਟੈਪ ਕਰੋ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 1f6effe431e7..b7ee75057626 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ukryj bieżącą sesję."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ukryj"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 14d7a84dab28..715b0e45faeb 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a6f7f004f411..1a59de496c91 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculte a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 14d7a84dab28..715b0e45faeb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0f15cfcd23f6..49c3ba0c2cd8 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ascunde sesiunea actuală."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ascunde"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6196f88a7bfb..7fb456d5f425 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Скрыть текущий сеанс?"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скрыть"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8aca9f4e0dbd..1cd1ceb21c97 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string>
<string name="controls_media_title" msgid="1746947284862928133">"මාධ්‍ය"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"වත්මන් සැසිය සඟවන්න."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"සඟවන්න"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"අක්‍රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 45ee562b374c..9d7e7d1cd27c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skryť aktuálnu reláciu."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skryť"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c7ad8ab92da3..ecbf1d905e5b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrije trenutno sejo."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 3e0aecc16d4e..70245b875726 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fshih sesionin aktual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fshih"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 985041b3b24d..1d02ca6ab455 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медији"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сакријте актуелну сесију."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сакриј"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 2018a383b5ed..7a7448be16c5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Dölj den aktuella sessionen."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Dölj"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 6eecc0e402fa..b8d95fcd0c1a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ficha kipindi cha sasa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ficha"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a05e0e735620..60c1cf9dcac0 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
<string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"இந்த அமர்வை மறையுங்கள்."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"மறை"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 7d76abd0f20f..6cfe03d95023 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
<string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ప్రస్తుత సెషన్‌ను దాచు."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"దాచు"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ఇన్‌యాక్టివ్, యాప్ చెక్ చేయండి"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 1696aab66148..7b1479acc35e 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -43,4 +43,7 @@
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.onehanded.OneHandedUI</item>
</string-array>
+
+ <!-- Show a separate icon for low and high volume on the volume dialog -->
+ <bool name="config_showLowMediaVolumeIcon">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index b01c5d88e3b3..4cf7034a29bf 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -22,4 +22,8 @@
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
</style>
+
+ <style name="volume_dialog_theme" parent="qs_theme">
+ <item name="android:colorAccent">@color/tv_volume_dialog_accent</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 765c22424e89..a2c1127df5ca 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ซ่อนเซสชันปัจจุบัน"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ซ่อน"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c2cae9024a60..e5f0532b0e7b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Itago ang kasalukuyang session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Itago"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 74b44f2079c6..4943e2d03920 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Mevcut oturumu gizle."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizle"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 38c331ade344..447912e08835 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медіа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Приховати поточний сеанс."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Приховати"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 69ddabbe94ac..20b551882344 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string>
<string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"موجودہ سیشن چھپائیں۔"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"چھپائیں"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ed704b0f5597..cf1da7508052 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -227,7 +227,7 @@
<string name="data_connection_roaming" msgid="375650836665414797">"Rouming"</string>
<string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
- <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM karta solinmagan."</string>
+ <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kartasiz."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobil internet"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil internet yoniq"</string>
<string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil internet yoqilmagan"</string>
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Berkitish"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5cc209941771..a12a08d0a1e6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ẩn phiên hiện tại."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ẩn"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f670bf682b64..3382365b7ccb 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒体"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隐藏当前会话。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隐藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2e26d6153a8f..1d55ca22a43f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 0049d2ec1f56..e62c164684b3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index c8c99b1c18c1..bd7391203dd8 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fihla iseshini yamanje."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fihla"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 53cd9716c98e..cb49918e4e3f 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -24,7 +24,11 @@
<!-- Background color for audio recording indicator (G800) -->
<color name="tv_audio_recording_indicator_background">#FF3C4043</color>
- <color name="tv_audio_recording_indicator_pulse">#4DFFFFFF</color>
+ <color name="tv_audio_recording_indicator_icon_background">#CC000000</color>
+ <color name="tv_audio_recording_indicator_stroke">#33FFFFFF</color>
<color name="red">#FFCC0000</color>
+ <color name="tv_volume_dialog_background">#E61F232B</color>
+ <color name="tv_volume_dialog_circle">#08FFFFFF</color>
+ <color name="tv_volume_dialog_accent">#FFDADCE0</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fba43a628387..17ba7c99dc0c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -574,4 +574,6 @@
<!-- Animation duration for translating of one handed when trigger / dismiss. -->
<integer name="config_one_handed_translate_animation_duration">150</integer>
+ <!-- Show a separate icon for low and high volume on the volume dialog -->
+ <bool name="config_showLowMediaVolumeIcon">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 67293c57e344..f05be066d2e2 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -21,5 +21,5 @@
<string name="system_ui_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</string>
<!-- Date format for the always on display. -->
- <item type="string" name="system_ui_aod_date_pattern" translatable="false">eeeMMMd</item>
+ <item type="string" name="system_ui_aod_date_pattern" translatable="false">EEEMMMd</item>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9e5b94ee855c..ee07e613a0c5 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -387,6 +387,9 @@
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
</style>
+ <!-- Overridden by values-television/styles.xml with tv-specific settings -->
+ <style name="volume_dialog_theme" parent="qs_theme"/>
+
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:colorAccent">@color/remote_input_accent</item>
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperEngineCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperEngineCompat.java
index 4d968f1763ca..73dc60dbc7da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperEngineCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperEngineCompat.java
@@ -26,6 +26,17 @@ public class WallpaperEngineCompat {
private static final String TAG = "WallpaperEngineCompat";
+ /**
+ * Returns true if {@link IWallpaperEngine#scalePreview(Rect)} is available.
+ */
+ public static boolean supportsScalePreview() {
+ try {
+ return IWallpaperEngine.class.getMethod("scalePreview", Rect.class) != null;
+ } catch (NoSuchMethodException | SecurityException e) {
+ return false;
+ }
+ }
+
private final IWallpaperEngine mWrappedEngine;
public WallpaperEngineCompat(IWallpaperEngine wrappedEngine) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
index 8b953fa46441..be089b12a95d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
@@ -21,7 +21,7 @@ import com.android.internal.logging.UiEventLogger
enum class AssistantSessionEvent(private val id: Int) : UiEventLogger.UiEventEnum {
@UiEvent(doc = "Unknown assistant session event")
- ASSISTANT_SESSION_UNKNOWN(523),
+ ASSISTANT_SESSION_UNKNOWN(0),
@UiEvent(doc = "Assistant session dismissed due to timeout")
ASSISTANT_SESSION_TIMEOUT_DISMISS(524),
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
index 95bbea15a88c..d4e6506bd9a0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -16,6 +16,7 @@
package com.android.systemui.biometrics;
+import android.annotation.NonNull;
import android.content.Context;
import android.os.UserHandle;
import android.text.InputType;
@@ -27,7 +28,9 @@ import android.widget.ImeAwareEditText;
import android.widget.TextView;
import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.VerifyCredentialResponse;
import com.android.systemui.R;
/**
@@ -104,18 +107,21 @@ public class AuthCredentialPasswordView extends AuthCredentialView
return;
}
+ // Request LockSettingsService to return the Gatekeeper Password in the
+ // VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
+ // Gatekeeper Password and operationId.
mPendingLockCheck = LockPatternChecker.verifyCredential(mLockPatternUtils,
- password, mOperationId, mEffectiveUserId, this::onCredentialVerified);
+ password, mEffectiveUserId, LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW,
+ this::onCredentialVerified);
}
}
@Override
- protected void onCredentialVerified(byte[] attestation, int timeoutMs) {
- super.onCredentialVerified(attestation, timeoutMs);
+ protected void onCredentialVerified(@NonNull VerifyCredentialResponse response,
+ int timeoutMs) {
+ super.onCredentialVerified(response, timeoutMs);
- final boolean matched = attestation != null;
-
- if (matched) {
+ if (response.isMatched()) {
mImm.hideSoftInputFromWindow(getWindowToken(), 0 /* flags */);
} else {
mPasswordField.setText("");
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
index 6d16f4397115..ad89ae82f637 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java
@@ -16,6 +16,7 @@
package com.android.systemui.biometrics;
+import android.annotation.NonNull;
import android.content.Context;
import android.util.AttributeSet;
@@ -23,6 +24,7 @@ import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.VerifyCredentialResponse;
import com.android.systemui.R;
import java.util.List;
@@ -61,22 +63,25 @@ public class AuthCredentialPatternView extends AuthCredentialView {
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
// Pattern size is less than the minimum, do not count it as a failed attempt.
- onPatternVerified(null /* attestation */, 0 /* timeoutMs */);
+ onPatternVerified(VerifyCredentialResponse.ERROR, 0 /* timeoutMs */);
return;
}
try (LockscreenCredential credential = LockscreenCredential.createPattern(pattern)) {
+ // Request LockSettingsService to return the Gatekeeper Password in the
+ // VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
+ // Gatekeeper Password and operationId.
mPendingLockCheck = LockPatternChecker.verifyCredential(
mLockPatternUtils,
credential,
- mOperationId,
mEffectiveUserId,
+ LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW,
this::onPatternVerified);
}
}
- private void onPatternVerified(byte[] attestation, int timeoutMs) {
- AuthCredentialPatternView.this.onCredentialVerified(attestation, timeoutMs);
+ private void onPatternVerified(@NonNull VerifyCredentialResponse response, int timeoutMs) {
+ AuthCredentialPatternView.this.onCredentialVerified(response, timeoutMs);
if (timeoutMs > 0) {
mLockPatternView.setEnabled(false);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
index 2695c69056b1..a8f6f85201f6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java
@@ -16,6 +16,9 @@
package com.android.systemui.biometrics;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -38,12 +41,10 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.VerifyCredentialResponse;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -283,14 +284,18 @@ public abstract class AuthCredentialView extends LinearLayout {
protected void onErrorTimeoutFinish() {}
- protected void onCredentialVerified(byte[] attestation, int timeoutMs) {
-
- final boolean matched = attestation != null;
-
- if (matched) {
+ protected void onCredentialVerified(@NonNull VerifyCredentialResponse response, int timeoutMs) {
+ if (response.isMatched()) {
mClearErrorRunnable.run();
mLockPatternUtils.userPresent(mEffectiveUserId);
- mCallback.onCredentialMatched(attestation);
+
+ // The response passed into this method contains the Gatekeeper Password. We still
+ // have to request Gatekeeper to create a Hardware Auth Token with the
+ // Gatekeeper Password and Challenge (keystore operationId in this case)
+ final VerifyCredentialResponse gkResponse = mLockPatternUtils.verifyGatekeeperPassword(
+ response.getGatekeeperPw(), mOperationId, mEffectiveUserId);
+
+ mCallback.onCredentialMatched(gkResponse.getGatekeeperHAT());
} else {
if (timeoutMs > 0) {
mHandler.removeCallbacks(mClearErrorRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index fce545b421d5..f774358b69fb 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -38,6 +38,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
@@ -72,7 +73,8 @@ import dagger.Provides;
subcomponents = {StatusBarComponent.class,
NotificationRowComponent.class,
DozeComponent.class,
- ExpandableNotificationRowComponent.class})
+ ExpandableNotificationRowComponent.class,
+ NotificationShelfComponent.class})
public abstract class SystemUIModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index ded386159dca..563684ad65c1 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -159,7 +159,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
} else {
float distance = (float) Math.hypot(mLastPos.x - mDownPos.x,
mLastPos.y - mDownPos.y);
- if (distance > mDragDistThreshold && mPassedSlop) {
+ if (distance > mDragDistThreshold) {
mGestureEventCallback.onStop();
}
}
@@ -273,13 +273,13 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
*/
public interface OneHandedGestureEventCallback {
/**
- * Handle the start event event, and return whether the event was consumed.
+ * Handles the start gesture.
*/
- boolean onStart();
+ void onStart();
/**
- * Handle the exit event event, and return whether the event was consumed.
+ * Handles the exit gesture.
*/
- boolean onStop();
+ void onStop();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
index 51e587586852..a3921ee54fec 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
@@ -24,6 +24,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
+import android.view.KeyEvent;
import androidx.annotation.NonNull;
@@ -33,6 +34,7 @@ import com.android.systemui.R;
import com.android.systemui.model.SysUiState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
@@ -50,9 +52,11 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
private static final String TAG = "OneHandedManager";
private boolean mIsOneHandedEnabled;
+ private boolean mIsSwipeToNotificationEnabled;
private boolean mTaskChangeToExit;
private float mOffSetFraction;
+ private final CommandQueue mCommandQueue;
private final DisplayController mDisplayController;
private final OneHandedGestureHandler mGestureHandler;
private final OneHandedTimeoutHandler mTimeoutHandler;
@@ -60,11 +64,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
private final OneHandedTutorialHandler mTutorialHandler;
private final SysUiState mSysUiFlagContainer;
- private Context mContext;
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
- private OneHandedGestureHandler.OneHandedGestureEventCallback mGestureEventCallback;
- private OneHandedTouchHandler.OneHandedTouchEventCallback mTouchEventCallback;
- private OneHandedTransitionCallback mTransitionCallback;
/**
* Handler for system task stack changes, exit when user lunch new task or bring task to front
@@ -105,13 +105,14 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
*/
@Inject
public OneHandedManagerImpl(Context context,
+ CommandQueue commandQueue,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
OneHandedGestureHandler gestureHandler,
SysUiState sysUiState) {
- mContext = context;
+ mCommandQueue = commandQueue;
mDisplayAreaOrganizer = displayAreaOrganizer;
mDisplayController = displayController;
mDisplayController.addDisplayChangingController(mRotationController);
@@ -120,6 +121,8 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
context.getResources().getFraction(R.fraction.config_one_handed_offset, 1, 1);
mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
context.getContentResolver());
+ mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ context.getContentResolver());
mTimeoutHandler = OneHandedTimeoutHandler.get();
mTouchHandler = touchHandler;
mTutorialHandler = tutorialHandler;
@@ -148,11 +151,19 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
}
/**
- * Start one handed mode
+ * Sets whether to enable swipe bottom to notification gesture when user update settings.
+ */
+ public void setSwipeToNotificationEnabled(boolean enabled) {
+ mIsSwipeToNotificationEnabled = enabled;
+ updateOneHandedEnabled();
+ }
+
+ /**
+ * Enters one handed mode.
*/
@Override
public void startOneHanded() {
- if (!mDisplayAreaOrganizer.isInOneHanded() && mIsOneHandedEnabled) {
+ if (!mDisplayAreaOrganizer.isInOneHanded()) {
final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
mTimeoutHandler.resetTimer();
@@ -160,7 +171,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
}
/**
- * Stop one handed mode
+ * Exits one handed mode.
*/
@Override
public void stopOneHanded() {
@@ -171,53 +182,45 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
}
private void setupGestures() {
- mTouchEventCallback = new OneHandedTouchHandler.OneHandedTouchEventCallback() {
- @Override
- public boolean onStart() {
- boolean result = false;
- if (!mDisplayAreaOrganizer.isInOneHanded()) {
- startOneHanded();
- result = true;
- }
- return result;
- }
+ mTouchHandler.registerTouchEventListener(
+ new OneHandedTouchHandler.OneHandedTouchEventCallback() {
+ @Override
+ public void onStart() {
+ if (mIsOneHandedEnabled) {
+ startOneHanded();
+ }
+ }
- @Override
- public boolean onStop() {
- boolean result = false;
- if (mDisplayAreaOrganizer.isInOneHanded()) {
- stopOneHanded();
- result = true;
- }
- return result;
- }
- };
- mTouchHandler.registerTouchEventListener(mTouchEventCallback);
+ @Override
+ public void onStop() {
+ if (mIsOneHandedEnabled) {
+ stopOneHanded();
+ }
+ }
+ });
- mGestureEventCallback = new OneHandedGestureHandler.OneHandedGestureEventCallback() {
- @Override
- public boolean onStart() {
- boolean result = false;
- if (!mDisplayAreaOrganizer.isInOneHanded()) {
- startOneHanded();
- result = true;
- }
- return result;
- }
+ mGestureHandler.setGestureEventListener(
+ new OneHandedGestureHandler.OneHandedGestureEventCallback() {
+ @Override
+ public void onStart() {
+ if (mIsOneHandedEnabled) {
+ startOneHanded();
+ } else if (mIsSwipeToNotificationEnabled) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
+ }
+ }
- @Override
- public boolean onStop() {
- boolean result = false;
- if (mDisplayAreaOrganizer.isInOneHanded()) {
- stopOneHanded();
- result = true;
- }
- return result;
- }
- };
- mGestureHandler.setGestureEventListener(mGestureEventCallback);
+ @Override
+ public void onStop() {
+ if (mIsOneHandedEnabled) {
+ stopOneHanded();
+ } else if (mIsSwipeToNotificationEnabled) {
+ mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
+ }
+ }
+ });
- mTransitionCallback = new OneHandedTransitionCallback() {
+ mDisplayAreaOrganizer.registerTransitionCallback(new OneHandedTransitionCallback() {
@Override
public void onStartFinished(Rect bounds) {
mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
@@ -229,8 +232,8 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
mSysUiFlagContainer.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
false).commitUpdate(DEFAULT_DISPLAY);
}
- };
- mDisplayAreaOrganizer.registerTransitionCallback(mTransitionCallback);
+ });
+
mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler);
@@ -264,7 +267,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled);
- mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled);
+ mGestureHandler.onOneHandedEnabled(mIsOneHandedEnabled || mIsSwipeToNotificationEnabled);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java
index 9b232cd0a19d..1b6ec04193f0 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java
@@ -132,6 +132,14 @@ public final class OneHandedSettingsUtil {
Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
}
+ /**
+ * Returns whether swipe bottom to notification gesture enabled or not.
+ */
+ public static boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver) {
+ return Settings.Secure.getInt(resolver,
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0) == 1;
+ }
+
protected static void dump(PrintWriter pw, String prefix, ContentResolver resolver) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
index d616a3a45b90..1446e5a431c6 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
@@ -175,13 +175,13 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
*/
public interface OneHandedTouchEventCallback {
/**
- * Handle the start event event, and return whether the event was consumed.
+ * Handle the start event.
*/
- boolean onStart();
+ void onStart();
/**
- * Handle the exit event event, and return whether the event was consumed.
+ * Handle the exit event.
*/
- boolean onStop();
+ void onStop();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
index 9239435f1622..0903c0e5c512 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
@@ -40,7 +40,6 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.SystemUI;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.statusbar.CommandQueue;
@@ -80,7 +79,10 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
mOneHandedManager.setOneHandedEnabled(enabled);
}
- setEnabledGesturalOverlay(enabled);
+ // Also checks swipe to notification settings since they all need gesture overlay.
+ setEnabledGesturalOverlay(
+ enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver()));
}
};
@@ -130,11 +132,28 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
}
};
+ private final ContentObserver mSwipeToNotificationEnabledObserver =
+ new ContentObserver(mMainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ final boolean enabled =
+ OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContext.getContentResolver());
+ if (mOneHandedManager != null) {
+ mOneHandedManager.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,
OneHandedManagerImpl oneHandedManager,
- DumpManager dumpManager,
OneHandedSettingsUtil settingsUtil,
ScreenLifecycle screenLifecycle) {
super(context);
@@ -239,6 +258,9 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
mContext.getContentResolver(), mTimeoutObserver);
mSettingUtil.registerSettingsKeyObserver(Settings.Secure.TAPS_APP_TO_EXIT,
mContext.getContentResolver(), mTaskChangeExitObserver);
+ mSettingUtil.registerSettingsKeyObserver(
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ mContext.getContentResolver(), mSwipeToNotificationEnabledObserver);
}
private void updateSettings() {
@@ -248,6 +270,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
mSettingUtil.getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
mOneHandedManager.setTaskChangeToExit(
mSettingUtil.getSettingsTapsAppToExit(mContext.getContentResolver()));
+ mOneHandedManager.setSwipeToNotificationEnabled(
+ mSettingUtil.getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index f8655cc44d2a..52a2cecec6b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -3,7 +3,9 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -44,6 +46,24 @@ public class PageIndicator extends ViewGroup {
private int mPosition = -1;
private boolean mAnimating;
+ private final Animatable2.AnimationCallback mAnimationCallback =
+ new Animatable2.AnimationCallback() {
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ super.onAnimationEnd(drawable);
+ if (DEBUG) Log.d(TAG, "onAnimationEnd - queued: " + mQueuedPositions.size());
+ if (drawable instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) drawable).unregisterAnimationCallback(
+ mAnimationCallback);
+ }
+ mAnimating = false;
+ if (mQueuedPositions.size() != 0) {
+ setPosition(mQueuedPositions.remove(0));
+ }
+ }
+ };
+
public PageIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -197,10 +217,8 @@ public class PageIndicator extends ViewGroup {
final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) getContext().getDrawable(res);
imageView.setImageDrawable(avd);
avd.forceAnimationOnUI();
+ avd.registerAnimationCallback(mAnimationCallback);
avd.start();
- // TODO: Figure out how to user an AVD animation callback instead, which doesn't
- // seem to be working right now...
- postDelayed(mAnimationDone, ANIMATION_DURATION);
}
private int getTransition(boolean fromB, boolean isMajorAState, boolean isMajor) {
@@ -264,15 +282,4 @@ public class PageIndicator extends ViewGroup {
getChildAt(i).layout(left, 0, mPageIndicatorWidth + left, mPageIndicatorHeight);
}
}
-
- private final Runnable mAnimationDone = new Runnable() {
- @Override
- public void run() {
- if (DEBUG) Log.d(TAG, "onAnimationEnd - queued: " + mQueuedPositions.size());
- mAnimating = false;
- if (mQueuedPositions.size() != 0) {
- setPosition(mQueuedPositions.remove(0));
- }
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c53523032353..6747281ac437 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -50,6 +50,7 @@ import android.graphics.drawable.LayerDrawable;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -556,11 +557,18 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) {
// copy the input Rect, since SurfaceControl.screenshot can mutate it
Rect screenRect = new Rect(crop);
- int rot = mDisplay.getRotation();
int width = crop.width();
int height = crop.height();
- saveScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,
- Insets.NONE, true);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setSourceCrop(crop)
+ .setSize(width, height)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
+ saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
}
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 71e788375d5e..1bea72aea2ba 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -385,7 +385,7 @@ public class BrightnessController implements ToggleSlider.Listener {
if (stopTracking) {
// TODO(brightnessfloat): change to use float value instead.
MetricsLogger.action(mContext, metric,
- BrightnessSynchronizer.brightnessFloatToInt(mContext, valFloat));
+ BrightnessSynchronizer.brightnessFloatToInt(valFloat));
}
setBrightness(valFloat);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index d798692879f5..36f8bcdc9123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
import android.content.res.Configuration;
@@ -26,7 +25,6 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.MathUtils;
import android.view.DisplayCutout;
import android.view.View;
@@ -36,10 +34,8 @@ import android.view.WindowInsets;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -50,12 +46,8 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.ViewState;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
@@ -69,7 +61,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
- private final KeyguardBypassController mBypassController;
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
@@ -77,7 +68,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mIconAppearTopPadding;
private float mHiddenShelfIconSize;
private int mStatusBarHeight;
- private int mStatusBarPaddingStart;
private AmbientState mAmbientState;
private NotificationStackScrollLayout mHostLayout;
private int mMaxLayoutHeight;
@@ -88,7 +78,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mScrollFastThreshold;
private int mIconSize;
private int mStatusBarState;
- private float mMaxShelfEnd;
private int mRelativeOffset;
private boolean mInteractive;
private float mOpenedAmount;
@@ -99,13 +88,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
private Rect mClipRect = new Rect();
private int mCutoutHeight;
private int mGapHeight;
+ private NotificationShelfController mController;
- @Inject
- public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
- AttributeSet attrs,
- KeyguardBypassController keyguardBypassController) {
+ public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
- mBypassController = keyguardBypassController;
}
@Override
@@ -128,19 +114,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
initDimens();
}
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
- .addCallback(this, SysuiStatusBarStateController.RANK_SHELF);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Dependency.get(StatusBarStateController.class).removeCallback(this);
- }
-
public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) {
mAmbientState = ambientState;
mHostLayout = hostLayout;
@@ -150,7 +123,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
Resources res = getResources();
mIconAppearTopPadding = res.getDimensionPixelSize(R.dimen.notification_icon_appear_padding);
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
- mStatusBarPaddingStart = res.getDimensionPixelOffset(R.dimen.status_bar_padding_start);
mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
@@ -315,9 +287,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
transitionAmount = inShelfAmount;
}
// We don't want to modify the color if the notification is hun'd
- boolean canModifyColor = mAmbientState.isShadeExpanded()
- && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
- if (isLastChild && canModifyColor) {
+ if (isLastChild && mController.canModifyColorOfNotifications()) {
if (colorOfViewBeforeLast == NO_COLOR) {
colorOfViewBeforeLast = ownColorUntinted;
}
@@ -999,10 +969,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
return mInteractive;
}
- public void setMaxShelfEnd(float maxShelfEnd) {
- mMaxShelfEnd = maxShelfEnd;
- }
-
public void setAnimationsEnabled(boolean enabled) {
mAnimationsEnabled = enabled;
if (!enabled) {
@@ -1044,6 +1010,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
updateBackgroundColors();
}
+ public void setController(NotificationShelfController notificationShelfController) {
+ mController = notificationShelfController;
+ }
+
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
@@ -1056,7 +1026,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
super.applyToView(view);
- setMaxShelfEnd(maxShelfEnd);
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
@@ -1070,7 +1039,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
super.animateTo(child, properties);
- setMaxShelfEnd(maxShelfEnd);
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java
new file mode 100644
index 000000000000..9f8f8447d72c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.view.View;
+
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.statusbar.phone.StatusBarNotificationPresenter;
+
+import javax.inject.Inject;
+
+/**
+ * Controller class for {@link NotificationShelf}.
+ */
+@NotificationRowScope
+public class NotificationShelfController {
+ private final NotificationShelf mView;
+ private final ActivatableNotificationViewController mActivatableNotificationViewController;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
+ private final View.OnAttachStateChangeListener mOnAttachStateChangeListener;
+ private AmbientState mAmbientState;
+
+ @Inject
+ public NotificationShelfController(NotificationShelf notificationShelf,
+ ActivatableNotificationViewController activatableNotificationViewController,
+ KeyguardBypassController keyguardBypassController,
+ SysuiStatusBarStateController statusBarStateController) {
+ mView = notificationShelf;
+ mActivatableNotificationViewController = activatableNotificationViewController;
+ mKeyguardBypassController = keyguardBypassController;
+ mStatusBarStateController = statusBarStateController;
+ mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mStatusBarStateController.addCallback(
+ mView, SysuiStatusBarStateController.RANK_SHELF);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mStatusBarStateController.removeCallback(mView);
+ }
+ };
+ }
+
+ public void init() {
+ mActivatableNotificationViewController.init();
+ mView.setController(this);
+ mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
+ if (mView.isAttachedToWindow()) {
+ mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
+ }
+ }
+
+ public NotificationShelf getView() {
+ return mView;
+ }
+
+ public boolean canModifyColorOfNotifications() {
+ return mAmbientState.isShadeExpanded()
+ && !(mAmbientState.isOnKeyguard() && mKeyguardBypassController.getBypassEnabled());
+ }
+
+ public NotificationIconContainer getShelfIcons() {
+ return mView.getShelfIcons();
+ }
+
+ public void setCollapsedIcons(NotificationIconContainer notificationIcons) {
+ mView.setCollapsedIcons(notificationIcons);
+ }
+
+ public void bind(AmbientState ambientState,
+ NotificationStackScrollLayout notificationStackScrollLayout) {
+ mView.bind(ambientState, notificationStackScrollLayout);
+ mAmbientState = ambientState;
+ }
+
+ public int getHeight() {
+ return mView.getHeight();
+ }
+
+ public void updateState(AmbientState ambientState) {
+ mAmbientState = ambientState;
+ mView.updateState(ambientState);
+ }
+
+ public int getIntrinsicHeight() {
+ return mView.getIntrinsicHeight();
+ }
+
+ public void setOnActivatedListener(StatusBarNotificationPresenter presenter) {
+ mView.setOnActivatedListener(presenter);
+ }
+
+ public void setOnClickListener(View.OnClickListener onClickListener) {
+ mView.setOnClickListener(onClickListener);
+ }
+
+ public int getNotGoneIndex() {
+ return mView.getNotGoneIndex();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
index 7cda23544ca0..27e4adee68ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
@@ -21,7 +21,7 @@ import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -41,22 +41,22 @@ public class SuperStatusBarViewFactory {
private final Context mContext;
private final InjectionInflationController mInjectionInflationController;
- private final NotificationRowComponent.Builder mNotificationRowComponentBuilder;
private final LockscreenLockIconController mLockIconController;
+ private final NotificationShelfComponent.Builder mNotificationShelfComponentBuilder;
private NotificationShadeWindowView mNotificationShadeWindowView;
private StatusBarWindowView mStatusBarWindowView;
- private NotificationShelf mNotificationShelf;
+ private NotificationShelfController mNotificationShelfController;
@Inject
public SuperStatusBarViewFactory(Context context,
InjectionInflationController injectionInflationController,
- NotificationRowComponent.Builder notificationRowComponentBuilder,
+ NotificationShelfComponent.Builder notificationShelfComponentBuilder,
LockscreenLockIconController lockIconController) {
mContext = context;
mInjectionInflationController = injectionInflationController;
- mNotificationRowComponentBuilder = notificationRowComponentBuilder;
mLockIconController = lockIconController;
+ mNotificationShelfComponentBuilder = notificationShelfComponentBuilder;
}
/**
@@ -114,25 +114,27 @@ public class SuperStatusBarViewFactory {
* isn't immediately attached, but the layout params of this view is used
* during inflation.
*/
- public NotificationShelf getNotificationShelf(ViewGroup container) {
- if (mNotificationShelf != null) {
- return mNotificationShelf;
+ public NotificationShelfController getNotificationShelfController(ViewGroup container) {
+ if (mNotificationShelfController != null) {
+ return mNotificationShelfController;
}
- mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable(
- LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf,
- container, /* attachToRoot= */ false);
+ NotificationShelf view = (NotificationShelf) LayoutInflater.from(mContext)
+ .inflate(R.layout.status_bar_notification_shelf, container, /* attachToRoot= */
+ false);
- NotificationRowComponent component = mNotificationRowComponentBuilder
- .activatableNotificationView(mNotificationShelf)
- .build();
- component.getActivatableNotificationViewController().init();
-
- if (mNotificationShelf == null) {
+ if (view == null) {
throw new IllegalStateException(
"R.layout.status_bar_notification_shelf could not be properly inflated");
}
- return mNotificationShelf;
+
+ NotificationShelfComponent component = mNotificationShelfComponentBuilder
+ .notificationShelf(view)
+ .build();
+ mNotificationShelfController = component.getNotificationShelfController();
+ mNotificationShelfController.init();
+
+ return mNotificationShelfController;
}
public NotificationPanelView getNotificationPanelView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java
new file mode 100644
index 000000000000..af8d6ec727d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.dagger;
+
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+
+import dagger.Binds;
+import dagger.BindsInstance;
+import dagger.Module;
+import dagger.Subcomponent;
+
+/**
+ * Dagger subcomponent for NotificationShelf.
+ */
+@Subcomponent(modules = {ActivatableNotificationViewModule.class,
+ NotificationShelfComponent.NotificationShelfModule.class})
+@NotificationRowScope
+public interface NotificationShelfComponent {
+ /**
+ * Builder for {@link NotificationShelfComponent}.
+ */
+ @Subcomponent.Builder
+ interface Builder {
+ @BindsInstance
+ Builder notificationShelf(NotificationShelf view);
+ NotificationShelfComponent build();
+ }
+
+ /**
+ * Creates a NotificationShelfController.
+ */
+ @NotificationRowScope
+ NotificationShelfController getNotificationShelfController();
+ /**
+ * Dagger Module that extracts interesting properties from a NotificationShelf.
+ */
+ @Module
+ abstract class NotificationShelfModule {
+
+ /** NotificationShelf is provided as an instance of ActivatableNotificationView. */
+ @Binds
+ abstract ActivatableNotificationView bindNotificationShelf(NotificationShelf view);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 66a541a923a4..57c1a16a259d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -113,6 +113,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -5419,28 +5420,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setShelf(NotificationShelf shelf) {
+ public void setShelfController(NotificationShelfController notificationShelfController) {
int index = -1;
if (mShelf != null) {
index = indexOfChild(mShelf);
removeView(mShelf);
}
- mShelf = shelf;
+ mShelf = notificationShelfController.getView();
addView(mShelf, index);
- mAmbientState.setShelf(shelf);
- mStateAnimator.setShelf(shelf);
- shelf.bind(mAmbientState, this);
+ mAmbientState.setShelf(mShelf);
+ mStateAnimator.setShelf(mShelf);
+ notificationShelfController.bind(mAmbientState, this);
if (ANCHOR_SCROLLING) {
mScrollAnchorView = mShelf;
}
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public NotificationShelf getNotificationShelf() {
- return mShelf;
- }
-
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setMaxDisplayedNotifications(int maxDisplayedNotifications) {
if (mMaxDisplayedNotifications != maxDisplayedNotifications) {
mMaxDisplayedNotifications = maxDisplayedNotifications;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 687f5f15a78c..8a85f7d6a2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -30,6 +30,8 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.KeyButtonView;
+import java.util.function.Consumer;
+
/** Containing logic for the rotation button on the physical left bottom corner of the screen. */
public class FloatingRotationButton implements RotationButton {
@@ -45,6 +47,7 @@ public class FloatingRotationButton implements RotationButton {
private boolean mCanShow = true;
private RotationButtonController mRotationButtonController;
+ private Consumer<Boolean> mVisibilityChangedCallback;
FloatingRotationButton(Context context) {
mContext = context;
@@ -67,6 +70,11 @@ public class FloatingRotationButton implements RotationButton {
}
@Override
+ public void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback) {
+ mVisibilityChangedCallback = visibilityChangedCallback;
+ }
+
+ @Override
public View getCurrentView() {
return mKeyButtonView;
}
@@ -105,6 +113,16 @@ public class FloatingRotationButton implements RotationButton {
mKeyButtonDrawable.resetAnimation();
mKeyButtonDrawable.startAnimation();
}
+ mKeyButtonView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5,
+ int i6, int i7) {
+ if (mIsShowing && mVisibilityChangedCallback != null) {
+ mVisibilityChangedCallback.accept(true);
+ }
+ mKeyButtonView.removeOnLayoutChangeListener(this);
+ }
+ });
return true;
}
@@ -115,6 +133,9 @@ public class FloatingRotationButton implements RotationButton {
}
mWindowManager.removeViewImmediate(mKeyButtonView);
mIsShowing = false;
+ if (mVisibilityChangedCallback != null) {
+ mVisibilityChangedCallback.accept(false);
+ }
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 8c5e2ceaeadf..fd653b4e8aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -120,7 +120,6 @@ import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
-import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
@@ -132,7 +131,6 @@ import com.android.systemui.util.LifecycleFragment;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
@@ -194,6 +192,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private int mLayoutDirection;
private boolean mForceNavBarHandleOpaque;
+ private boolean mIsCurrentUserSetup;
/** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
private @Appearance int mAppearance;
@@ -313,6 +312,10 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
@Override
public void onNavBarButtonAlphaChanged(float alpha, boolean animate) {
+ if (!mIsCurrentUserSetup) {
+ // If the current user is not yet setup, then don't update any button alphas
+ return;
+ }
ButtonDispatcher buttonDispatcher = null;
boolean forceVisible = false;
if (QuickStepContract.isSwipeUpMode(mNavBarMode)) {
@@ -351,15 +354,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
};
- private final ContextButtonListener mRotationButtonListener = (button, visible) -> {
- if (visible) {
- // If the button will actually become visible and the navbar is about to hide,
- // tell the statusbar to keep it around for longer
- mAutoHideController.touchAutoHide();
- mNavigationBarView.notifyActiveTouchRegions();
- }
- };
-
private final Runnable mAutoDim = () -> getBarTransitions().setAutoDim(true);
private final ContentObserver mAssistContentObserver = new ContentObserver(
@@ -414,6 +408,14 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
};
+ private final DeviceProvisionedController.DeviceProvisionedListener mUserSetupListener =
+ new DeviceProvisionedController.DeviceProvisionedListener() {
+ @Override
+ public void onUserSetupChanged() {
+ mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
+ }
+ };
+
@Inject
public NavigationBarFragment(AccessibilityManagerWrapper accessibilityManagerWrapper,
DeviceProvisionedController deviceProvisionedController, MetricsLogger metricsLogger,
@@ -481,6 +483,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
/* defaultValue = */ true);
DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener);
+
+ mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
+ mDeviceProvisionedController.addCallback(mUserSetupListener);
}
@Override
@@ -489,6 +494,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mNavigationModeController.removeListener(this);
mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
mContentResolver.unregisterContentObserver(mAssistContentObserver);
+ mDeviceProvisionedController.removeCallback(mUserSetupListener);
DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
}
@@ -535,8 +541,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
// Currently there is no accelerometer sensor on non-default display.
if (mIsOnDefaultDisplay) {
- mNavigationBarView.getRotateSuggestionButton().setListener(mRotationButtonListener);
-
final RotationButtonController rotationButtonController =
mNavigationBarView.getRotationButtonController();
rotationButtonController.addRotationCallback(mRotationWatcher);
@@ -1340,6 +1344,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
if (mAutoHideController != null) {
mAutoHideController.setNavigationBar(mAutoHideUiElement);
}
+ mNavigationBarView.setAutoHideController(autoHideController);
}
private boolean isTransientShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 0b4a2b69ffb3..e3cb105ba2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -131,6 +131,7 @@ public class NavigationBarView extends FrameLayout implements
private boolean mDeadZoneConsuming = false;
private final NavigationBarTransitions mBarTransitions;
private final OverviewProxyService mOverviewProxyService;
+ private AutoHideController mAutoHideController;
// performs manual animation in sync with layout transitions
private final NavTransitionListener mTransitionListener = new NavTransitionListener();
@@ -276,6 +277,15 @@ public class NavigationBarView extends FrameLayout implements
info.touchableRegion.setEmpty();
};
+ private final Consumer<Boolean> mRotationButtonListener = (visible) -> {
+ if (visible) {
+ // If the button will actually become visible and the navbar is about to hide,
+ // tell the statusbar to keep it around for longer
+ mAutoHideController.touchAutoHide();
+ }
+ notifyActiveTouchRegions();
+ };
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -313,7 +323,8 @@ public class NavigationBarView extends FrameLayout implements
mFloatingRotationButton = new FloatingRotationButton(context);
mRotationButtonController = new RotationButtonController(mLightContext,
mLightIconColor, mDarkIconColor,
- isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton);
+ isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
+ mRotationButtonListener);
mConfiguration = new Configuration();
mTmpLastConfiguration = new Configuration();
@@ -361,6 +372,10 @@ public class NavigationBarView extends FrameLayout implements
});
}
+ public void setAutoHideController(AutoHideController autoHideController) {
+ mAutoHideController = autoHideController;
+ }
+
public NavigationBarTransitions getBarTransitions() {
return mBarTransitions;
}
@@ -939,7 +954,15 @@ public class NavigationBarView extends FrameLayout implements
updateButtonLocation(getBackButton());
updateButtonLocation(getHomeButton());
updateButtonLocation(getRecentsButton());
- updateButtonLocation(getRotateSuggestionButton());
+ updateButtonLocation(getImeSwitchButton());
+ updateButtonLocation(getAccessibilityButton());
+ if (mFloatingRotationButton.isVisible()) {
+ View floatingRotationView = mFloatingRotationButton.getCurrentView();
+ floatingRotationView.getBoundsOnScreen(mTmpBounds);
+ mActiveRegion.op(mTmpBounds, Op.UNION);
+ } else {
+ updateButtonLocation(getRotateSuggestionButton());
+ }
mOverviewProxyService.onActiveNavBarRegionChanges(mActiveRegion);
}
@@ -1211,6 +1234,7 @@ public class NavigationBarView extends FrameLayout implements
dumpButton(pw, "rcnt", getRecentsButton());
dumpButton(pw, "rota", getRotateSuggestionButton());
dumpButton(pw, "a11y", getAccessibilityButton());
+ dumpButton(pw, "ime", getImeSwitchButton());
pw.println(" }");
pw.println(" mScreenOn: " + mScreenOn);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 9d3e915cad69..7bbe1c986249 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -26,7 +26,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -160,9 +160,9 @@ public class NotificationIconAreaController implements DarkReceiver,
}
}
- public void setupShelf(NotificationShelf shelf) {
- mShelfIcons = shelf.getShelfIcons();
- shelf.setCollapsedIcons(mNotificationIcons);
+ public void setupShelf(NotificationShelfController notificationShelfController) {
+ mShelfIcons = notificationShelfController.getShelfIcons();
+ notificationShelfController.setCollapsedIcons(mNotificationIcons);
}
public void onDensityOrFontScaleChanged(Context context) {
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 a87311a69ab5..6946346eee2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -86,6 +86,7 @@ import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
@@ -454,6 +455,7 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean mAnimatingQS;
private int mOldLayoutDirection;
+ private NotificationShelfController mNotificationShelfController;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@Override
@@ -858,7 +860,7 @@ public class NotificationPanelViewController extends PanelViewController {
float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
int notificationPadding = Math.max(
1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
- NotificationShelf shelf = mNotificationStackScroller.getNotificationShelf();
+ NotificationShelf shelf = mNotificationShelfController.getView();
float
shelfSize =
shelf.getVisibility() == View.GONE ? 0
@@ -3053,7 +3055,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
- NotificationShelf notificationShelf,
+ NotificationShelfController notificationShelfController,
NotificationIconAreaController notificationIconAreaController,
ScrimController scrimController) {
setStatusBar(statusBar);
@@ -3062,9 +3064,10 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScroller.setIconAreaController(notificationIconAreaController);
mNotificationStackScroller.setStatusBar(statusBar);
mNotificationStackScroller.setGroupManager(groupManager);
- mNotificationStackScroller.setShelf(notificationShelf);
+ mNotificationStackScroller.setShelfController(notificationShelfController);
mNotificationStackScroller.setScrimController(scrimController);
updateShowEmptyShadeView();
+ mNotificationShelfController = notificationShelfController;
}
public void showTransientIndication(int id) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
index 687efd34ee30..74d4eb175ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
@@ -20,9 +20,12 @@ import android.view.View;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import java.util.function.Consumer;
+
/** Interface of a rotation button that interacts {@link RotationButtonController}. */
interface RotationButton {
void setRotationButtonController(RotationButtonController rotationButtonController);
+ void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback);
View getCurrentView();
boolean show();
boolean hide();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
index b0630a649ffe..2f2e1f9a1f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
@@ -124,7 +124,8 @@ public class RotationButtonController {
}
RotationButtonController(Context context, @ColorInt int lightIconColor,
- @ColorInt int darkIconColor, RotationButton rotationButton) {
+ @ColorInt int darkIconColor, RotationButton rotationButton,
+ Consumer<Boolean> visibilityChangedCallback) {
mContext = context;
mLightIconColor = lightIconColor;
mDarkIconColor = darkIconColor;
@@ -139,6 +140,7 @@ public class RotationButtonController {
mTaskStackListener = new TaskStackListenerImpl();
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
+ mRotationButton.setVisibilityChangedCallback(visibilityChangedCallback);
}
void registerListeners() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index 08aeb0425f68..d63d445d8ba3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -23,6 +23,8 @@ import android.view.View;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
+import java.util.function.Consumer;
+
/** Containing logic for the rotation button in nav bar. */
public class RotationContextButton extends ContextualButton implements RotationButton {
public static final boolean DEBUG_ROTATION = false;
@@ -43,6 +45,18 @@ public class RotationContextButton extends ContextualButton implements RotationB
}
@Override
+ public void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback) {
+ setListener(new ContextButtonListener() {
+ @Override
+ public void onVisibilityChanged(ContextualButton button, boolean visible) {
+ if (visibilityChangedCallback != null) {
+ visibilityChangedCallback.accept(visible);
+ }
+ }
+ });
+ }
+
+ @Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
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 eb626280b494..c8fb4e3372c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -179,7 +179,6 @@ import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -189,7 +188,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.ScrimView;
@@ -1029,7 +1028,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController);
mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController);
inflateShelf();
- mNotificationIconAreaController.setupShelf(mNotificationShelf);
+ mNotificationIconAreaController.setupShelf(mNotificationShelfController);
mNotificationPanelViewController.setOnReinflationListener(
mNotificationIconAreaController::initAodIcons);
mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
@@ -1147,7 +1146,8 @@ public class StatusBar extends SystemUI implements DemoMode,
});
mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
- mNotificationPanelViewController.initDependencies(this, mGroupManager, mNotificationShelf,
+ mNotificationPanelViewController.initDependencies(this, mGroupManager,
+ mNotificationShelfController,
mNotificationIconAreaController, mScrimController);
BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
@@ -1310,7 +1310,7 @@ public class StatusBar extends SystemUI implements DemoMode,
this /* statusBar */, mShadeController, mCommandQueue, mInitController,
mNotificationInterruptStateProvider);
- mNotificationShelf.setOnActivatedListener(mPresenter);
+ mNotificationShelfController.setOnActivatedListener(mPresenter);
mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController);
mNotificationActivityStarter =
@@ -1386,8 +1386,9 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void inflateShelf() {
- mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller);
- mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
+ mNotificationShelfController = mSuperStatusBarViewFactory
+ .getNotificationShelfController(mStackScroller);
+ mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener);
}
@Override
@@ -4085,8 +4086,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Optional<Recents> mRecentsOptional;
- protected NotificationShelf mNotificationShelf;
- protected EmptyShadeView mEmptyShadeView;
+ protected NotificationShelfController mNotificationShelfController;
private final Lazy<AssistManager> mAssistManagerLazy;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
index 87b3956060f3..bbab6253a4d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
@@ -40,5 +40,9 @@ abstract class AudioActivityObserver {
mListener = listener;
}
+ abstract void start();
+
+ abstract void stop();
+
abstract Set<String> getActivePackages();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 8e4e12358836..e3eed35f0483 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -22,12 +22,12 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
import android.annotation.IntDef;
import android.annotation.UiThread;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.provider.Settings;
import android.text.TextUtils;
@@ -65,11 +65,13 @@ public class AudioRecordingDisclosureBar implements
// CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
+ private static final String ENABLE_FLAG = "sysui_mic_disclosure_enable";
private static final String EXEMPT_PACKAGES_LIST = "sysui_mic_disclosure_exempt";
private static final String FORCED_PACKAGES_LIST = "sysui_mic_disclosure_forced";
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"STATE_"}, value = {
+ STATE_STOPPED,
STATE_NOT_SHOWN,
STATE_APPEARING,
STATE_SHOWN,
@@ -80,6 +82,7 @@ public class AudioRecordingDisclosureBar implements
})
public @interface State {}
+ private static final int STATE_STOPPED = -1;
private static final int STATE_NOT_SHOWN = 0;
private static final int STATE_APPEARING = 1;
private static final int STATE_SHOWN = 2;
@@ -90,10 +93,9 @@ public class AudioRecordingDisclosureBar implements
private static final int ANIMATION_DURATION = 600;
private static final int MAXIMIZED_DURATION = 3000;
- private static final int PULSE_BIT_DURATION = 1000;
- private static final float PULSE_SCALE = 1.25f;
private final Context mContext;
+ private boolean mIsEnabledInSettings;
private View mIndicatorView;
private View mIconTextsContainer;
@@ -104,13 +106,13 @@ public class AudioRecordingDisclosureBar implements
private TextView mTextView;
private boolean mIsLtr;
- @State private int mState = STATE_NOT_SHOWN;
+ @State private int mState = STATE_STOPPED;
/**
* Array of the observers that monitor different aspects of the system, such as AppOps and
* microphone foreground services
*/
- private final AudioActivityObserver[] mAudioActivityObservers;
+ private AudioActivityObserver[] mAudioActivityObservers;
/**
* Whether the indicator should expand and show the recording application's label.
* If disabled ({@code false}) the "minimized" ({@link #STATE_MINIMIZED}) indicator would appear
@@ -144,6 +146,7 @@ public class AudioRecordingDisclosureBar implements
public AudioRecordingDisclosureBar(Context context) {
mContext = context;
+ // Loading configs
mRevealRecordingPackages = mContext.getResources().getBoolean(
R.bool.audio_recording_disclosure_reveal_packages);
mExemptPackages = new ArraySet<>(
@@ -152,10 +155,52 @@ public class AudioRecordingDisclosureBar implements
mExemptPackages.addAll(Arrays.asList(getGlobalStringArray(EXEMPT_PACKAGES_LIST)));
mExemptPackages.removeAll(Arrays.asList(getGlobalStringArray(FORCED_PACKAGES_LIST)));
- mAudioActivityObservers = new AudioActivityObserver[]{
- new RecordAudioAppOpObserver(mContext, this),
- new MicrophoneForegroundServicesObserver(mContext, this),
- };
+ // Check setting, and start if enabled
+ mIsEnabledInSettings = checkIfEnabledInSettings();
+ registerSettingsObserver();
+ if (mIsEnabledInSettings) {
+ start();
+ }
+ }
+
+ @UiThread
+ private void start() {
+ if (mState != STATE_STOPPED) {
+ return;
+ }
+ mState = STATE_NOT_SHOWN;
+
+ if (mAudioActivityObservers == null) {
+ mAudioActivityObservers = new AudioActivityObserver[]{
+ new RecordAudioAppOpObserver(mContext, this),
+ new MicrophoneForegroundServicesObserver(mContext, this),
+ };
+ }
+
+ for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
+ mAudioActivityObservers[i].start();
+ }
+ }
+
+ @UiThread
+ private void stop() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+ mState = STATE_STOPPED;
+
+ for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
+ mAudioActivityObservers[i].stop();
+ }
+
+ // Remove the view if shown.
+ if (mState != STATE_NOT_SHOWN) {
+ removeIndicatorView();
+ }
+
+ // Clean up the state.
+ mSessionNotifiedPackages.clear();
+ mPendingNotificationPackages.clear();
}
@UiThread
@@ -213,7 +258,6 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hideIndicatorIfNeeded() {
- if (DEBUG) Log.d(TAG, "hideIndicatorIfNeeded");
// If not MINIMIZED, will check whether the indicator should be hidden when the indicator
// comes to the STATE_MINIMIZED eventually.
if (mState != STATE_MINIMIZED) return;
@@ -222,7 +266,6 @@ public class AudioRecordingDisclosureBar implements
for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) {
for (String activePackage : mAudioActivityObservers[index].getActivePackages()) {
if (mExemptPackages.contains(activePackage)) continue;
- if (DEBUG) Log.d(TAG, " - there are still ongoing activities");
return;
}
}
@@ -235,7 +278,7 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void show(String packageName) {
if (DEBUG) {
- Log.d(TAG, "Showing indicator for " + packageName);
+ Log.d(TAG, "Showing indicator");
}
mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
@@ -286,6 +329,10 @@ public class AudioRecordingDisclosureBar implements
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
// Remove the observer
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
@@ -306,13 +353,16 @@ public class AudioRecordingDisclosureBar implements
@Override
public void onAnimationStart(Animator animation,
boolean isReverse) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
// Indicator is INVISIBLE at the moment, change it.
mIndicatorView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
- startPulsatingAnimation();
if (mRevealRecordingPackages) {
onExpanded();
} else {
@@ -345,9 +395,6 @@ public class AudioRecordingDisclosureBar implements
assertRevealingRecordingPackages();
final String label = getApplicationLabel(packageName);
- if (DEBUG) {
- Log.d(TAG, "Expanding for " + packageName + " (" + label + ")...");
- }
mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
final AnimatorSet set = new AnimatorSet();
@@ -373,7 +420,6 @@ public class AudioRecordingDisclosureBar implements
private void minimize() {
assertRevealingRecordingPackages();
- if (DEBUG) Log.d(TAG, "Minimizing...");
final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth();
final AnimatorSet set = new AnimatorSet();
set.playTogether(
@@ -396,7 +442,9 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hide() {
- if (DEBUG) Log.d(TAG, "Hiding...");
+ if (DEBUG) {
+ Log.d(TAG, "Hide indicator");
+ }
final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth()
- (int) mIconTextsContainer.getTranslationX());
final AnimatorSet set = new AnimatorSet();
@@ -418,9 +466,12 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onExpanded() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
assertRevealingRecordingPackages();
- if (DEBUG) Log.d(TAG, "Expanded");
mState = STATE_SHOWN;
mIndicatorView.postDelayed(this::minimize, MAXIMIZED_DURATION);
@@ -428,7 +479,10 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onMinimized() {
- if (DEBUG) Log.d(TAG, "Minimized");
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
mState = STATE_MINIMIZED;
if (mRevealRecordingPackages) {
@@ -443,8 +497,21 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onHidden() {
- if (DEBUG) Log.d(TAG, "Hidden");
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+ removeIndicatorView();
+ mState = STATE_NOT_SHOWN;
+
+ // Check if anybody started recording while we were in STATE_DISAPPEARING
+ if (!mPendingNotificationPackages.isEmpty()) {
+ // There is a new application that started recording, tell the user about it.
+ show(mPendingNotificationPackages.poll());
+ }
+ }
+
+ private void removeIndicatorView() {
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
windowManager.removeView(mIndicatorView);
@@ -456,28 +523,6 @@ public class AudioRecordingDisclosureBar implements
mTextsContainers = null;
mTextView = null;
mBgEnd = null;
-
- mState = STATE_NOT_SHOWN;
-
- // Check if anybody started recording while we were in STATE_DISAPPEARING
- if (!mPendingNotificationPackages.isEmpty()) {
- // There is a new application that started recording, tell the user about it.
- show(mPendingNotificationPackages.poll());
- }
- }
-
- @UiThread
- private void startPulsatingAnimation() {
- final View pulsatingView = mIconTextsContainer.findViewById(R.id.pulsating_circle);
- final ObjectAnimator animator =
- ObjectAnimator.ofPropertyValuesHolder(
- pulsatingView,
- PropertyValuesHolder.ofFloat(View.SCALE_X, PULSE_SCALE),
- PropertyValuesHolder.ofFloat(View.SCALE_Y, PULSE_SCALE));
- animator.setDuration(PULSE_BIT_DURATION);
- animator.setRepeatCount(ObjectAnimator.INFINITE);
- animator.setRepeatMode(ObjectAnimator.REVERSE);
- animator.start();
}
private String[] getGlobalStringArray(String setting) {
@@ -504,4 +549,33 @@ public class AudioRecordingDisclosureBar implements
DEBUG ? new RuntimeException("Should not be called") : null);
}
}
+
+ private boolean checkIfEnabledInSettings() {
+ // 0 = disabled, everything else = enabled. Enabled by default.
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ ENABLE_FLAG, 1) != 0;
+ }
+
+ private void registerSettingsObserver() {
+ final ContentObserver contentObserver = new ContentObserver(
+ mContext.getMainThreadHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ if (mIsEnabledInSettings == checkIfEnabledInSettings()) {
+ // Nothing changed as we know it - ignore.
+ return;
+ }
+
+ // Things changed: flip the flag.
+ mIsEnabledInSettings = !mIsEnabledInSettings;
+ if (mIsEnabledInSettings) {
+ start();
+ } else {
+ stop();
+ }
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(ENABLE_FLAG), false, contentObserver);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
index 1ede88a26020..8caf95fb48f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
@@ -30,7 +30,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -41,9 +40,8 @@ import java.util.Set;
*/
class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
private static final String TAG = "MicrophoneForegroundServicesObserver";
- private static final boolean ENABLED = true;
- private final IActivityManager mActivityManager;
+ private IActivityManager mActivityManager;
/**
* A dictionary that maps PIDs to the package names. We only keep track of the PIDs that are
* "active" (those that are running FGS with FOREGROUND_SERVICE_TYPE_MICROPHONE flag).
@@ -60,7 +58,10 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
MicrophoneForegroundServicesObserver(Context context,
OnAudioActivityStateChangeListener listener) {
super(context, listener);
+ }
+ @Override
+ void start() {
mActivityManager = ActivityManager.getService();
try {
mActivityManager.registerProcessObserver(mProcessObserver);
@@ -70,8 +71,19 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
}
@Override
+ void stop() {
+ try {
+ mActivityManager.unregisterProcessObserver(mProcessObserver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't unregister process observer", e);
+ }
+ mActivityManager = null;
+ mPackageToProcessCount.clear();
+ }
+
+ @Override
Set<String> getActivePackages() {
- return ENABLED ? mPackageToProcessCount.keySet() : Collections.emptySet();
+ return mPackageToProcessCount.keySet();
}
@UiThread
@@ -141,13 +153,12 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
@UiThread
private void notifyPackageStateChanged(String packageName, boolean active) {
- if (active) {
- if (DEBUG) Log.d(TAG, "New microphone fgs detected, package=" + packageName);
- } else {
- if (DEBUG) Log.d(TAG, "Microphone fgs is gone, package=" + packageName);
+ if (DEBUG) {
+ Log.d(TAG, (active ? "New microphone fgs detected" : "Microphone fgs is gone")
+ + ", package=" + packageName);
}
- if (ENABLED) mListener.onAudioActivityStateChange(active, packageName);
+ mListener.onAudioActivityStateChange(active, packageName);
}
@UiThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
index b5b1c2b3018a..9a2b4a93ac89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
@@ -42,14 +42,33 @@ class RecordAudioAppOpObserver extends AudioActivityObserver implements
RecordAudioAppOpObserver(Context context, OnAudioActivityStateChangeListener listener) {
super(context, listener);
+ }
+
+ @Override
+ void start() {
+ if (DEBUG) {
+ Log.d(TAG, "Start");
+ }
// Register AppOpsManager callback
- final AppOpsManager appOpsManager = (AppOpsManager) mContext.getSystemService(
- Context.APP_OPS_SERVICE);
- appOpsManager.startWatchingActive(
- new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
- mContext.getMainExecutor(),
- this);
+ mContext.getSystemService(AppOpsManager.class)
+ .startWatchingActive(
+ new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
+ mContext.getMainExecutor(),
+ this);
+ }
+
+ @Override
+ void stop() {
+ if (DEBUG) {
+ Log.d(TAG, "Stop");
+ }
+
+ // Unregister AppOpsManager callback
+ mContext.getSystemService(AppOpsManager.class).stopWatchingActive(this);
+
+ // Clean up state
+ mActiveAudioRecordingPackages.clear();
}
@UiThread
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 551b7b41212a..d16bedcad960 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -23,6 +23,7 @@ import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
+import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.dagger.SystemUIRootComponent;
@@ -126,11 +127,6 @@ public class InjectionInflationController {
NotificationStackScrollLayout createNotificationStackScrollLayout();
/**
- * Creates the Shelf.
- */
- NotificationShelf creatNotificationShelf();
-
- /**
* Creates the KeyguardSliceView.
*/
KeyguardSliceView createKeyguardSliceView();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 3455ff47de8d..4b119dd7e176 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -150,6 +150,8 @@ public class VolumeDialogImpl implements VolumeDialog,
private boolean mShowing;
private boolean mShowA11yStream;
+ private final boolean mShowLowMediaVolumeIcon;
+
private int mActiveStream;
private int mPrevActiveStream;
private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE;
@@ -166,7 +168,7 @@ public class VolumeDialogImpl implements VolumeDialog,
public VolumeDialogImpl(Context context) {
mContext =
- new ContextThemeWrapper(context, R.style.qs_theme);
+ new ContextThemeWrapper(context, R.style.volume_dialog_theme);
mController = Dependency.get(VolumeDialogController.class);
mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -175,6 +177,8 @@ public class VolumeDialogImpl implements VolumeDialog,
mShowActiveStreamOnly = showActiveStreamOnly();
mHasSeenODICaptionsTooltip =
Prefs.getBoolean(context, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false);
+ mShowLowMediaVolumeIcon =
+ mContext.getResources().getBoolean(R.bool.config_showLowMediaVolumeIcon);
}
@Override
@@ -421,6 +425,7 @@ public class VolumeDialogImpl implements VolumeDialog,
row.dndIcon = row.view.findViewById(R.id.dnd_icon);
row.slider = row.view.findViewById(R.id.volume_row_slider);
row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
+ row.number = row.view.findViewById(R.id.volume_number);
row.anim = null;
@@ -1024,19 +1029,28 @@ public class VolumeDialogImpl implements VolumeDialog,
final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
row.icon.setEnabled(iconEnabled);
row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
- final int iconRes =
- isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
- : isRingSilent || zenMuted ? row.iconMuteRes
- : ss.routedToBluetooth
- ? isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute
- : R.drawable.ic_volume_media_bt
- : isStreamMuted(ss) ? row.iconMuteRes : row.iconRes;
+ final int iconRes;
+ if (isRingVibrate) {
+ iconRes = R.drawable.ic_volume_ringer_vibrate;
+ } else if (isRingSilent || zenMuted) {
+ iconRes = row.iconMuteRes;
+ } else if (ss.routedToBluetooth) {
+ iconRes = isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute
+ : R.drawable.ic_volume_media_bt;
+ } else if (isStreamMuted(ss)) {
+ iconRes = row.iconMuteRes;
+ } else {
+ iconRes = mShowLowMediaVolumeIcon && ss.level * 2 < (ss.levelMax + ss.levelMin)
+ ? R.drawable.ic_volume_media_low : row.iconRes;
+ }
+
row.icon.setImageResource(iconRes);
row.iconState =
iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
: (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
? Events.ICON_STATE_MUTE
- : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
+ : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes
+ || iconRes == R.drawable.ic_volume_media_low)
? Events.ICON_STATE_UNMUTE
: Events.ICON_STATE_UNKNOWN;
if (iconEnabled) {
@@ -1090,6 +1104,7 @@ public class VolumeDialogImpl implements VolumeDialog,
final int vlevel = row.ss.muted && (!isRingStream && !zenMuted) ? 0
: row.ss.level;
updateVolumeRowSliderH(row, enableSlider, vlevel);
+ if (row.number != null) row.number.setText(Integer.toString(vlevel));
}
private boolean isStreamMuted(final StreamState streamState) {
@@ -1115,6 +1130,10 @@ public class VolumeDialogImpl implements VolumeDialog,
row.icon.setImageTintList(tint);
row.icon.setImageAlpha(alpha);
row.cachedTint = tint;
+ if (row.number != null) {
+ row.number.setTextColor(tint);
+ row.number.setAlpha(alpha);
+ }
}
private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) {
@@ -1346,7 +1365,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private final class CustomDialog extends Dialog implements DialogInterface {
public CustomDialog(Context context) {
- super(context, R.style.qs_theme);
+ super(context, R.style.volume_dialog_theme);
}
@Override
@@ -1458,6 +1477,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private TextView header;
private ImageButton icon;
private SeekBar slider;
+ private TextView number;
private int stream;
private StreamState ss;
private long userAttempt; // last user-driven slider change
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index b7589534a770..1538a32ecf8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -60,6 +60,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -70,7 +71,9 @@ import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -79,8 +82,10 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
@@ -90,6 +95,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
+import com.android.systemui.util.InjectionInflationController;
import com.google.common.collect.ImmutableList;
@@ -174,6 +180,8 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private ShadeController mShadeController;
@Mock
+ private NotificationShelfComponent mNotificationShelfComponent;
+ @Mock
private NotifPipeline mNotifPipeline;
@Mock
private FeatureFlags mFeatureFlagsOldPipeline;
@@ -185,11 +193,14 @@ public class BubbleControllerTest extends SysuiTestCase {
private IStatusBarService mStatusBarService;
@Mock
private LauncherApps mLauncherApps;
+ @Mock private LockscreenLockIconController mLockIconController;
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -199,6 +210,23 @@ public class BubbleControllerTest extends SysuiTestCase {
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
+ new NotificationShelfComponent.Builder() {
+ @Override
+ public NotificationShelfComponent.Builder notificationShelf(
+ NotificationShelf view) {
+ return this;
+ }
+
+ @Override
+ public NotificationShelfComponent build() {
+ return mNotificationShelfComponent;
+ }
+ },
+ mLockIconController);
+
+ // Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 43bf19111049..0e7cb79ec266 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -58,6 +58,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -66,7 +67,9 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
@@ -75,7 +78,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
@@ -88,6 +91,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Ignore;
@@ -168,7 +172,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
@Mock
private ShadeController mShadeController;
@Mock
- private NotificationRowComponent mNotificationRowComponent;
+ private NotificationShelfComponent mNotificationShelfComponent;
@Mock
private NotifPipeline mNotifPipeline;
@Mock
@@ -185,6 +189,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setUp() throws Exception {
@@ -195,6 +200,22 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
+ new NotificationShelfComponent.Builder() {
+ @Override
+ public NotificationShelfComponent.Builder notificationShelf(
+ NotificationShelf view) {
+ return this;
+ }
+
+ @Override
+ public NotificationShelfComponent build() {
+ return mNotificationShelfComponent;
+ }
+ },
+ mLockIconController);
+
// Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
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 694f51be4e30..f4c07004f632 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -24,14 +24,13 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.app.Instrumentation;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.wm.shell.common.DisplayController;
@@ -46,12 +45,13 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedGestureHandlerTest extends OneHandedTestCase {
- Instrumentation mInstrumentation;
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedManagerImpl mOneHandedManagerImpl;
@Mock
+ CommandQueue mCommandQueue;
+ @Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@@ -62,12 +62,13 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = Mockito.spy(new OneHandedGestureHandler(
mContext, mMockDisplayController, mMockNavigationModeController));
- mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(),
+ mOneHandedManagerImpl = new OneHandedManagerImpl(
+ getContext(),
+ mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
@@ -100,6 +101,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
mOneHandedManagerImpl.setOneHandedEnabled(false);
+ mOneHandedManagerImpl.setSwipeToNotificationEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
index 3418ebf75e0c..763f6e4fe94b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
@@ -33,6 +33,7 @@ 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;
@@ -51,6 +52,8 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
OneHandedTimeoutHandler mTimeoutHandler;
@Mock
+ CommandQueue mCommandQueue;
+ @Mock
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@@ -67,7 +70,9 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDisplay = mContext.getDisplay();
- mOneHandedManagerImpl = new OneHandedManagerImpl(getContext(),
+ mOneHandedManagerImpl = new OneHandedManagerImpl(
+ getContext(),
+ mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
@@ -94,14 +99,14 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testRegisterOrganizer() {
- verify(mMockDisplayAreaOrganizer, times(1)).registerOrganizer(anyInt());
+ verify(mMockDisplayAreaOrganizer).registerOrganizer(anyInt());
}
@Test
public void testStartOneHanded() {
mOneHandedManagerImpl.startOneHanded();
- verify(mMockDisplayAreaOrganizer, times(1)).scheduleOffset(anyInt(), anyInt());
+ verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
}
@Test
@@ -121,7 +126,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
public void testStopOneHanded_shouldRemoveTimer() {
mOneHandedManagerImpl.stopOneHanded();
- verify(mTimeoutHandler, times(1)).removeTimer();
+ verify(mTimeoutHandler).removeTimer();
}
@Test
@@ -129,7 +134,14 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
final boolean enabled = true;
mOneHandedManagerImpl.setOneHandedEnabled(enabled);
- verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled);
+ verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
}
+ @Test
+ public void testUpdateSwipeToNotificationIsEnabled() {
+ final boolean enabled = true;
+ mOneHandedManagerImpl.setSwipeToNotificationEnabled(enabled);
+
+ verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java
index c157ae651cd5..f81d047b0f0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java
@@ -104,4 +104,10 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase {
ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS,
ONE_HANDED_TIMEOUT_LONG_IN_SECONDS);
}
+
+ @Test
+ public void testGetSettingsSwipeToNotificationEnabled() {
+ assertThat(mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ mContentResolver)).isAnyOf(true, false);
+ }
}
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 befa42a0acc9..04ebf25e1b49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java
@@ -32,6 +32,7 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
static boolean sOrigEnabled;
static boolean sOrigTapsAppToExitEnabled;
static int sOrigTimeout;
+ static boolean sOrigSwipeToNotification;
@Before
public void setupSettings() {
@@ -41,12 +42,16 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
getContext().getContentResolver());
sOrigTapsAppToExitEnabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
getContext().getContentResolver());
+ sOrigSwipeToNotification = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ getContext().getContentResolver());
Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.TAPS_APP_TO_EXIT, 1);
+ Settings.Secure.putInt(getContext().getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
}
@After
@@ -57,6 +62,9 @@ public abstract class OneHandedTestCase extends SysuiTestCase {
Settings.Secure.ONE_HANDED_MODE_TIMEOUT, sOrigTimeout);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.TAPS_APP_TO_EXIT, sOrigTapsAppToExitEnabled ? 1 : 0);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ sOrigSwipeToNotification ? 1 : 0);
}
}
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 fdb28d3d43b5..15881a2e7c18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -22,14 +22,13 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.app.Instrumentation;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.wm.shell.common.DisplayController;
@@ -44,12 +43,13 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTouchHandlerTest extends OneHandedTestCase {
- Instrumentation mInstrumentation;
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedManagerImpl mOneHandedManagerImpl;
@Mock
+ CommandQueue mCommandQueue;
+ @Mock
DisplayController mMockDisplayController;
@Mock
NavigationModeController mMockNavigationModeController;
@@ -61,11 +61,12 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
mMockNavigationModeController);
- mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(),
+ mOneHandedManagerImpl = new OneHandedManagerImpl(
+ getContext(),
+ mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
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 f4aa00eaf02f..f2b77a0a936b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -19,14 +19,13 @@ package com.android.systemui.onehanded;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.app.Instrumentation;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.wm.shell.common.DisplayController;
@@ -41,12 +40,13 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
- Instrumentation mInstrumentation;
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedManagerImpl mOneHandedManagerImpl;
@Mock
+ CommandQueue mCommandQueue;
+ @Mock
DisplayController mMockDisplayController;
@Mock
NavigationModeController mMockNavigationModeController;
@@ -58,12 +58,13 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTouchHandler = new OneHandedTouchHandler();
mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
mMockNavigationModeController);
- mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(),
+ mOneHandedManagerImpl = new OneHandedManagerImpl(
+ getContext(),
+ mCommandQueue,
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
index ffedb07b8db4..6db2679ea116 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
@@ -28,7 +28,6 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.statusbar.CommandQueue;
@@ -53,8 +52,6 @@ public class OneHandedUITest extends OneHandedTestCase {
@Mock
OneHandedManagerImpl mMockOneHandedManagerImpl;
@Mock
- DumpManager mMockDumpManager;
- @Mock
OneHandedSettingsUtil mMockSettingsUtil;
@Mock
OneHandedTimeoutHandler mMockTimeoutHandler;
@@ -68,7 +65,6 @@ public class OneHandedUITest extends OneHandedTestCase {
mOneHandedUI = new OneHandedUI(mContext,
mCommandQueue,
mMockOneHandedManagerImpl,
- mMockDumpManager,
mMockSettingsUtil,
mScreenLifecycle);
mOneHandedUI.start();
@@ -168,6 +164,18 @@ public class OneHandedUITest extends OneHandedTestCase {
OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
}
+ @Test
+ public void tesSettingsObserver_updateSwipeToNotification() {
+ // Bypass test if device not support one-handed mode
+ if (!mIsSupportOneHandedMode) {
+ return;
+ }
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
+
+ verify(mMockOneHandedManagerImpl).setSwipeToNotificationEnabled(true);
+ }
+
@Ignore("Clarifying do not receive callback")
@Test
public void testKeyguardBouncerShowing_shouldStopOneHanded() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index ddac2ecbd6eb..85701c24f7d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -64,6 +64,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -197,7 +198,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class));
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+ NotificationShelfController notificationShelfController =
+ mock(NotificationShelfController.class);
NotificationShelf notificationShelf = mock(NotificationShelf.class);
+ when(notificationShelfController.getView()).thenReturn(notificationShelf);
when(mNotificationSectionsManager.createSectionsForBuckets()).thenReturn(
new NotificationSection[]{
mNotificationSection
@@ -230,7 +234,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture());
mUserChangedListener = userChangedCaptor.getValue();
mStackScroller = spy(mStackScrollerInternal);
- mStackScroller.setShelf(notificationShelf);
+ mStackScroller.setShelfController(notificationShelfController);
mStackScroller.setStatusBar(mBar);
mStackScroller.setScrimController(mock(ScrimController.class));
mStackScroller.setGroupManager(mGroupManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
index f21235c12cde..f66524114292 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
@@ -60,7 +60,7 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
final View view = new View(mContext);
mRotationButton = mock(RotationButton.class);
mRotationButtonController = spy(new RotationButtonController(mContext, 0, 0,
- mRotationButton));
+ mRotationButton, (visibility) -> {}));
final KeyButtonDrawable kbd = mock(KeyButtonDrawable.class);
doReturn(view).when(mRotationButton).getCurrentView();
doReturn(true).when(mRotationButton).acceptRotationProposal();
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 c7434f6fd95f..bf4ccd22effd 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
@@ -63,7 +63,7 @@ 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.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -115,7 +115,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private HeadsUpManagerPhone mHeadsUpManager;
@Mock
- private NotificationShelf mNotificationShelf;
+ private NotificationShelfController mNotificationShelfController;
@Mock
private NotificationGroupManager mGroupManager;
@Mock
@@ -246,7 +246,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mBiometricUnlockController, mStatusBarKeyguardViewManager,
() -> mKeyguardClockSwitchController);
mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
- mNotificationShelf, mNotificationAreaController, mScrimController);
+ mNotificationShelfController, mNotificationAreaController, mScrimController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelViewController.setBar(mPanelBar);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
index 4b6bbac051e0..75c819bb0ced 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
@@ -18,33 +18,40 @@ package com.android.networkstack.tethering
import android.app.Notification
import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
+import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.content.res.Resources
import android.net.ConnectivityManager.TETHERING_WIFI
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
import android.os.UserHandle
+import android.provider.Settings
import android.telephony.TelephonyManager
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.android.internal.util.test.BroadcastInterceptingContext
+import com.android.networkstack.tethering.TetheringNotificationUpdater.ACTION_DISABLE_TETHERING
import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.ROAMING_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.VERIZON_CARRIER_ID
+import com.android.networkstack.tethering.TetheringNotificationUpdater.getSettingsPackageName
import com.android.testutils.waitForIdle
import org.junit.After
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Test
@@ -87,12 +94,17 @@ class TetheringNotificationUpdaterTest {
// every test but should always be initialized before use (or the test should crash).
private lateinit var context: TestContext
private lateinit var notificationUpdater: TetheringNotificationUpdater
+
+ // Initializing the following members depends on initializing some of the mocks and
+ // is more logically done in setup().
private lateinit var fakeTetheringThread: HandlerThread
private val ROAMING_CAPABILITIES = NetworkCapabilities()
private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING)
private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general
private val TIMEOUT_MS = 500L
+ private val ACTIVITY_PENDING_INTENT = 0
+ private val BROADCAST_PENDING_INTENT = 1
private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) {
override fun createContextAsUser(user: UserHandle, flags: Int) =
@@ -146,10 +158,43 @@ class TetheringNotificationUpdaterTest {
fakeTetheringThread.quitSafely()
}
+ private fun verifyActivityPendingIntent(intent: Intent, flags: Int) {
+ // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
+ // the flag in creating arguments). If the described PendingIntent does not already exist,
+ // getActivity() will return null instead of PendingIntent object.
+ val pi = PendingIntent.getActivity(
+ context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
+ 0 /* requestCode */,
+ intent,
+ flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE,
+ null /* options */)
+ assertNotNull("Activity PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
+ }
+
+ private fun verifyBroadcastPendingIntent(intent: Intent, flags: Int) {
+ // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
+ // the flag in creating arguments). If the described PendingIntent does not already exist,
+ // getBroadcast() will return null instead of PendingIntent object.
+ val pi = PendingIntent.getBroadcast(
+ context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
+ 0 /* requestCode */,
+ intent,
+ flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE)
+ assertNotNull("Broadcast PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
+ }
+
private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE)
private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT)
- private fun verifyNotification(iconId: Int, title: String, text: String, id: Int) {
+ private fun verifyNotification(
+ iconId: Int,
+ title: String,
+ text: String,
+ id: Int,
+ intentSenderType: Int,
+ intent: Intent,
+ flags: Int
+ ) {
verify(notificationManager, never()).cancel(any(), eq(id))
val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
@@ -161,6 +206,11 @@ class TetheringNotificationUpdaterTest {
assertEquals(title, notification.title())
assertEquals(text, notification.text())
+ when (intentSenderType) {
+ ACTIVITY_PENDING_INTENT -> verifyActivityPendingIntent(intent, flags)
+ BROADCAST_PENDING_INTENT -> verifyBroadcastPendingIntent(intent, flags)
+ }
+
reset(notificationManager)
}
@@ -176,6 +226,10 @@ class TetheringNotificationUpdaterTest {
@Test
fun testRestrictedNotification() {
+ val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
+ .setPackage(getSettingsPackageName(context.packageManager))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -183,7 +237,7 @@ class TetheringNotificationUpdaterTest {
// User restrictions on. Show restricted notification.
notificationUpdater.notifyTetheringDisabledByRestriction()
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID)
+ RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// User restrictions off. Clear notification.
notificationUpdater.tetheringRestrictionLifted()
@@ -196,7 +250,7 @@ class TetheringNotificationUpdaterTest {
// User restrictions on again. Show restricted notification.
notificationUpdater.notifyTetheringDisabledByRestriction()
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID)
+ RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
}
val MAX_BACKOFF_MS = 200L
@@ -234,6 +288,8 @@ class TetheringNotificationUpdaterTest {
@Test
fun testNoUpstreamNotification() {
+ val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -246,7 +302,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// Same capabilities changed. Nothing happened.
notificationUpdater.onUpstreamCapabilitiesChanged(null)
@@ -260,7 +317,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// No downstream.
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
@@ -305,6 +363,11 @@ class TetheringNotificationUpdaterTest {
@Test
fun testRoamingNotification() {
+ val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
+ val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
+ .setPackage(getSettingsPackageName(context.packageManager))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -316,7 +379,7 @@ class TetheringNotificationUpdaterTest {
// Upstream capabilities changed to roaming state. Show roaming notification.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID)
+ ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// Same capabilities change. Nothing happened.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
@@ -329,14 +392,15 @@ class TetheringNotificationUpdaterTest {
// Upstream capabilities changed to roaming state again. Show roaming notification.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID)
+ ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// No upstream. Clear roaming notification and show no upstream notification.
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// No downstream.
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
@@ -347,7 +411,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// Set R.bool.config_upstream_roaming_notification to false and change upstream
// network to roaming state again. No roaming notification.
@@ -363,8 +428,7 @@ class TetheringNotificationUpdaterTest {
val testSettingsPackageName = "com.android.test.settings"
val pm = mock(PackageManager::class.java)
doReturn(null).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(defaultSettingsPackageName,
- TetheringNotificationUpdater.getSettingsPackageName(pm))
+ assertEquals(defaultSettingsPackageName, getSettingsPackageName(pm))
val resolveInfo = ResolveInfo().apply {
activityInfo = ActivityInfo().apply {
@@ -375,7 +439,6 @@ class TetheringNotificationUpdaterTest {
}
}
doReturn(resolveInfo).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(testSettingsPackageName,
- TetheringNotificationUpdater.getSettingsPackageName(pm))
+ assertEquals(testSettingsPackageName, getSettingsPackageName(pm))
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index e1baefed4425..c45da8668087 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -609,6 +609,9 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendHoverExitDelayed.cancel();
if (mGestureDetector.isMultiFingerGesturesEnabled()
&& mGestureDetector.isTwoFingerPassthroughEnabled()) {
+ if (pointerIndex < 0) {
+ return;
+ }
final float deltaX =
mReceivedPointerTracker.getReceivedPointerDownX(pointerId)
- rawEvent.getX(pointerIndex);
@@ -966,25 +969,32 @@ public class TouchExplorer extends BaseEventStreamTransformation
final float secondPtrX = event.getX(1);
final float secondPtrY = event.getY(1);
final int secondPtrId = event.getPointerId(1);
- float draggingX;
- float draggingY;
+ float draggingX = firstPtrX;
+ float draggingY = firstPtrY;
+ if (mDraggingPointerId != INVALID_POINTER_ID) {
+ // Just use the coordinates of the dragging pointer.
+ int pointerIndex = event.findPointerIndex(mDraggingPointerId);
+ if (pointerIndex >= 0) {
+ draggingX = event.getX(pointerIndex);
+ draggingY = event.getY(pointerIndex);
+ } else {
+ // We've lost track of the dragging pointer. Try to recover by invalidating it.
+ // We'll the drop into the code below to choose a new one.
+ mDraggingPointerId = INVALID_POINTER_ID;
+ }
+ }
+ // Not quite an else, since the above code can invalidate the pointer
if (mDraggingPointerId == INVALID_POINTER_ID) {
// The goal is to use the coordinates of the finger that is closest to its closest edge.
if (getDistanceToClosestEdge(firstPtrX, firstPtrY)
< getDistanceToClosestEdge(secondPtrX, secondPtrY)) {
- draggingX = firstPtrX;
- draggingY = firstPtrY;
+ // X and Y initialized to firstPtrX and Y was right
mDraggingPointerId = firstPtrId;
} else {
draggingX = secondPtrX;
draggingY = secondPtrY;
mDraggingPointerId = secondPtrId;
}
- } else {
- // Just use the coordinates of the dragging pointer.
- int pointerIndex = event.findPointerIndex(mDraggingPointerId);
- draggingX = event.getX(pointerIndex);
- draggingY = event.getY(pointerIndex);
}
event.setLocation(draggingX, draggingY);
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1c3116699b2d..a92d334a94fa 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -27,6 +27,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -214,7 +215,13 @@ final class SaveUi {
return componentName;
}
intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
- return intent.resolveActivity(packageManager);
+ final ActivityInfo ai =
+ intent.resolveActivityInfo(packageManager, PackageManager.MATCH_INSTANT);
+ if (ai != null) {
+ return new ComponentName(ai.applicationInfo.packageName, ai.name);
+ }
+
+ return null;
}
};
final LayoutInflater inflater = LayoutInflater.from(context);
diff --git a/services/core/Android.bp b/services/core/Android.bp
index e76ec743661c..addaa6568665 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -2,38 +2,25 @@ filegroup {
name: "services.core-sources",
srcs: ["java/**/*.java"],
path: "java",
- visibility: ["//frameworks/base/services"],
-}
-
-java_library {
- name: "protolog-common",
- srcs: [
- "java/com/android/server/protolog/common/**/*.java",
- ],
- host_supported: true,
-}
-
-java_library {
- name: "services.core.wm.protologgroups",
- srcs: [
- "java/com/android/server/wm/ProtoLogGroup.java",
+ visibility: [
+ "//frameworks/base/services",
+ "//frameworks/base/core/java/com/android/internal/protolog",
],
- static_libs: ["protolog-common"],
}
genrule {
name: "services.core.protologsrc",
srcs: [
- ":services.core.wm.protologgroups",
+ ":protolog-groups",
":services.core-sources",
],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
- "--protolog-class com.android.server.protolog.common.ProtoLog " +
- "--protolog-impl-class com.android.server.protolog.ProtoLogImpl " +
- "--protolog-cache-class 'com.android.server.protolog.ProtoLog$$Cache' " +
- "--loggroups-class com.android.server.wm.ProtoLogGroup " +
- "--loggroups-jar $(location :services.core.wm.protologgroups) " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
+ "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
"--output-srcjar $(out) " +
"$(locations :services.core-sources)",
out: ["services.core.protolog.srcjar"],
@@ -42,14 +29,14 @@ genrule {
genrule {
name: "generate-protolog.json",
srcs: [
- ":services.core.wm.protologgroups",
+ ":protolog-groups",
":services.core-sources",
],
tools: ["protologtool"],
cmd: "$(location protologtool) generate-viewer-config " +
- "--protolog-class com.android.server.protolog.common.ProtoLog " +
- "--loggroups-class com.android.server.wm.ProtoLogGroup " +
- "--loggroups-jar $(location :services.core.wm.protologgroups) " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
"--viewer-conf $(out) " +
"$(locations :services.core-sources)",
out: ["services.core.protolog.json"],
@@ -109,6 +96,7 @@ java_library_static {
],
static_libs: [
+ "protolog-lib",
"time_zone_distro",
"time_zone_distro_installer",
"android.hardware.authsecret-V1.0-java",
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index a3c04be02c6f..c9513592ea79 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -28,7 +28,9 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryStatsInternal;
import android.os.Binder;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -308,50 +310,134 @@ public class BinderCallsStatsService extends Binder {
}
boolean verbose = false;
+ int worksourceUid = Process.INVALID_UID;
if (args != null) {
- for (final String arg : args) {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
if ("-a".equals(arg)) {
verbose = true;
- } else if ("--reset".equals(arg)) {
+ } else if ("-h".equals(arg)) {
+ pw.println("dumpsys binder_calls_stats options:");
+ pw.println(" -a: Verbose");
+ pw.println(" --work-source-uid <UID>: Dump binder calls from the UID");
+ return;
+ } else if ("--work-source-uid".equals(arg)) {
+ i++;
+ if (i >= args.length) {
+ throw new IllegalArgumentException(
+ "Argument expected after \"" + arg + "\"");
+ }
+ String uidArg = args[i];
+ try {
+ worksourceUid = Integer.parseInt(uidArg);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid UID: " + uidArg);
+ return;
+ }
+ }
+ }
+
+ if (args.length > 0 && worksourceUid == Process.INVALID_UID) {
+ // For compatibility, support "cmd"-style commands when passed to "dumpsys".
+ BinderCallsStatsShellCommand command = new BinderCallsStatsShellCommand(pw);
+ int status = command.exec(this, null, FileDescriptor.out, FileDescriptor.err, args);
+ if (status == 0) {
+ return;
+ }
+ }
+ }
+ mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), worksourceUid, verbose);
+ }
+
+ @Override
+ public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
+ ParcelFileDescriptor err, String[] args) {
+ ShellCommand command = new BinderCallsStatsShellCommand(null);
+ int status = command.exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
+ err.getFileDescriptor(), args);
+ if (status != 0) {
+ command.onHelp();
+ }
+ return status;
+ }
+
+ private class BinderCallsStatsShellCommand extends ShellCommand {
+ private final PrintWriter mPrintWriter;
+
+ BinderCallsStatsShellCommand(PrintWriter printWriter) {
+ mPrintWriter = printWriter;
+ }
+
+ @Override
+ public PrintWriter getOutPrintWriter() {
+ if (mPrintWriter != null) {
+ return mPrintWriter;
+ }
+ return super.getOutPrintWriter();
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ PrintWriter pw = getOutPrintWriter();
+ if (cmd == null) {
+ return -1;
+ }
+
+ switch (cmd) {
+ case "--reset":
reset();
pw.println("binder_calls_stats reset.");
- return;
- } else if ("--enable".equals(arg)) {
+ break;
+ case "--enable":
Binder.setObserver(mBinderCallsStats);
- return;
- } else if ("--disable".equals(arg)) {
+ break;
+ case "--disable":
Binder.setObserver(null);
- return;
- } else if ("--no-sampling".equals(arg)) {
+ break;
+ case "--no-sampling":
mBinderCallsStats.setSamplingInterval(1);
- return;
- } else if ("--enable-detailed-tracking".equals(arg)) {
+ break;
+ case "--enable-detailed-tracking":
SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
mBinderCallsStats.setDetailedTracking(true);
pw.println("Detailed tracking enabled");
- return;
- } else if ("--disable-detailed-tracking".equals(arg)) {
+ break;
+ case "--disable-detailed-tracking":
SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "");
mBinderCallsStats.setDetailedTracking(false);
pw.println("Detailed tracking disabled");
- return;
- } else if ("--dump-worksource-provider".equals(arg)) {
+ break;
+ case "--dump-worksource-provider":
+ mBinderCallsStats.setDetailedTracking(true);
mWorkSourceProvider.dump(pw, AppIdToPackageMap.getSnapshot());
- return;
- } else if ("-h".equals(arg)) {
- pw.println("binder_calls_stats commands:");
- pw.println(" --reset: Reset stats");
- pw.println(" --enable: Enable tracking binder calls");
- pw.println(" --disable: Disables tracking binder calls");
- pw.println(" --no-sampling: Tracks all calls");
- pw.println(" --enable-detailed-tracking: Enables detailed tracking");
- pw.println(" --disable-detailed-tracking: Disables detailed tracking");
- return;
- } else {
- pw.println("Unknown option: " + arg);
- }
+ break;
+ case "--work-source-uid":
+ String uidArg = getNextArgRequired();
+ try {
+ int uid = Integer.parseInt(uidArg);
+ mBinderCallsStats.recordAllCallsForWorkSourceUid(uid);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid UID: " + uidArg);
+ return -1;
+ }
+ break;
+ default:
+ return handleDefaultCommands(cmd);
}
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("binder_calls_stats commands:");
+ pw.println(" --reset: Reset stats");
+ pw.println(" --enable: Enable tracking binder calls");
+ pw.println(" --disable: Disables tracking binder calls");
+ pw.println(" --no-sampling: Tracks all calls");
+ pw.println(" --enable-detailed-tracking: Enables detailed tracking");
+ pw.println(" --disable-detailed-tracking: Disables detailed tracking");
+ pw.println(" --work-source-uid <UID>: Track all binder calls from the UID");
}
- mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), verbose);
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 02c08cc4cd39..ef62a991f323 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -220,6 +220,8 @@ import com.android.server.utils.PriorityDump;
import com.google.android.collect.Lists;
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -7513,18 +7515,34 @@ public class ConnectivityService extends IConnectivityManager.Stub
public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
String dstAddr) {
- mKeepaliveTracker.startNattKeepalive(
- getNetworkAgentInfoForNetwork(network), fd, resourceId,
- intervalSeconds, cb,
- srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
+ try {
+ mKeepaliveTracker.startNattKeepalive(
+ getNetworkAgentInfoForNetwork(network), fd, resourceId,
+ intervalSeconds, cb,
+ srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
+ } finally {
+ // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
+ // startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately.
+ if (fd != null && Binder.getCallingPid() != Process.myPid()) {
+ IoUtils.closeQuietly(fd);
+ }
+ }
}
@Override
public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
ISocketKeepaliveCallback cb) {
- enforceKeepalivePermission();
- mKeepaliveTracker.startTcpKeepalive(
- getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
+ try {
+ enforceKeepalivePermission();
+ mKeepaliveTracker.startTcpKeepalive(
+ getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
+ } finally {
+ // FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
+ // startTcpKeepalive calls Os.dup(fd) before returning, so we can close immediately.
+ if (fd != null && Binder.getCallingPid() != Process.myPid()) {
+ IoUtils.closeQuietly(fd);
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0ddfa1c16a0a..97f3b373f63e 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -185,10 +185,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
/** Set of interfaces with active alerts. */
@GuardedBy("mQuotaLock")
private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
- /** Set of UIDs blacklisted on metered networks. */
+ /** Set of UIDs denylisted on metered networks. */
@GuardedBy("mRulesLock")
private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
- /** Set of UIDs whitelisted on metered networks. */
+ /** Set of UIDs allowlisted on metered networks. */
@GuardedBy("mRulesLock")
private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
/** Set of UIDs with cleartext penalties. */
@@ -561,27 +561,27 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
synchronized (mRulesLock) {
size = mUidRejectOnMetered.size();
if (size > 0) {
- if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered denylist rules");
uidRejectOnQuota = mUidRejectOnMetered;
mUidRejectOnMetered = new SparseBooleanArray();
}
size = mUidAllowOnMetered.size();
if (size > 0) {
- if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered allowlist rules");
uidAcceptOnQuota = mUidAllowOnMetered;
mUidAllowOnMetered = new SparseBooleanArray();
}
}
if (uidRejectOnQuota != null) {
for (int i = 0; i < uidRejectOnQuota.size(); i++) {
- setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
+ setUidMeteredNetworkDenylist(uidRejectOnQuota.keyAt(i),
uidRejectOnQuota.valueAt(i));
}
}
if (uidAcceptOnQuota != null) {
for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
- setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
+ setUidMeteredNetworkAllowlist(uidAcceptOnQuota.keyAt(i),
uidAcceptOnQuota.valueAt(i));
}
}
@@ -1307,14 +1307,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
- private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
+ private void setUidOnMeteredNetworkList(int uid, boolean denylist, boolean enable) {
NetworkStack.checkNetworkStackPermission(mContext);
synchronized (mQuotaLock) {
boolean oldEnable;
SparseBooleanArray quotaList;
synchronized (mRulesLock) {
- quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
+ quotaList = denylist ? mUidRejectOnMetered : mUidAllowOnMetered;
oldEnable = quotaList.get(uid, false);
}
if (oldEnable == enable) {
@@ -1324,7 +1324,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
try {
- if (blacklist) {
+ if (denylist) {
if (enable) {
mNetdService.bandwidthAddNaughtyApp(uid);
} else {
@@ -1353,12 +1353,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
@Override
- public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
+ public void setUidMeteredNetworkDenylist(int uid, boolean enable) {
setUidOnMeteredNetworkList(uid, true, enable);
}
@Override
- public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
+ public void setUidMeteredNetworkAllowlist(int uid, boolean enable) {
setUidOnMeteredNetworkList(uid, false, enable);
}
@@ -1626,7 +1626,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
}
- // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
+ // Normally, allowlist chains only contain deny rules, so numUids == exemptUids.length.
// But the code does not guarantee this in any way, and at least in one case - if we add
// a UID rule to the firewall, and then disable the firewall - the chains can contain
// the wrong type of rule. In this case, don't close connections that we shouldn't.
@@ -1691,7 +1691,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
// Close any sockets that were opened by the affected UIDs. This has to be done after
// disabling network connectivity, in case they react to the socket close by reopening
// the connection and race with the iptables commands that enable the firewall. All
- // whitelist and blacklist chains allow RSTs through.
+ // allowlist and denylist chains allow RSTs through.
if (enable) {
closeSocketsForFirewallChainLocked(chain, chainName);
}
@@ -1828,7 +1828,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
} else {
ruleName = "deny";
}
- } else { // Blacklist mode
+ } else { // Denylist mode
if (rule == FIREWALL_RULE_DENY) {
ruleName = "deny";
} else {
@@ -1913,8 +1913,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
pw.print("Data saver mode: "); pw.println(mDataSaverMode);
synchronized (mRulesLock) {
- dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
- dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
+ dumpUidRuleOnQuotaLocked(pw, "denylist", mUidRejectOnMetered);
+ dumpUidRuleOnQuotaLocked(pw, "allowlist", mUidAllowOnMetered);
}
}
@@ -2179,9 +2179,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
- void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
+ void setUidOnMeteredNetworkList(boolean denylist, int uid, boolean enable) {
synchronized (mRulesLock) {
- if (blacklist) {
+ if (denylist) {
mUidRejectOnMetered.put(uid, enable);
} else {
mUidAllowOnMetered.put(uid, enable);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 1689656479a5..e675d8d458c7 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1453,8 +1453,11 @@ public class PackageWatchdog {
} else {
mHealthCheckState = HealthCheckState.ACTIVE;
}
- Slog.i(TAG, "Updated health check state for package " + getName() + ": "
- + toString(oldState) + " -> " + toString(mHealthCheckState));
+
+ if (oldState != mHealthCheckState) {
+ Slog.i(TAG, "Updated health check state for package " + getName() + ": "
+ + toString(oldState) + " -> " + toString(mHealthCheckState));
+ }
return mHealthCheckState;
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 2534a535079e..59ac09ca2f3d 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -167,7 +167,7 @@ public class VibratorService extends IVibratorService.Stub
private boolean mIsVibrating;
@GuardedBy("mLock")
private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
- new RemoteCallbackList<>();
+ new RemoteCallbackList<>();
private int mHapticFeedbackIntensity;
private int mNotificationIntensity;
private int mRingIntensity;
@@ -176,16 +176,25 @@ public class VibratorService extends IVibratorService.Stub
static native long vibratorInit();
static native long vibratorGetFinalizer();
+
static native boolean vibratorExists(long controllerPtr);
- static native void vibratorOn(long milliseconds);
+
+ static native void vibratorOn(long controllerPtr, long milliseconds, Vibration vibration);
+
static native void vibratorOff(long controllerPtr);
+
static native void vibratorSetAmplitude(long controllerPtr, int amplitude);
+
static native int[] vibratorGetSupportedEffects(long controllerPtr);
+
static native long vibratorPerformEffect(long effect, long strength, Vibration vibration,
boolean withCallback);
- static native void vibratorPerformComposedEffect(
+
+ static native void vibratorPerformComposedEffect(long controllerPtr,
VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
+
static native void vibratorSetExternalControl(long controllerPtr, boolean enabled);
+
static native long vibratorGetCapabilities(long controllerPtr);
static native void vibratorAlwaysOnEnable(long controllerPtr, long id, long effect,
long strength);
@@ -231,8 +240,7 @@ public class VibratorService extends IVibratorService.Stub
// The actual effect to be played.
public VibrationEffect effect;
- // The original effect that was requested. This is non-null only when the original effect
- // differs from the effect that's being played. Typically these two things differ because
+ // The original effect that was requested. Typically these two things differ because
// the effect was scaled based on the users vibration intensity settings.
public VibrationEffect originalEffect;
@@ -248,9 +256,13 @@ public class VibratorService extends IVibratorService.Stub
this.reason = reason;
}
+ @Override
public void binderDied() {
synchronized (mLock) {
if (this == mCurrentVibration) {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibration finished because binder died, cleaning up");
+ }
doCancelVibrateLocked();
}
}
@@ -261,6 +273,9 @@ public class VibratorService extends IVibratorService.Stub
public void onComplete() {
synchronized (mLock) {
if (this == mCurrentVibration) {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibration finished by callback, cleaning up");
+ }
doCancelVibrateLocked();
}
}
@@ -915,7 +930,7 @@ public class VibratorService extends IVibratorService.Stub
// Callback for whenever the current vibration has finished played out
public void onVibrationFinished() {
if (DEBUG) {
- Slog.e(TAG, "Vibration finished, cleaning up");
+ Slog.d(TAG, "Vibration finished, cleaning up");
}
synchronized (mLock) {
// Make sure the vibration is really done. This also reports that the vibration is
@@ -943,25 +958,22 @@ public class VibratorService extends IVibratorService.Stub
private void startVibrationInnerLocked(Vibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationInnerLocked");
try {
+ long timeout = 0;
mCurrentVibration = vib;
if (vib.effect instanceof VibrationEffect.OneShot) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect;
- doVibratorOn(oneShot.getDuration(), oneShot.getAmplitude(), vib.uid, vib.attrs);
- mH.postDelayed(mVibrationEndRunnable, oneShot.getDuration());
+ doVibratorOn(oneShot.getDuration(), oneShot.getAmplitude(), vib);
+ timeout = oneShot.getDuration() * ASYNC_TIMEOUT_MULTIPLIER;
} else if (vib.effect instanceof VibrationEffect.Waveform) {
// mThread better be null here. doCancelVibrate should always be
// called before startNextVibrationLocked or startVibrationLocked.
- Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect;
mThread = new VibrateThread(waveform, vib.uid, vib.attrs);
mThread.start();
} else if (vib.effect instanceof VibrationEffect.Prebaked) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
- long timeout = doVibratorPrebakedEffectLocked(vib);
- if (timeout > 0) {
- mH.postDelayed(mVibrationEndRunnable, timeout);
- }
+ timeout = doVibratorPrebakedEffectLocked(vib);
} else if (vib.effect instanceof VibrationEffect.Composed) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
doVibratorComposedEffectLocked(vib);
@@ -969,10 +981,16 @@ public class VibratorService extends IVibratorService.Stub
// devices which support composition also support the completion callback. If we
// ever get a device that supports the former but not the latter, then we have no
// real way of knowing how long a given effect should last.
- mH.postDelayed(mVibrationEndRunnable, 10000);
+ timeout = 10_000;
} else {
Slog.e(TAG, "Unknown vibration type, ignoring");
}
+ // Post extra runnable to ensure vibration will end even if the HAL or native controller
+ // never triggers the callback.
+ // TODO: Move ASYNC_TIMEOUT_MULTIPLIER here once native controller is fully integrated.
+ if (timeout > 0) {
+ mH.postDelayed(mVibrationEndRunnable, timeout);
+ }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
@@ -1062,18 +1080,18 @@ public class VibratorService extends IVibratorService.Stub
return attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY);
}
- private int getAppOpMode(Vibration vib) {
+ private int getAppOpMode(int uid, String packageName, VibrationAttributes attrs) {
int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
- vib.attrs.getAudioAttributes().getUsage(), vib.uid, vib.opPkg);
+ attrs.getAudioAttributes().getUsage(), uid, packageName);
if (mode == AppOpsManager.MODE_ALLOWED) {
- mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, vib.uid, vib.opPkg);
+ mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, packageName);
}
- if (mode == AppOpsManager.MODE_IGNORED && shouldBypassDnd(vib.attrs)) {
+ if (mode == AppOpsManager.MODE_IGNORED && shouldBypassDnd(attrs)) {
// If we're just ignoring the vibration op then this is set by DND and we should ignore
// if we're asked to bypass. AppOps won't be able to record this operation, so make
// sure we at least note it in the logs for debugging.
- Slog.d(TAG, "Bypassing DND for vibration: " + vib);
+ Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid);
mode = AppOpsManager.MODE_ALLOWED;
}
return mode;
@@ -1095,7 +1113,7 @@ public class VibratorService extends IVibratorService.Stub
return false;
}
- final int mode = getAppOpMode(vib);
+ final int mode = getAppOpMode(vib.uid, vib.opPkg, vib.attrs);
if (mode != AppOpsManager.MODE_ALLOWED) {
if (mode == AppOpsManager.MODE_ERRORED) {
// We might be getting calls from within system_server, so we don't actually
@@ -1265,7 +1283,18 @@ public class VibratorService extends IVibratorService.Stub
return mNativeWrapper.vibratorExists();
}
+ /** Vibrates with native callback trigger for {@link Vibration#onComplete()}. */
+ private void doVibratorOn(long millis, int amplitude, Vibration vib) {
+ doVibratorOn(millis, amplitude, vib.uid, vib.attrs, vib);
+ }
+
+ /** Vibrates without native callback. */
private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs) {
+ doVibratorOn(millis, amplitude, uid, attrs, /* vib= */ null);
+ }
+
+ private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs,
+ @Nullable Vibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOn");
try {
synchronized (mInputDeviceVibrators) {
@@ -1280,13 +1309,14 @@ public class VibratorService extends IVibratorService.Stub
final int vibratorCount = mInputDeviceVibrators.size();
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
- mInputDeviceVibrators.get(i).vibrate(millis, attrs.getAudioAttributes());
+ Vibrator inputDeviceVibrator = mInputDeviceVibrators.get(i);
+ inputDeviceVibrator.vibrate(millis, attrs.getAudioAttributes());
}
} else {
// Note: ordering is important here! Many haptic drivers will reset their
// amplitude when enabled, so we always have to enable first, then set the
// amplitude.
- mNativeWrapper.vibratorOn(millis);
+ mNativeWrapper.vibratorOn(millis, vib);
doVibratorSetAmplitude(amplitude);
}
}
@@ -1570,6 +1600,7 @@ public class VibratorService extends IVibratorService.Stub
proto.flush();
}
+ /** Thread that plays a single {@link VibrationEffect.Waveform}. */
private class VibrateThread extends Thread {
private final VibrationEffect.Waveform mWaveform;
private final int mUid;
@@ -1738,8 +1769,8 @@ public class VibratorService extends IVibratorService.Stub
}
/** Turns vibrator on for given time. */
- public void vibratorOn(long milliseconds) {
- VibratorService.vibratorOn(milliseconds);
+ public void vibratorOn(long milliseconds, @Nullable Vibration vibration) {
+ VibratorService.vibratorOn(mNativeControllerPtr, milliseconds, vibration);
}
/** Turns vibrator off. */
@@ -1766,7 +1797,7 @@ public class VibratorService extends IVibratorService.Stub
/** Turns vibrator on to perform one of the supported composed effects. */
public void vibratorPerformComposedEffect(
VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration) {
- VibratorService.vibratorPerformComposedEffect(effect, vibration);
+ VibratorService.vibratorPerformComposedEffect(mNativeControllerPtr, effect, vibration);
}
/** Enabled the device vibrator to be controlled by another service. */
@@ -1865,7 +1896,7 @@ public class VibratorService extends IVibratorService.Stub
return SCALE_MUTE;
}
if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
- vib.getUid(), -1 /*owningUid*/, true /*exported*/)
+ vib.getUid(), -1 /*owningUid*/, true /*exported*/)
!= PackageManager.PERMISSION_GRANTED) {
Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
+ " tried to play externally controlled vibration"
@@ -1873,6 +1904,14 @@ public class VibratorService extends IVibratorService.Stub
return SCALE_MUTE;
}
+ int mode = getAppOpMode(vib.getUid(), vib.getPackage(), vib.getVibrationAttributes());
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode == AppOpsManager.MODE_ERRORED) {
+ Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid());
+ }
+ return SCALE_MUTE;
+ }
+
final int scaleLevel;
synchronized (mLock) {
if (!vib.equals(mCurrentExternalVibration)) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 33a92e6ad0ac..3eb26de3a675 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1836,11 +1836,13 @@ public final class ActiveServices {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
- + " (pid=" + Binder.getCallingPid()
+ + " (pid=" + callingPid
+ ") when binding service " + service);
}
@@ -1880,19 +1882,19 @@ public final class ActiveServices {
}
if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 && !isCallerSystem) {
- throw new SecurityException("Non-system caller (pid=" + Binder.getCallingPid()
+ throw new SecurityException("Non-system caller (pid=" + callingPid
+ ") set BIND_SCHEDULE_LIKE_TOP_APP when binding service " + service);
}
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException(
- "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ "Non-system caller " + caller + " (pid=" + callingPid
+ ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
if ((flags & Context.BIND_ALLOW_INSTANT) != 0 && !isCallerSystem) {
throw new SecurityException(
- "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ "Non-system caller " + caller + " (pid=" + callingPid
+ ") set BIND_ALLOW_INSTANT when binding service " + service);
}
@@ -1908,7 +1910,7 @@ public final class ActiveServices {
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
- Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+ callingPid, callingUid, userId, true,
callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
@@ -2068,7 +2070,7 @@ public final class ActiveServices {
if (!s.mAllowWhileInUsePermissionInFgs) {
s.mAllowWhileInUsePermissionInFgs =
shouldAllowWhileInUsePermissionInFgsLocked(callingPackage,
- Binder.getCallingPid(), Binder.getCallingUid(),
+ callingPid, callingUid,
service, s, false);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 71d12eed5412..b62ff1c26f8f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14055,13 +14055,13 @@ public class ActivityManagerService extends IActivityManager.Stub
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
- return registerReceiverWithFeature(caller, callerPackage, null, receiver, filter,
- permission, userId, flags);
+ return registerReceiverWithFeature(caller, callerPackage, null, null,
+ receiver, filter, permission, userId, flags);
}
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
- String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
- String permission, int userId, int flags) {
+ String callerFeatureId, String receiverId, IIntentReceiver receiver,
+ IntentFilter filter, String permission, int userId, int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
@@ -14198,7 +14198,7 @@ public class ActivityManagerService extends IActivityManager.Stub
+ " callerPackage is " + callerPackage);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
- permission, callingUid, userId, instantApp, visibleToInstantApps);
+ receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
index 578db6f9dba1..50e06c30e17d 100644
--- a/services/core/java/com/android/server/am/BroadcastFilter.java
+++ b/services/core/java/com/android/server/am/BroadcastFilter.java
@@ -28,6 +28,7 @@ final class BroadcastFilter extends IntentFilter {
final ReceiverList receiverList;
final String packageName;
final String featureId;
+ final String receiverId;
final String requiredPermission;
final int owningUid;
final int owningUserId;
@@ -35,12 +36,13 @@ final class BroadcastFilter extends IntentFilter {
final boolean visibleToInstantApp;
BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
- String _packageName, String _featureId, String _requiredPermission, int _owningUid, int _userId,
- boolean _instantApp, boolean _visibleToInstantApp) {
+ String _packageName, String _featureId, String _receiverId, String _requiredPermission,
+ int _owningUid, int _userId, boolean _instantApp, boolean _visibleToInstantApp) {
super(_filter);
receiverList = _receiverList;
packageName = _packageName;
featureId = _featureId;
+ receiverId = _receiverId;
requiredPermission = _requiredPermission;
owningUid = _owningUid;
owningUserId = _userId;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 12937b988beb..960d26b5da34 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -639,7 +639,7 @@ public final class BroadcastQueue {
final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
if (opCode != AppOpsManager.OP_NONE
&& mService.getAppOpsManager().noteOpNoThrow(opCode, r.callingUid,
- r.callerPackage, r.callerFeatureId, "")
+ r.callerPackage, r.callerFeatureId, "Broadcast sent to protected receiver")
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
@@ -672,7 +672,8 @@ public final class BroadcastQueue {
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.getAppOpsManager().noteOpNoThrow(appOp,
- filter.receiverList.uid, filter.packageName, filter.featureId, "")
+ filter.receiverList.uid, filter.packageName, filter.featureId,
+ "Broadcast delivered to registered receiver " + filter.receiverId)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
@@ -704,7 +705,8 @@ public final class BroadcastQueue {
}
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.getAppOpsManager().noteOpNoThrow(r.appOp,
- filter.receiverList.uid, filter.packageName, filter.featureId, "")
+ filter.receiverList.uid, filter.packageName, filter.featureId,
+ "Broadcast delivered to registered receiver " + filter.receiverId)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
@@ -1366,9 +1368,10 @@ public final class BroadcastQueue {
skip = true;
} else if (!skip && info.activityInfo.permission != null) {
final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
- if (opCode != AppOpsManager.OP_NONE
- && mService.getAppOpsManager().noteOpNoThrow(opCode, r.callingUid, r.callerPackage,
- r.callerFeatureId, "") != AppOpsManager.MODE_ALLOWED) {
+ if (opCode != AppOpsManager.OP_NONE && mService.getAppOpsManager().noteOpNoThrow(opCode,
+ r.callingUid, r.callerPackage, r.callerFeatureId,
+ "Broadcast delivered to " + info.activityInfo.name)
+ != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
@@ -1407,7 +1410,8 @@ public final class BroadcastQueue {
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.getAppOpsManager().noteOpNoThrow(appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
- null /* default featureId */, "")
+ null /* default featureId */,
+ "Broadcast delivered to " + info.activityInfo.name)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
@@ -1424,7 +1428,7 @@ public final class BroadcastQueue {
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.getAppOpsManager().noteOpNoThrow(r.appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
- null /* default featureId */, "")
+ null /* default featureId */, "Broadcast delivered to " + info.activityInfo.name)
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 366f30318cd5..b94396634530 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1282,7 +1282,6 @@ public class AudioService extends IAudioService.Stub
}
if (isPlatformTelevision()) {
- checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller);
synchronized (mHdmiClientLock) {
if (mHdmiManager != null && mHdmiPlaybackClient != null) {
updateHdmiCecSinkLocked(mHdmiCecSink | false);
@@ -1302,22 +1301,54 @@ public class AudioService extends IAudioService.Stub
}
}
- private void checkAddAllFixedVolumeDevices(int device, String caller) {
+ /**
+ * Update volume states for the given device.
+ *
+ * This will initialize the volume index if no volume index is available.
+ * If the device is the currently routed device, fixed/full volume policies will be applied.
+ *
+ * @param device a single audio device, ensure that this is not a devices bitmask
+ * @param caller caller of this method
+ */
+ private void updateVolumeStatesForAudioDevice(int device, String caller) {
final int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = 0; streamType < numStreamTypes; streamType++) {
- if (!mStreamStates[streamType].hasIndexForDevice(device)) {
- // set the default value, if device is affected by a full/fix/abs volume rule, it
- // will taken into account in checkFixedVolumeDevices()
- mStreamStates[streamType].setIndex(
- mStreamStates[mStreamVolumeAlias[streamType]]
- .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
- device, caller, true /*hasModifyAudioSettings*/);
- }
- mStreamStates[streamType].checkFixedVolumeDevices();
+ updateVolumeStates(device, streamType, caller);
+ }
+ }
- // Unmute streams if device is full volume
- if (mFullVolumeDevices.contains(device)) {
- mStreamStates[streamType].mute(false);
+ /**
+ * Update volume states for the given device and given stream.
+ *
+ * This will initialize the volume index if no volume index is available.
+ * If the device is the currently routed device, fixed/full volume policies will be applied.
+ *
+ * @param device a single audio device, ensure that this is not a devices bitmask
+ * @param streamType streamType to be updated
+ * @param caller caller of this method
+ */
+ private void updateVolumeStates(int device, int streamType, String caller) {
+ if (!mStreamStates[streamType].hasIndexForDevice(device)) {
+ // set the default value, if device is affected by a full/fix/abs volume rule, it
+ // will taken into account in checkFixedVolumeDevices()
+ mStreamStates[streamType].setIndex(
+ mStreamStates[mStreamVolumeAlias[streamType]]
+ .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
+ device, caller, true /*hasModifyAudioSettings*/);
+ }
+
+ // Check if device to be updated is routed for the given audio stream
+ List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributes(
+ new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
+ for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) {
+ if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType(
+ device)) {
+ mStreamStates[streamType].checkFixedVolumeDevices();
+
+ // Unmute streams if required if device is full volume
+ if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) {
+ mStreamStates[streamType].mute(false);
+ }
}
}
}
@@ -4901,7 +4932,15 @@ public class AudioService extends IAudioService.Stub
synchronized (VolumeStreamState.class) {
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (stream != skipStream) {
- mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
+ int devices = mStreamStates[stream].observeDevicesForStream_syncVSS(
+ false /*checkOthers*/);
+
+ Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices);
+ for (Integer device : devicesSet) {
+ // Update volume states for devices routed for the stream
+ updateVolumeStates(device, stream,
+ "AudioService#observeDevicesForStreams");
+ }
}
}
}
@@ -4970,7 +5009,7 @@ public class AudioService extends IAudioService.Stub
+ Integer.toHexString(audioSystemDeviceOut) + " from:" + caller));
// make sure we have a volume entry for this device, and that volume is updated according
// to volume behavior
- checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
+ updateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
}
/**
@@ -7192,10 +7231,9 @@ public class AudioService extends IAudioService.Stub
// HDMI output
removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
}
+ updateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI,
+ "HdmiPlaybackClient.DisplayStatusCallback");
}
-
- checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
- "HdmiPlaybackClient.DisplayStatusCallback");
}
private class MyHdmiControlStatusChangeListenerCallback
@@ -7903,9 +7941,6 @@ public class AudioService extends IAudioService.Stub
return null;
}
- mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
- + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
-
String regId = null;
synchronized (mAudioPolicies) {
if (mAudioPolicies.containsKey(pcb.asBinder())) {
@@ -7916,6 +7951,13 @@ public class AudioService extends IAudioService.Stub
AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
isFocusPolicy, isTestFocusPolicy, isVolumeController, projection);
pcb.asBinder().linkToDeath(app, 0/*flags*/);
+
+ // logging after registration so we have the registration id
+ mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
+ + pcb.asBinder() + " u/pid:" + Binder.getCallingUid() + "/"
+ + Binder.getCallingPid() + " with config:" + app.toCompactLogString()))
+ .printLog(TAG));
+
regId = app.getRegistrationId();
mAudioPolicies.put(pcb.asBinder(), app);
} catch (RemoteException e) {
@@ -8079,7 +8121,10 @@ public class AudioService extends IAudioService.Stub
* @param pcb nullable because on service interface
*/
public void unregisterAudioPolicyAsync(@Nullable IAudioPolicyCallback pcb) {
- unregisterAudioPolicy(pcb);
+ if (pcb == null) {
+ return;
+ }
+ unregisterAudioPolicyInt(pcb, "unregisterAudioPolicyAsync");
}
/**
@@ -8090,12 +8135,12 @@ public class AudioService extends IAudioService.Stub
if (pcb == null) {
return;
}
- unregisterAudioPolicyInt(pcb);
+ unregisterAudioPolicyInt(pcb, "unregisterAudioPolicy");
}
- private void unregisterAudioPolicyInt(@NonNull IAudioPolicyCallback pcb) {
- mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
+ private void unregisterAudioPolicyInt(@NonNull IAudioPolicyCallback pcb, String operationName) {
+ mDynPolicyLogger.log((new AudioEventLogger.StringEvent(operationName + " for "
+ pcb.asBinder()).printLog(TAG)));
synchronized (mAudioPolicies) {
AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
@@ -8570,7 +8615,8 @@ public class AudioService extends IAudioService.Stub
}
public void binderDied() {
- Log.i(TAG, "audio policy " + mPolicyCallback + " died");
+ mDynPolicyLogger.log((new AudioEventLogger.StringEvent("AudioPolicy "
+ + mPolicyCallback.asBinder() + " died").printLog(TAG)));
release();
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 6f12155c5ec6..b8e579d58794 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -349,9 +349,7 @@ public abstract class BrightnessMappingStrategy {
// Normalize entire brightness range to 0 - 1.
protected static float normalizeAbsoluteBrightness(int brightness) {
- return BrightnessSynchronizer.brightnessIntToFloat(brightness,
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ return BrightnessSynchronizer.brightnessIntToFloat(brightness);
}
private Pair<float[], float[]> insertControlPoint(
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 0979ad67a8cd..dab8c7fc9d48 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -30,8 +30,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import android.Manifest;
import android.annotation.NonNull;
@@ -46,7 +44,6 @@ import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.ColorSpace;
import android.graphics.Point;
-import android.graphics.Rect;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
@@ -104,7 +101,6 @@ import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.UiThread;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -1394,9 +1390,13 @@ public final class DisplayManagerService extends SystemService {
}
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
- return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
- displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
- false /* useIdentityTransform */, 0 /* rotation */);
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(token)
+ .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
+ .setUseIdentityTransform(true)
+ .setCaptureSecureLayers(true)
+ .build();
+ return SurfaceControl.captureDisplay(captureArgs);
}
}
@@ -1406,30 +1406,11 @@ public final class DisplayManagerService extends SystemService {
if (token == null) {
return null;
}
- final LogicalDisplay logicalDisplay = mLogicalDisplays.get(displayId);
- if (logicalDisplay == null) {
- return null;
- }
- final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
- // Takes screenshot based on current device orientation.
- final Display display = DisplayManagerGlobal.getInstance()
- .getRealDisplay(displayId);
- if (display == null) {
- return null;
- }
- final Point displaySize = new Point();
- display.getRealSize(displaySize);
-
- int rotation = displayInfo.rotation;
- // TODO (b/153382624) : This workaround solution would be removed after
- // SurfaceFlinger fixes the inconsistency with rotation direction issue.
- if (rotation == ROTATION_90 || rotation == ROTATION_270) {
- rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
- }
-
- return SurfaceControl.screenshotToBuffer(token, new Rect(), displaySize.x,
- displaySize.y, false /* useIdentityTransform */, rotation /* rotation */);
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(token)
+ .build();
+ return SurfaceControl.captureDisplay(captureArgs);
}
}
@@ -2550,8 +2531,7 @@ public final class DisplayManagerService extends SystemService {
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
- return mDisplayPowerController.requestPowerState(request,
- waitForNegativeProximity);
+ return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);
}
}
@@ -2679,6 +2659,10 @@ public final class DisplayManagerService extends SystemService {
return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp);
}
+ @Override
+ public void ignoreProximitySensorUntilChanged() {
+ mDisplayPowerController.ignoreProximitySensorUntilChanged();
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9411c5629457..58ef9d11ef97 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -117,6 +117,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_CONFIGURE_BRIGHTNESS = 5;
private static final int MSG_SET_TEMPORARY_BRIGHTNESS = 6;
private static final int MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT = 7;
+ private static final int MSG_IGNORE_PROXIMITY = 8;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -263,6 +264,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// go to sleep by the user. While true, the screen remains off.
private boolean mWaitingForNegativeProximity;
+ // True if the device should not take into account the proximity sensor
+ // until either the proximity sensor state changes, or there is no longer a
+ // request to listen to proximity sensor.
+ private boolean mIgnoreProximityUntilChanged;
+
// The actual proximity sensor threshold value.
private float mProximityThreshold;
@@ -699,13 +705,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Initialize screen state for battery stats.
try {
mBatteryStats.noteScreenState(mPowerState.getScreenState());
- mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(mContext,
+ mBatteryStats.noteScreenBrightness(BrightnessSynchronizer.brightnessFloatToInt(
mPowerState.getScreenBrightness()));
} catch (RemoteException ex) {
// same process
}
// Initialize all of the brightness tracking state
- final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(mContext,
+ final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(
mPowerState.getScreenBrightness()));
if (brightness >= 0.0f) {
mBrightnessTracker.start(brightness);
@@ -760,8 +766,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mPowerRequest == null) {
mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
- mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
+ updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mustInitialize = true;
// Assume we're on and bright until told otherwise, since that's the state we turn
@@ -770,8 +775,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else if (mPendingRequestChangedLocked) {
previousPolicy = mPowerRequest.policy;
mPowerRequest.copyFrom(mPendingRequestLocked);
- mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
+ updatePendingProximityRequestsLocked();
mPendingRequestChangedLocked = false;
mDisplayReadyLocked = false;
} else {
@@ -822,9 +826,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Apply the proximity sensor.
if (mProximitySensor != null) {
if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
+ // At this point the policy says that the screen should be on, but we've been
+ // asked to listen to the prox sensor to adjust the display state, so lets make
+ // sure the sensor is on.
setProximitySensorEnabled(true);
if (!mScreenOffBecauseOfProximity
- && mProximity == PROXIMITY_POSITIVE) {
+ && mProximity == PROXIMITY_POSITIVE
+ && !mIgnoreProximityUntilChanged) {
+ // Prox sensor already reporting "near" so we should turn off the screen.
+ // Also checked that we aren't currently set to ignore the proximity sensor
+ // temporarily.
mScreenOffBecauseOfProximity = true;
sendOnProximityPositiveWithWakelock();
}
@@ -832,18 +843,28 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE
&& state != Display.STATE_OFF) {
+ // The policy says that we should have the screen on, but it's off due to the prox
+ // and we've been asked to wait until the screen is far from the user to turn it
+ // back on. Let keep the prox sensor on so we can tell when it's far again.
setProximitySensorEnabled(true);
} else {
+ // We haven't been asked to use the prox sensor and we're not waiting on the screen
+ // to turn back on...so lets shut down the prox sensor.
setProximitySensorEnabled(false);
mWaitingForNegativeProximity = false;
}
+
if (mScreenOffBecauseOfProximity
- && mProximity != PROXIMITY_POSITIVE) {
+ && (mProximity != PROXIMITY_POSITIVE || mIgnoreProximityUntilChanged)) {
+ // The screen *was* off due to prox being near, but now it's "far" so lets turn
+ // the screen back on. Also turn it back on if we've been asked to ignore the
+ // prox sensor temporarily.
mScreenOffBecauseOfProximity = false;
sendOnProximityNegativeWithWakelock();
}
} else {
mWaitingForNegativeProximity = false;
+ mIgnoreProximityUntilChanged = false;
}
if (mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
@@ -1093,7 +1114,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
userInitiatedChange = false;
}
notifyBrightnessChanged(
- BrightnessSynchronizer.brightnessFloatToInt(mContext, brightnessState),
+ BrightnessSynchronizer.brightnessFloatToInt(brightnessState),
userInitiatedChange, hadUserBrightnessPoint);
}
@@ -1181,6 +1202,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
sendUpdatePowerState();
}
+ /**
+ * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
+ * currently enabled and forcing the screen to be dark.
+ */
+ public void ignoreProximitySensorUntilChanged() {
+ mHandler.sendEmptyMessage(MSG_IGNORE_PROXIMITY);
+ }
+
public void setBrightnessConfiguration(BrightnessConfiguration c) {
Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS, c);
msg.sendToTarget();
@@ -1341,8 +1370,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
try {
// TODO(brightnessfloat): change BatteryStats to use float
mBatteryStats.noteScreenBrightness(
- BrightnessSynchronizer.brightnessFloatToInt(
- mContext, target));
+ BrightnessSynchronizer.brightnessFloatToInt(target));
} catch (RemoteException ex) {
// same process
}
@@ -1529,6 +1557,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Register the listener.
// Proximity sensor state already cleared initially.
mProximitySensorEnabled = true;
+ mIgnoreProximityUntilChanged = false;
mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
}
@@ -1538,6 +1567,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Clear the proximity sensor state for next time.
mProximitySensorEnabled = false;
mProximity = PROXIMITY_UNKNOWN;
+ mIgnoreProximityUntilChanged = false;
mPendingProximity = PROXIMITY_UNKNOWN;
mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
mSensorManager.unregisterListener(mProximitySensorListener);
@@ -1580,6 +1610,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& mPendingProximityDebounceTime >= 0) {
final long now = SystemClock.uptimeMillis();
if (mPendingProximityDebounceTime <= now) {
+ if (mProximity != mPendingProximity) {
+ // if the status of the sensor changed, stop ignoring.
+ mIgnoreProximityUntilChanged = false;
+ Slog.i(TAG, "No longer ignoring proximity [" + mPendingProximity + "]");
+ }
// Sensor reading accepted. Apply the change then release the wake lock.
mProximity = mPendingProximity;
updatePowerState();
@@ -1723,6 +1758,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
+ private void updatePendingProximityRequestsLocked() {
+ mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+ mPendingWaitForNegativeProximityLocked = false;
+
+ if (mIgnoreProximityUntilChanged) {
+ // Also, lets stop waiting for negative proximity if we're ignoring it.
+ mWaitingForNegativeProximity = false;
+ }
+ }
+
+ private void ignoreProximitySensorUntilChangedInternal() {
+ if (!mIgnoreProximityUntilChanged
+ && mPowerRequest.useProximitySensor
+ && mProximity == PROXIMITY_POSITIVE) {
+ // Only ignore if it is still reporting positive (near)
+ mIgnoreProximityUntilChanged = true;
+ Slog.i(TAG, "Ignoring proximity");
+ updatePowerState();
+ }
+ }
+
private final Runnable mOnStateChangedRunnable = new Runnable() {
@Override
public void run() {
@@ -1961,6 +2017,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryAutoBrightnessAdjustment = Float.intBitsToFloat(msg.arg1);
updatePowerState();
break;
+
+ case MSG_IGNORE_PROXIMITY:
+ ignoreProximitySensorUntilChangedInternal();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 48fa1bf9f246..0be428bdba47 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -728,16 +728,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
try {
if (isHalBrightnessRangeSpecified()) {
brightness = displayBrightnessToHalBrightness(
- BrightnessSynchronizer.brightnessFloatToIntRange(
- getContext(), brightness));
+ BrightnessSynchronizer.brightnessFloatToIntRange(brightness));
}
if (mBacklight != null) {
mBacklight.setBrightness(brightness);
}
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness",
- BrightnessSynchronizer.brightnessFloatToInt(
- getContext(), brightness));
+ BrightnessSynchronizer.brightnessFloatToInt(brightness));
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 596c1eccfabe..d675b81629a4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -232,11 +232,12 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
mAutoTvOff = enabled;
}
+ @Override
@ServiceThreadOnly
@VisibleForTesting
void setIsActiveSource(boolean on) {
assertRunOnServiceThread();
- mIsActiveSource = on;
+ super.setIsActiveSource(on);
if (on) {
getWakeLock().acquire();
} else {
@@ -274,19 +275,15 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
@Override
@ServiceThreadOnly
- protected boolean handleActiveSource(HdmiCecMessage message) {
- super.handleActiveSource(message);
- if (mIsActiveSource) {
- return true;
- }
+ protected void onActiveSourceLost() {
+ assertRunOnServiceThread();
switch (mPowerStateChangeOnActiveSourceLost) {
case STANDBY_NOW:
mService.standby();
- return true;
+ return;
case NONE:
- return true;
+ return;
}
- return true;
}
@ServiceThreadOnly
@@ -398,9 +395,12 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
}
@Override
+ @ServiceThreadOnly
protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
+ assertRunOnServiceThread();
if (physicalAddress != mService.getPhysicalAddress()) {
- return; // Do nothing.
+ setActiveSource(physicalAddress);
+ return;
}
switch (mPlaybackDeviceActionOnRoutingControl) {
case WAKE_UP_AND_SEND_ACTIVE_SOURCE:
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 1c677184b9d2..44ad8eea65ca 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -114,6 +114,19 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
}
@ServiceThreadOnly
+ protected void onActiveSourceLost() {
+ // Nothing to do.
+ }
+
+ @ServiceThreadOnly
+ protected void setActiveSource(int physicalAddress) {
+ assertRunOnServiceThread();
+ // Invalidate the internal active source record. This will also update mIsActiveSource.
+ ActiveSource activeSource = ActiveSource.of(Constants.ADDR_INVALID, physicalAddress);
+ setActiveSource(activeSource);
+ }
+
+ @ServiceThreadOnly
protected boolean handleActiveSource(HdmiCecMessage message) {
assertRunOnServiceThread();
int logicalAddress = message.getSource();
@@ -148,6 +161,9 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
if (physicalAddress == mService.getPhysicalAddress() && mService.isPlaybackDevice()) {
setAndBroadcastActiveSource(message, physicalAddress);
}
+ if (physicalAddress != mService.getPhysicalAddress()) {
+ setActiveSource(physicalAddress);
+ }
switchInputOnReceivingNewActivePath(physicalAddress);
return true;
}
@@ -156,18 +172,21 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected boolean handleRoutingChange(HdmiCecMessage message) {
assertRunOnServiceThread();
+ int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams(), 2);
+ if (physicalAddress != mService.getPhysicalAddress()) {
+ setActiveSource(physicalAddress);
+ }
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
return true;
}
- int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2);
// if the current device is a pure playback device
if (!mIsSwitchDevice
- && newPath == mService.getPhysicalAddress()
+ && physicalAddress == mService.getPhysicalAddress()
&& mService.isPlaybackDevice()) {
- setAndBroadcastActiveSource(message, newPath);
+ setAndBroadcastActiveSource(message, physicalAddress);
}
- handleRoutingChangeAndInformation(newPath, message);
+ handleRoutingChangeAndInformation(physicalAddress, message);
return true;
}
@@ -175,11 +194,14 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected boolean handleRoutingInformation(HdmiCecMessage message) {
assertRunOnServiceThread();
+ int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
+ if (physicalAddress != mService.getPhysicalAddress()) {
+ setActiveSource(physicalAddress);
+ }
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
return true;
}
- int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
// if the current device is a pure playback device
if (!mIsSwitchDevice
&& physicalAddress == mService.getPhysicalAddress()
@@ -222,7 +244,11 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
@ServiceThreadOnly
void setIsActiveSource(boolean on) {
assertRunOnServiceThread();
+ boolean wasActiveSource = mIsActiveSource;
mIsActiveSource = on;
+ if (wasActiveSource && !mIsActiveSource) {
+ onActiveSourceLost();
+ }
}
protected void wakeUpIfActiveSource() {
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index c4f8441a995b..ac9b7ea0d808 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -318,8 +318,7 @@ public class LightsService extends SystemService {
SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
} else {
// Old system
- int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(
- getContext(), brightness);
+ int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
int color = brightnessInt & 0x000000ff;
color = 0xff000000 | (color << 16) | (color << 8) | color;
setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index d4f8c7e855b9..c3532a84c42d 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -1615,7 +1615,7 @@ class LocationProviderManager extends
case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
// fall through
case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
- updateService();
+ updateRegistrations(registration -> true);
break;
default:
break;
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 8004ec70aaf3..850cf7f4b7ce 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -49,8 +49,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
-import android.os.PowerManager.ServiceType;
-import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -486,10 +484,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
deviceIdleService.unregisterStationaryListener(
mDeviceIdleStationaryListener);
}
- // Intentional fall-through.
- case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
- case Intent.ACTION_SCREEN_OFF:
- case Intent.ACTION_SCREEN_ON:
// Call updateLowPowerMode on handler thread so it's always called from the
// same thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
@@ -554,15 +548,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode and the device is stationary.
boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
- final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
- switch (result.locationMode) {
- case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
- case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
- // If we are in battery saver mode and the screen is off, disable GPS.
- disableGpsForPowerManager |=
- result.batterySaverEnabled && !mPowerManager.isInteractive();
- break;
- }
if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
mDisableGpsForPowerManager = disableGpsForPowerManager;
updateEnabled();
@@ -1959,10 +1944,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
- intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f1b89c7a433c..d6e37bacdba8 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -33,6 +33,7 @@ import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HA
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
import static com.android.internal.widget.LockPatternUtils.USER_FRP;
+import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW;
import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
@@ -186,6 +187,9 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts";
private static final String USER_SERIAL_NUMBER_KEY = "serial-number";
+ // TODO (b/145978626) LockSettingsService no longer accepts challenges in the verifyCredential
+ // paths. These are temporarily left around to ensure that resetLockout works. It will be
+ // removed once resetLockout is compartmentalized.
// No challenge provided
private static final int CHALLENGE_NONE = 0;
// Challenge was provided from the external caller (non-LockSettingsService)
@@ -1308,7 +1312,7 @@ public class LockSettingsService extends ILockSettings.Stub {
try {
doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
challengeType, challenge, profileHandle, null /* progressCallback */,
- resetLockouts);
+ resetLockouts, 0 /* flags */);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
@@ -1608,8 +1612,8 @@ public class LockSettingsService extends ILockSettings.Stub {
// Verify the parent credential again, to make sure we have a fresh enough
// auth token such that getDecryptedPasswordForTiedProfile() inside
// setLockCredentialInternal() can function correctly.
- verifyCredential(savedCredential, /* challenge */ 0,
- mUserManager.getProfileParent(userId).id);
+ verifyCredential(savedCredential, mUserManager.getProfileParent(userId).id,
+ 0 /* flags */);
savedCredential.zeroize();
savedCredential = LockscreenCredential.createNone();
}
@@ -1724,7 +1728,7 @@ public class LockSettingsService extends ILockSettings.Stub {
fixateNewestUserKeyAuth(userId);
// Refresh the auth token
doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId,
- null /* progressCallback */);
+ null /* progressCallback */, 0 /* flags */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
@@ -1835,7 +1839,7 @@ public class LockSettingsService extends ILockSettings.Stub {
throw new IllegalArgumentException("Non-OK response verifying a credential we just set "
+ vcr.getResponseCode());
}
- byte[] token = vcr.getPayload();
+ byte[] token = vcr.getGatekeeperHAT();
if (token == null) {
throw new IllegalArgumentException("Empty payload verifying a credential we just set");
}
@@ -1968,35 +1972,56 @@ public class LockSettingsService extends ILockSettings.Stub {
ICheckCredentialProgressCallback progressCallback) {
checkPasswordReadPermission(userId);
try {
- return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback);
+ return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId, progressCallback,
+ 0 /* flags */);
} finally {
scheduleGc();
}
}
@Override
+ @Nullable
public VerifyCredentialResponse verifyCredential(LockscreenCredential credential,
- long challenge, int userId) {
+ int userId, int flags) {
checkPasswordReadPermission(userId);
- @ChallengeType int challengeType = CHALLENGE_FROM_CALLER;
- if (challenge == 0) {
- Slog.w(TAG, "VerifyCredential called with challenge=0");
- challengeType = CHALLENGE_NONE;
- }
try {
- return doVerifyCredential(credential, challengeType, challenge, userId,
- null /* progressCallback */);
+ return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId,
+ null /* progressCallback */, flags);
} finally {
scheduleGc();
}
}
+ @Override
+ public VerifyCredentialResponse verifyGatekeeperPassword(byte[] gatekeeperPassword,
+ long challenge, int userId) {
+ checkPasswordReadPermission(userId);
+
+ VerifyCredentialResponse response;
+ synchronized (mSpManager) {
+ response = mSpManager.verifyChallengeInternal(getGateKeeperService(),
+ gatekeeperPassword, challenge, userId);
+ }
+ return response;
+ }
+
+ /**
+ * @param credential User's lockscreen credential
+ * @param challengeType Owner of the challenge
+ * @param challenge Challenge to be wrapped within Gatekeeper's HAT, if the credential is
+ * verified
+ * @param userId User to verify the credential for
+ * @param progressCallback Receive progress callbacks
+ * @param flags See {@link LockPatternUtils.VerifyFlag}
+ * @return See {@link VerifyCredentialResponse}
+ */
private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
@ChallengeType int challengeType, long challenge, int userId,
- ICheckCredentialProgressCallback progressCallback) {
+ ICheckCredentialProgressCallback progressCallback,
+ @LockPatternUtils.VerifyFlag int flags) {
return doVerifyCredential(credential, challengeType, challenge, userId,
- progressCallback, null /* resetLockouts */);
+ progressCallback, null /* resetLockouts */, flags);
}
/**
@@ -2006,7 +2031,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
@ChallengeType int challengeType, long challenge, int userId,
ICheckCredentialProgressCallback progressCallback,
- @Nullable ArrayList<PendingResetLockout> resetLockouts) {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts,
+ @LockPatternUtils.VerifyFlag int flags) {
if (credential == null || credential.isNone()) {
throw new IllegalArgumentException("Credential can't be null or empty");
}
@@ -2017,7 +2043,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
VerifyCredentialResponse response = null;
response = spBasedDoVerifyCredential(credential, challengeType, challenge,
- userId, progressCallback, resetLockouts);
+ userId, progressCallback, resetLockouts, flags);
// The user employs synthetic password based credential.
if (response != null) {
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -2050,7 +2076,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
- long challenge, int userId) {
+ int userId, @LockPatternUtils.VerifyFlag int flags) {
checkPasswordReadPermission(userId);
if (!isManagedProfileWithUnifiedLock(userId)) {
throw new IllegalArgumentException("User id must be managed profile with unified lock");
@@ -2059,10 +2085,11 @@ public class LockSettingsService extends ILockSettings.Stub {
// Unlock parent by using parent's challenge
final VerifyCredentialResponse parentResponse = doVerifyCredential(
credential,
- CHALLENGE_FROM_CALLER,
- challenge,
+ CHALLENGE_NONE,
+ 0L,
parentProfileId,
- null /* progressCallback */);
+ null /* progressCallback */,
+ flags);
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
// Failed, just return parent's response
return parentResponse;
@@ -2071,9 +2098,10 @@ public class LockSettingsService extends ILockSettings.Stub {
try {
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
- CHALLENGE_FROM_CALLER,
- challenge,
- userId, null /* progressCallback */);
+ CHALLENGE_NONE,
+ 0L,
+ userId, null /* progressCallback */,
+ flags);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
@@ -2132,8 +2160,8 @@ public class LockSettingsService extends ILockSettings.Stub {
unlockKeystore(credential.getCredential(), userId);
Slog.i(TAG, "Unlocking user " + userId + " with token length "
- + response.getPayload().length);
- unlockUser(userId, response.getPayload(), secretFromCredential(credential));
+ + response.getGatekeeperHAT().length);
+ unlockUser(userId, response.getGatekeeperHAT(), secretFromCredential(credential));
if (isManagedProfileWithSeparatedLock(userId)) {
setDeviceUnlockedForUser(userId);
@@ -2684,7 +2712,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
@ChallengeType int challengeType, long challenge,
int userId, ICheckCredentialProgressCallback progressCallback,
- @Nullable ArrayList<PendingResetLockout> resetLockouts) {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts,
+ @LockPatternUtils.VerifyFlag int flags) {
final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
@@ -2705,6 +2734,8 @@ public class LockSettingsService extends ILockSettings.Stub {
final AuthenticationResult authResult;
VerifyCredentialResponse response;
+ final boolean returnGkPw = (flags & VERIFY_FLAG_RETURN_GK_PW) != 0;
+
synchronized (mSpManager) {
if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
return null;
@@ -2717,8 +2748,8 @@ public class LockSettingsService extends ILockSettings.Stub {
long handle = getSyntheticPasswordHandleLocked(userId);
authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
getGateKeeperService(), handle, userCredential, userId, progressCallback);
-
response = authResult.gkResponse;
+
// credential has matched
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
// perform verifyChallenge with synthetic password which generates the real GK auth
@@ -2739,7 +2770,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (resetLockouts == null) {
resetLockouts = new ArrayList<>();
}
- resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
+ resetLockouts.add(new PendingResetLockout(userId, response.getGatekeeperHAT()));
}
onCredentialVerified(authResult.authToken, challengeType, challenge, resetLockouts,
@@ -2750,7 +2781,12 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- return response;
+ if (response.isMatched() && returnGkPw) {
+ return new VerifyCredentialResponse.Builder()
+ .setGatekeeperPassword(authResult.authToken.deriveGkPassword()).build();
+ } else {
+ return response;
+ }
}
private void onCredentialVerified(AuthenticationToken authToken,
@@ -3172,7 +3208,8 @@ public class LockSettingsService extends ILockSettings.Stub {
if (cred == null) {
return false;
}
- return doVerifyCredential(cred, CHALLENGE_NONE, 0, userId, null /* progressCallback */)
+ return doVerifyCredential(cred, CHALLENGE_NONE, 0, userId,
+ null /* progressCallback */, 0 /* flags */)
.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK;
}
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index d644b1dc6ca0..e31bf3d514ed 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -482,11 +482,12 @@ public class SyntheticPasswordManager {
(int status, WeaverReadResponse readResponse) -> {
switch (status) {
case WeaverReadStatus.OK:
- response[0] = new VerifyCredentialResponse(
- fromByteArrayList(readResponse.value));
+ response[0] = new VerifyCredentialResponse.Builder().setGatekeeperHAT(
+ fromByteArrayList(readResponse.value)).build();
break;
case WeaverReadStatus.THROTTLE:
- response[0] = new VerifyCredentialResponse(readResponse.timeout);
+ response[0] = VerifyCredentialResponse
+ .fromTimeout(readResponse.timeout);
Slog.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
break;
case WeaverReadStatus.INCORRECT_KEY:
@@ -494,7 +495,8 @@ public class SyntheticPasswordManager {
response[0] = VerifyCredentialResponse.ERROR;
Slog.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
} else {
- response[0] = new VerifyCredentialResponse(readResponse.timeout);
+ response[0] = VerifyCredentialResponse
+ .fromTimeout(readResponse.timeout);
Slog.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: "
+ slot);
}
@@ -1007,7 +1009,8 @@ public class SyntheticPasswordManager {
return result;
}
sid = GateKeeper.INVALID_SECURE_USER_ID;
- applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
+ applicationId = transformUnderWeaverSecret(pwdToken,
+ result.gkResponse.getGatekeeperHAT());
} else {
byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
GateKeeperResponse response;
@@ -1045,7 +1048,7 @@ public class SyntheticPasswordManager {
}
}
} else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- result.gkResponse = new VerifyCredentialResponse(response.getTimeout());
+ result.gkResponse = VerifyCredentialResponse.fromTimeout(response.getTimeout());
return result;
} else {
result.gkResponse = VerifyCredentialResponse.ERROR;
@@ -1096,12 +1099,12 @@ public class SyntheticPasswordManager {
}
VerifyCredentialResponse response = weaverVerify(slotId, null);
if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
- response.getPayload() == null) {
+ response.getGatekeeperHAT() == null) {
Slog.e(TAG, "Failed to retrieve weaver secret when unwrapping token");
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
- secdiscardable = SyntheticPasswordCrypto.decrypt(response.getPayload(),
+ secdiscardable = SyntheticPasswordCrypto.decrypt(response.getGatekeeperHAT(),
PERSONALISATION_WEAVER_TOKEN, secdiscardable);
}
byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable);
@@ -1174,6 +1177,12 @@ public class SyntheticPasswordManager {
*/
public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper,
@NonNull AuthenticationToken auth, long challenge, int userId) {
+ return verifyChallengeInternal(gatekeeper, auth.deriveGkPassword(), challenge, userId);
+ }
+
+ protected @Nullable VerifyCredentialResponse verifyChallengeInternal(
+ IGateKeeperService gatekeeper, @NonNull byte[] gatekeeperPassword, long challenge,
+ int userId) {
byte[] spHandle = loadSyntheticPasswordHandle(userId);
if (spHandle == null) {
// There is no password handle associated with the given user, i.e. the user is not
@@ -1183,18 +1192,19 @@ public class SyntheticPasswordManager {
GateKeeperResponse response;
try {
response = gatekeeper.verifyChallenge(userId, challenge,
- spHandle, auth.deriveGkPassword());
+ spHandle, gatekeeperPassword);
} catch (RemoteException e) {
Slog.e(TAG, "Fail to verify with gatekeeper " + userId, e);
return VerifyCredentialResponse.ERROR;
}
int responseCode = response.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_OK) {
- VerifyCredentialResponse result = new VerifyCredentialResponse(response.getPayload());
+ VerifyCredentialResponse result = new VerifyCredentialResponse.Builder()
+ .setGatekeeperHAT(response.getPayload()).build();
if (response.getShouldReEnroll()) {
try {
response = gatekeeper.enroll(userId, spHandle, spHandle,
- auth.deriveGkPassword());
+ gatekeeperPassword);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to invoke gatekeeper.enroll", e);
response = GateKeeperResponse.ERROR;
@@ -1203,7 +1213,8 @@ public class SyntheticPasswordManager {
spHandle = response.getPayload();
saveSyntheticPasswordHandle(spHandle, userId);
// Call self again to re-verify with updated handle
- return verifyChallenge(gatekeeper, auth, challenge, userId);
+ return verifyChallengeInternal(gatekeeper, gatekeeperPassword, challenge,
+ userId);
} else {
// Fall through, return result from the previous verification attempt.
Slog.w(TAG, "Fail to re-enroll SP handle for user " + userId);
@@ -1211,7 +1222,7 @@ public class SyntheticPasswordManager {
}
return result;
} else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- return new VerifyCredentialResponse(response.getTimeout());
+ return VerifyCredentialResponse.fromTimeout(response.getTimeout());
} else {
return VerifyCredentialResponse.ERROR;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 3bd18f9a360f..006d78e4a648 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -70,9 +70,9 @@ public class NetworkPolicyLogger {
static final int NTWK_BLOCKED_POWER = 0;
static final int NTWK_ALLOWED_NON_METERED = 1;
- static final int NTWK_BLOCKED_BLACKLIST = 2;
- static final int NTWK_ALLOWED_WHITELIST = 3;
- static final int NTWK_ALLOWED_TMP_WHITELIST = 4;
+ static final int NTWK_BLOCKED_DENYLIST = 2;
+ static final int NTWK_ALLOWED_ALLOWLIST = 3;
+ static final int NTWK_ALLOWED_TMP_ALLOWLIST = 4;
static final int NTWK_BLOCKED_BG_RESTRICT = 5;
static final int NTWK_ALLOWED_DEFAULT = 6;
static final int NTWK_ALLOWED_SYSTEM = 7;
@@ -269,12 +269,12 @@ public class NetworkPolicyLogger {
return "blocked by power restrictions";
case NTWK_ALLOWED_NON_METERED:
return "allowed on unmetered network";
- case NTWK_BLOCKED_BLACKLIST:
- return "blacklisted on metered network";
- case NTWK_ALLOWED_WHITELIST:
- return "whitelisted on metered network";
- case NTWK_ALLOWED_TMP_WHITELIST:
- return "temporary whitelisted on metered network";
+ case NTWK_BLOCKED_DENYLIST:
+ return "denylisted on metered network";
+ case NTWK_ALLOWED_ALLOWLIST:
+ return "allowlisted on metered network";
+ case NTWK_ALLOWED_TMP_ALLOWLIST:
+ return "temporary allowlisted on metered network";
case NTWK_BLOCKED_BG_RESTRICT:
return "blocked when background is restricted";
case NTWK_ALLOWED_DEFAULT:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d6557f6410ec..295143e76235 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -101,13 +101,13 @@ import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_ALLOWLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_DEFAULT;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_NON_METERED;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_SYSTEM;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_WHITELIST;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_WHITELIST;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_ALLOWLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BG_RESTRICT;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BLACKLIST;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_DENYLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_POWER;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -507,7 +507,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* UIDs that have been initially white-listed by system to avoid restricted background.
*/
@GuardedBy("mUidRulesFirstLock")
- private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
+ private final SparseBooleanArray mDefaultRestrictBackgroundAllowlistUids =
new SparseBooleanArray();
/**
@@ -515,7 +515,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* but later revoked by user.
*/
@GuardedBy("mUidRulesFirstLock")
- private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
+ private final SparseBooleanArray mRestrictBackgroundAllowlistRevokedUids =
new SparseBooleanArray();
/** Set of ifaces that are metered. */
@@ -582,7 +582,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
- // TODO: keep whitelist of system-critical services that should never have
+ // TODO: keep allowlist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs.
// TODO: migrate notifications to SystemUI
@@ -668,26 +668,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Whitelists pre-defined apps for restrict background, but only if the user didn't already
- * revoke the whitelist.
+ * Allows pre-defined apps for restrict background, but only if the user didn't already
+ * revoked them.
*
- * @return whether any uid has been whitelisted.
+ * @return whether any uid has been allowlisted.
*/
@GuardedBy("mUidRulesFirstLock")
- boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
+ boolean addDefaultRestrictBackgroundAllowlistUidsUL() {
final List<UserInfo> users = mUserManager.getUsers();
final int numberUsers = users.size();
boolean changed = false;
for (int i = 0; i < numberUsers; i++) {
final UserInfo user = users.get(i);
- changed = addDefaultRestrictBackgroundWhitelistUidsUL(user.id) || changed;
+ changed = addDefaultRestrictBackgroundAllowlistUidsUL(user.id) || changed;
}
return changed;
}
@GuardedBy("mUidRulesFirstLock")
- private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) {
+ private boolean addDefaultRestrictBackgroundAllowlistUidsUL(int userId) {
final SystemConfig sysConfig = SystemConfig.getInstance();
final PackageManager pm = mContext.getPackageManager();
final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
@@ -695,7 +695,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int i = 0; i < allowDataUsage.size(); i++) {
final String pkg = allowDataUsage.valueAt(i);
if (LOGD)
- Slog.d(TAG, "checking restricted background whitelisting for package " + pkg
+ Slog.d(TAG, "checking restricted background allowlisting for package " + pkg
+ " and user " + userId);
final ApplicationInfo app;
try {
@@ -706,20 +706,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
continue;
}
if (!app.isPrivilegedApp()) {
- Slog.e(TAG, "addDefaultRestrictBackgroundWhitelistUidsUL(): "
+ Slog.e(TAG, "addDefaultRestrictBackgroundAllowlistUidsUL(): "
+ "skipping non-privileged app " + pkg);
continue;
}
final int uid = UserHandle.getUid(userId, app.uid);
- mDefaultRestrictBackgroundWhitelistUids.append(uid, true);
+ mDefaultRestrictBackgroundAllowlistUids.append(uid, true);
if (LOGD)
Slog.d(TAG, "Adding uid " + uid + " (user " + userId + ") to default restricted "
- + "background whitelist. Revoked status: "
- + mRestrictBackgroundWhitelistRevokedUids.get(uid));
- if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ + "background allowlist. Revoked status: "
+ + mRestrictBackgroundAllowlistRevokedUids.get(uid));
+ if (!mRestrictBackgroundAllowlistRevokedUids.get(uid)) {
if (LOGD)
Slog.d(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
- + userId + ") to restrict background whitelist");
+ + userId + ") to restrict background allowlist");
setUidPolicyUncheckedUL(uid, POLICY_ALLOW_METERED_BACKGROUND, false);
changed = true;
}
@@ -799,7 +799,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
});
- if (addDefaultRestrictBackgroundWhitelistUidsUL()) {
+ if (addDefaultRestrictBackgroundAllowlistUidsUL()) {
writePolicyAL();
}
@@ -1005,14 +1005,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case ACTION_USER_ADDED:
synchronized (mUidRulesFirstLock) {
// Remove any persistable state for the given user; both cleaning up after a
- // USER_REMOVED, and one last sanity check during USER_ADDED
+ // USER_REMOVED, and one last check during USER_ADDED
removeUserStateUL(userId, true, false);
// Removing outside removeUserStateUL since that can also be called when
// user resets app preferences.
mMeteredRestrictedUids.remove(userId);
if (action == ACTION_USER_ADDED) {
- // Add apps that are whitelisted by default.
- addDefaultRestrictBackgroundWhitelistUidsUL(userId);
+ // Add apps that are allowlisted by default.
+ addDefaultRestrictBackgroundAllowlistUidsUL(userId);
}
// Update global restrict for that user
synchronized (mNetworkPoliciesSecondLock) {
@@ -2196,12 +2196,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
in.setInput(fis, StandardCharsets.UTF_8.name());
// Must save the <restrict-background> tags and convert them to <uid-policy> later,
- // to skip UIDs that were explicitly blacklisted.
- final SparseBooleanArray whitelistedRestrictBackground = new SparseBooleanArray();
+ // to skip UIDs that were explicitly denylisted.
+ final SparseBooleanArray allowlistedRestrictBackground = new SparseBooleanArray();
int type;
int version = VERSION_INIT;
- boolean insideWhitelist = false;
+ boolean insideAllowlist = false;
while ((type = in.next()) != END_DOCUMENT) {
final String tag = in.getName();
if (type == START_TAG) {
@@ -2340,28 +2340,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
} else if (TAG_WHITELIST.equals(tag)) {
- insideWhitelist = true;
- } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+ insideAllowlist = true;
+ } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideAllowlist) {
final int uid = readIntAttribute(in, ATTR_UID);
- whitelistedRestrictBackground.append(uid, true);
- } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+ allowlistedRestrictBackground.append(uid, true);
+ } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideAllowlist) {
final int uid = readIntAttribute(in, ATTR_UID);
- mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
+ mRestrictBackgroundAllowlistRevokedUids.put(uid, true);
}
} else if (type == END_TAG) {
if (TAG_WHITELIST.equals(tag)) {
- insideWhitelist = false;
+ insideAllowlist = false;
}
}
}
- final int size = whitelistedRestrictBackground.size();
+ final int size = allowlistedRestrictBackground.size();
for (int i = 0; i < size; i++) {
- final int uid = whitelistedRestrictBackground.keyAt(i);
+ final int uid = allowlistedRestrictBackground.keyAt(i);
final int policy = mUidPolicy.get(uid, POLICY_NONE);
if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
- Slog.w(TAG, "ignoring restrict-background-whitelist for " + uid
+ Slog.w(TAG, "ignoring restrict-background-allowlist for " + uid
+ " because its policy is " + uidPoliciesToString(policy));
continue;
}
@@ -2533,13 +2533,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
out.endTag(null, TAG_POLICY_LIST);
- // write all whitelists
+ // write all allowlists
out.startTag(null, TAG_WHITELIST);
- // revoked restrict background whitelist
- int size = mRestrictBackgroundWhitelistRevokedUids.size();
+ // revoked restrict background allowlist
+ int size = mRestrictBackgroundAllowlistRevokedUids.size();
for (int i = 0; i < size; i++) {
- final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+ final int uid = mRestrictBackgroundAllowlistRevokedUids.keyAt(i);
out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
writeIntAttribute(out, ATTR_UID, uid);
out.endTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
@@ -2619,21 +2619,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
setUidPolicyUncheckedUL(uid, policy, false);
final boolean notifyApp;
- if (!isUidValidForWhitelistRulesUL(uid)) {
+ if (!isUidValidForAllowlistRulesUL(uid)) {
notifyApp = false;
} else {
- final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
- final boolean isBlacklisted = policy == POLICY_REJECT_METERED_BACKGROUND;
- final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
- final boolean isWhitelisted = policy == POLICY_ALLOW_METERED_BACKGROUND;
- final boolean wasBlocked = wasBlacklisted || (mRestrictBackground && !wasWhitelisted);
- final boolean isBlocked = isBlacklisted || (mRestrictBackground && !isWhitelisted);
- if ((wasWhitelisted && (!isWhitelisted || isBlacklisted))
- && mDefaultRestrictBackgroundWhitelistUids.get(uid)
- && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ final boolean wasDenylisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
+ final boolean isDenylisted = policy == POLICY_REJECT_METERED_BACKGROUND;
+ final boolean wasAllowlisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
+ final boolean isAllowlisted = policy == POLICY_ALLOW_METERED_BACKGROUND;
+ final boolean wasBlocked = wasDenylisted || (mRestrictBackground && !wasAllowlisted);
+ final boolean isBlocked = isDenylisted || (mRestrictBackground && !isAllowlisted);
+ if ((wasAllowlisted && (!isAllowlisted || isDenylisted))
+ && mDefaultRestrictBackgroundAllowlistUids.get(uid)
+ && !mRestrictBackgroundAllowlistRevokedUids.get(uid)) {
if (LOGD)
- Slog.d(TAG, "Adding uid " + uid + " to revoked restrict background whitelist");
- mRestrictBackgroundWhitelistRevokedUids.append(uid, true);
+ Slog.d(TAG, "Adding uid " + uid + " to revoked restrict background allowlist");
+ mRestrictBackgroundAllowlistRevokedUids.append(uid, true);
}
notifyApp = wasBlocked != isBlocked;
}
@@ -2700,11 +2700,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mLogger.removingUserState(userId);
boolean changed = false;
- // Remove entries from revoked default restricted background UID whitelist
- for (int i = mRestrictBackgroundWhitelistRevokedUids.size() - 1; i >= 0; i--) {
- final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+ // Remove entries from revoked default restricted background UID allowlist
+ for (int i = mRestrictBackgroundAllowlistRevokedUids.size() - 1; i >= 0; i--) {
+ final int uid = mRestrictBackgroundAllowlistRevokedUids.keyAt(i);
if (UserHandle.getUserId(uid) == userId) {
- mRestrictBackgroundWhitelistRevokedUids.removeAt(i);
+ mRestrictBackgroundAllowlistRevokedUids.removeAt(i);
changed = true;
}
}
@@ -2913,7 +2913,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.d(TAG, "setRestrictBackgroundUL(): " + restrictBackground + "; reason: " + reason);
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
- // Must whitelist foreground apps before turning data saver mode on.
+ // Must allowlist foreground apps before turning data saver mode on.
// TODO: there is no need to iterate through all apps here, just those in the foreground,
// so it could call AM to get the UIDs of such apps, and iterate through them instead.
updateRulesForRestrictBackgroundUL();
@@ -2966,7 +2966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Binder.restoreCallingIdentity(token);
}
if (policy == POLICY_REJECT_METERED_BACKGROUND) {
- // App is blacklisted.
+ // App is denylisted.
return RESTRICT_BACKGROUND_STATUS_ENABLED;
}
if (!mRestrictBackground) {
@@ -3543,25 +3543,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.decreaseIndent();
}
- size = mDefaultRestrictBackgroundWhitelistUids.size();
+ size = mDefaultRestrictBackgroundAllowlistUids.size();
if (size > 0) {
- fout.println("Default restrict background whitelist uids:");
+ fout.println("Default restrict background allowlist uids:");
fout.increaseIndent();
for (int i = 0; i < size; i++) {
fout.print("UID=");
- fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.print(mDefaultRestrictBackgroundAllowlistUids.keyAt(i));
fout.println();
}
fout.decreaseIndent();
}
- size = mRestrictBackgroundWhitelistRevokedUids.size();
+ size = mRestrictBackgroundAllowlistRevokedUids.size();
if (size > 0) {
- fout.println("Default restrict background whitelist uids revoked by users:");
+ fout.println("Default restrict background allowlist uids revoked by users:");
fout.increaseIndent();
for (int i = 0; i < size; i++) {
fout.print("UID=");
- fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+ fout.print(mRestrictBackgroundAllowlistRevokedUids.keyAt(i));
fout.println();
}
fout.decreaseIndent();
@@ -3882,7 +3882,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
void updateRuleForAppIdleUL(int uid) {
- if (!isUidValidForBlacklistRulesUL(uid)) return;
+ if (!isUidValidForDenylistRulesUL(uid)) return;
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRuleForAppIdleUL: " + uid );
@@ -3915,13 +3915,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final SparseIntArray blockedUids = new SparseIntArray();
for (int i = 0; i < ruleCount; i++) {
final int uid = mUidFirewallStandbyRules.keyAt(i);
- if (!isUidValidForBlacklistRulesUL(uid)) {
+ if (!isUidValidForDenylistRulesUL(uid)) {
continue;
}
int oldRules = mUidRules.get(uid);
if (enableChain) {
// Chain wasn't enabled before and the other power-related
- // chains are whitelists, so we can clear the
+ // chains are allowlists, so we can clear the
// MASK_ALL_NETWORKS part of the rules and re-inform listeners if
// the effective rules result in blocking network access.
oldRules &= MASK_METERED_NETWORKS;
@@ -4079,10 +4079,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// TODO: the MEDIA / DRM restriction might not be needed anymore, in which case both
// methods below could be merged into a isUidValidForRules() method.
@GuardedBy("mUidRulesFirstLock")
- private boolean isUidValidForBlacklistRulesUL(int uid) {
+ private boolean isUidValidForDenylistRulesUL(int uid) {
// allow rules on specific system services, and any apps
if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
- || isUidValidForWhitelistRulesUL(uid)) {
+ || isUidValidForAllowlistRulesUL(uid)) {
return true;
}
@@ -4090,7 +4090,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@GuardedBy("mUidRulesFirstLock")
- private boolean isUidValidForWhitelistRulesUL(int uid) {
+ private boolean isUidValidForAllowlistRulesUL(int uid) {
return UserHandle.isApp(uid) && hasInternetPermissionUL(uid);
}
@@ -4235,23 +4235,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Applies network rules to bandwidth controllers based on process state and user-defined
- * restrictions (blacklist / whitelist).
+ * restrictions (allowlist / denylist).
*
* <p>
* {@code netd} defines 3 firewall chains that govern whether an app has access to metered
* networks:
* <ul>
- * <li>@{code bw_penalty_box}: UIDs added to this chain do not have access (blacklist).
- * <li>@{code bw_happy_box}: UIDs added to this chain have access (whitelist), unless they're
- * also blacklisted.
+ * <li>@{code bw_penalty_box}: UIDs added to this chain do not have access (denylist).
+ * <li>@{code bw_happy_box}: UIDs added to this chain have access (allowlist), unless they're
+ * also denylisted.
* <li>@{code bw_data_saver}: when enabled (through {@link #setRestrictBackground(boolean)}),
- * no UIDs other than those whitelisted will have access.
+ * no UIDs other than those allowlisted will have access.
* <ul>
*
* <p>The @{code bw_penalty_box} and @{code bw_happy_box} are primarily managed through the
- * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
- * {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
- * respectively): these methods set the proper internal state (blacklist / whitelist), then call
+ * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundAllowlistedUid(int)} /
+ * {@link #removeRestrictBackgroundDenylistedUid(int)} methods (for denylist and allowlist
+ * respectively): these methods set the proper internal state (denylist / allowlist), then call
* this ({@link #updateRulesForDataUsageRestrictionsUL(int)}) to propagate the rules to
* {@link INetworkManagementService}, but this method should also be called in events (like
* Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
@@ -4260,7 +4260,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* <ul>
* <li>When Data Saver mode is on, the foreground app should be temporarily added to
* {@code bw_happy_box} before the @{code bw_data_saver} chain is enabled.
- * <li>If the foreground app is blacklisted by the user, it should be temporarily removed from
+ * <li>If the foreground app is denylisted by the user, it should be temporarily removed from
* {@code bw_penalty_box}.
* <li>When the app leaves foreground state, the temporary changes above should be reverted.
* </ul>
@@ -4285,7 +4285,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
private void updateRulesForDataUsageRestrictionsULInner(int uid) {
- if (!isUidValidForWhitelistRulesUL(uid)) {
+ if (!isUidValidForAllowlistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
return;
}
@@ -4295,8 +4295,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
- final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- final boolean isWhitelisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
+ final boolean isDenylisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ final boolean isAllowlisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
int newRule = RULE_NONE;
@@ -4304,15 +4304,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (isRestrictedByAdmin) {
newRule = RULE_REJECT_METERED;
} else if (isForeground) {
- if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
+ if (isDenylisted || (mRestrictBackground && !isAllowlisted)) {
newRule = RULE_TEMPORARY_ALLOW_METERED;
- } else if (isWhitelisted) {
+ } else if (isAllowlisted) {
newRule = RULE_ALLOW_METERED;
}
} else {
- if (isBlacklisted) {
+ if (isDenylisted) {
newRule = RULE_REJECT_METERED;
- } else if (mRestrictBackground && isWhitelisted) {
+ } else if (mRestrictBackground && isAllowlisted) {
newRule = RULE_ALLOW_METERED;
}
}
@@ -4321,8 +4321,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ ": isForeground=" +isForeground
- + ", isBlacklisted=" + isBlacklisted
- + ", isWhitelisted=" + isWhitelisted
+ + ", isDenylisted=" + isDenylisted
+ + ", isAllowlisted=" + isAllowlisted
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", oldRule=" + uidRulesToString(oldRule)
+ ", newRule=" + uidRulesToString(newRule)
@@ -4339,49 +4339,49 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Second step: apply bw changes based on change of state.
if (newRule != oldRule) {
if (hasRule(newRule, RULE_TEMPORARY_ALLOW_METERED)) {
- // Temporarily whitelist foreground app, removing from blacklist if necessary
+ // Temporarily allowlist foreground app, removing from denylist if necessary
// (since bw_penalty_box prevails over bw_happy_box).
- setMeteredNetworkWhitelist(uid, true);
+ setMeteredNetworkAllowlist(uid, true);
// TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
// but ideally it should be just:
- // setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (isBlacklisted) {
- setMeteredNetworkBlacklist(uid, false);
+ // setMeteredNetworkDenylist(uid, isDenylisted);
+ if (isDenylisted) {
+ setMeteredNetworkDenylist(uid, false);
}
} else if (hasRule(oldRule, RULE_TEMPORARY_ALLOW_METERED)) {
- // Remove temporary whitelist from app that is not on foreground anymore.
+ // Remove temporary allowlist from app that is not on foreground anymore.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
// but ideally they should be just:
- // setMeteredNetworkWhitelist(uid, isWhitelisted);
- // setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (!isWhitelisted) {
- setMeteredNetworkWhitelist(uid, false);
+ // setMeteredNetworkAllowlist(uid, isAllowlisted);
+ // setMeteredNetworkDenylist(uid, isDenylisted);
+ if (!isAllowlisted) {
+ setMeteredNetworkAllowlist(uid, false);
}
- if (isBlacklisted || isRestrictedByAdmin) {
- setMeteredNetworkBlacklist(uid, true);
+ if (isDenylisted || isRestrictedByAdmin) {
+ setMeteredNetworkDenylist(uid, true);
}
} else if (hasRule(newRule, RULE_REJECT_METERED)
|| hasRule(oldRule, RULE_REJECT_METERED)) {
- // Flip state because app was explicitly added or removed to blacklist.
- setMeteredNetworkBlacklist(uid, (isBlacklisted || isRestrictedByAdmin));
- if (hasRule(oldRule, RULE_REJECT_METERED) && isWhitelisted) {
- // Since blacklist prevails over whitelist, we need to handle the special case
- // where app is whitelisted and blacklisted at the same time (although such
- // scenario should be blocked by the UI), then blacklist is removed.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ // Flip state because app was explicitly added or removed to denylist.
+ setMeteredNetworkDenylist(uid, (isDenylisted || isRestrictedByAdmin));
+ if (hasRule(oldRule, RULE_REJECT_METERED) && isAllowlisted) {
+ // Since dneylist prevails over allowlist, we need to handle the special case
+ // where app is allowlisted and denylisted at the same time (although such
+ // scenario should be blocked by the UI), then denylist is removed.
+ setMeteredNetworkAllowlist(uid, isAllowlisted);
}
} else if (hasRule(newRule, RULE_ALLOW_METERED)
|| hasRule(oldRule, RULE_ALLOW_METERED)) {
- // Flip state because app was explicitly added or removed to whitelist.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ // Flip state because app was explicitly added or removed to allowlist.
+ setMeteredNetworkAllowlist(uid, isAllowlisted);
} else {
// All scenarios should have been covered above.
Log.wtf(TAG, "Unexpected change of metered UID state for " + uid
+ ": foreground=" + isForeground
- + ", whitelisted=" + isWhitelisted
- + ", blacklisted=" + isBlacklisted
+ + ", allowlisted=" + isAllowlisted
+ + ", denylisted=" + isDenylisted
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules));
@@ -4397,7 +4397,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* listeners in case of change.
* <p>
* There are 3 power-related rules that affects whether an app has background access on
- * non-metered networks, and when the condition applies and the UID is not whitelisted for power
+ * non-metered networks, and when the condition applies and the UID is not allowlisted for power
* restriction, it's added to the equivalent firewall chain:
* <ul>
* <li>App is idle: {@code fw_standby} firewall chain.
@@ -4406,7 +4406,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* </ul>
* <p>
* This method updates the power-related part of the {@link #mUidRules} for a given uid based on
- * these modes, the UID process state (foreground or not), and the UIDwhitelist state.
+ * these modes, the UID process state (foreground or not), and the UID allowlist state.
* <p>
* <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
*/
@@ -4450,7 +4450,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules,
boolean isUidIdle) {
- if (!isUidValidForBlacklistRulesUL(uid)) {
+ if (!isUidValidForDenylistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
return RULE_NONE;
}
@@ -4859,23 +4859,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private void setMeteredNetworkBlacklist(int uid, boolean enable) {
- if (LOGV) Slog.v(TAG, "setMeteredNetworkBlacklist " + uid + ": " + enable);
+ private void setMeteredNetworkDenylist(int uid, boolean enable) {
+ if (LOGV) Slog.v(TAG, "setMeteredNetworkDenylist " + uid + ": " + enable);
try {
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, enable);
+ mNetworkManager.setUidMeteredNetworkDenylist(uid, enable);
} catch (IllegalStateException e) {
- Log.wtf(TAG, "problem setting blacklist (" + enable + ") rules for " + uid, e);
+ Log.wtf(TAG, "problem setting denylist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
- private void setMeteredNetworkWhitelist(int uid, boolean enable) {
- if (LOGV) Slog.v(TAG, "setMeteredNetworkWhitelist " + uid + ": " + enable);
+ private void setMeteredNetworkAllowlist(int uid, boolean enable) {
+ if (LOGV) Slog.v(TAG, "setMeteredNetworkAllowlist " + uid + ": " + enable);
try {
- mNetworkManager.setUidMeteredNetworkWhitelist(uid, enable);
+ mNetworkManager.setUidMeteredNetworkAllowlist(uid, enable);
} catch (IllegalStateException e) {
- Log.wtf(TAG, "problem setting whitelist (" + enable + ") rules for " + uid, e);
+ Log.wtf(TAG, "problem setting allowlist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -4936,7 +4936,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Add or remove a uid to the firewall blacklist for all network ifaces.
+ * Add or remove a uid to the firewall denylist for all network ifaces.
*/
private void setUidFirewallRule(int chain, int uid, int rule) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
@@ -4966,7 +4966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Add or remove a uid to the firewall blacklist for all network ifaces.
+ * Add or remove a uid to the firewall denylist for all network ifaces.
*/
@GuardedBy("mUidRulesFirstLock")
private void enableFirewallChainUL(int chain, boolean enable) {
@@ -4995,8 +4995,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
mNetworkManager
.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager.setUidMeteredNetworkWhitelist(uid, false);
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, false);
+ mNetworkManager.setUidMeteredNetworkAllowlist(uid, false);
+ mNetworkManager.setUidMeteredNetworkDenylist(uid, false);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem resetting firewall uid rules for " + uid, e);
} catch (RemoteException e) {
@@ -5189,13 +5189,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
reason = NTWK_ALLOWED_NON_METERED;
}
else if (hasRule(uidRules, RULE_REJECT_METERED)) {
- reason = NTWK_BLOCKED_BLACKLIST;
+ reason = NTWK_BLOCKED_DENYLIST;
}
else if (hasRule(uidRules, RULE_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_WHITELIST;
+ reason = NTWK_ALLOWED_ALLOWLIST;
}
else if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_TMP_WHITELIST;
+ reason = NTWK_ALLOWED_TMP_ALLOWLIST;
}
else if (isBackgroundRestricted) {
reason = NTWK_BLOCKED_BG_RESTRICT;
@@ -5208,13 +5208,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
switch(reason) {
case NTWK_ALLOWED_DEFAULT:
case NTWK_ALLOWED_NON_METERED:
- case NTWK_ALLOWED_TMP_WHITELIST:
- case NTWK_ALLOWED_WHITELIST:
+ case NTWK_ALLOWED_TMP_ALLOWLIST:
+ case NTWK_ALLOWED_ALLOWLIST:
case NTWK_ALLOWED_SYSTEM:
blocked = false;
break;
case NTWK_BLOCKED_POWER:
- case NTWK_BLOCKED_BLACKLIST:
+ case NTWK_BLOCKED_DENYLIST:
case NTWK_BLOCKED_BG_RESTRICT:
blocked = true;
break;
@@ -5234,7 +5234,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void resetUserState(int userId) {
synchronized (mUidRulesFirstLock) {
boolean changed = removeUserStateUL(userId, false, true);
- changed = addDefaultRestrictBackgroundWhitelistUidsUL(userId) || changed;
+ changed = addDefaultRestrictBackgroundAllowlistUidsUL(userId) || changed;
if (changed) {
synchronized (mNetworkPoliciesSecondLock) {
writePolicyAL();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d71c33e6e6f5..2d052da22714 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7288,12 +7288,12 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mToastQueue")
private void keepProcessAliveForToastIfNeededLocked(int pid) {
- int toastCount = 0; // toasts from this pid
+ int toastCount = 0; // toasts from this pid, rendered by the app
ArrayList<ToastRecord> list = mToastQueue;
int n = list.size();
for (int i = 0; i < n; i++) {
ToastRecord r = list.get(i);
- if (r.pid == pid) {
+ if (r.pid == pid && r.keepProcessAlive()) {
toastCount++;
}
}
diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
index 2b91a00f9da5..17e0b39ea890 100644
--- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java
@@ -71,6 +71,13 @@ public class CustomToastRecord extends ToastRecord {
}
@Override
+ public boolean keepProcessAlive() {
+ // As custom toasts are rendered by the app, we need to keep the app alive for it to show
+ // the toast.
+ return true;
+ }
+
+ @Override
public String toString() {
return "CustomToastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java
index 7915f7013227..33906ccd3cd1 100644
--- a/services/core/java/com/android/server/notification/toast/ToastRecord.java
+++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java
@@ -85,4 +85,14 @@ public abstract class ToastRecord {
}
pw.println(prefix + this);
}
+
+ /**
+ * Returns whether it's necessary to bump the process state to keep it alive in order to show
+ * the toast.
+ */
+ public boolean keepProcessAlive() {
+ // By default we assume the toast is rendered by the systemUI. Any toast rendered by the app
+ // should override this method.
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 55e7ca8ca838..840645edcb82 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -442,7 +442,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
// After reboot housekeeping.
for (int i = 0; i < mSessions.size(); ++i) {
PackageInstallerSession session = mSessions.valueAt(i);
- session.onAfterSessionRead();
+ session.onAfterSessionRead(mSessions);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 05026a0cafb6..ff9edd511e84 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -122,7 +122,7 @@ import android.util.ArraySet;
import android.util.ExceptionUtils;
import android.util.MathUtils;
import android.util.Slog;
-import android.util.SparseIntArray;
+import android.util.SparseArray;
import android.util.apk.ApkSignatureVerifier;
import com.android.internal.R;
@@ -336,7 +336,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private PackageParser.SigningDetails mSigningDetails;
@GuardedBy("mLock")
- private SparseIntArray mChildSessionIds = new SparseIntArray();
+ private SparseArray<PackageInstallerSession> mChildSessions = new SparseArray<>();
@GuardedBy("mLock")
private int mParentSessionId;
@@ -589,7 +589,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
this.mShouldBeSealed = sealed;
if (childSessionIds != null) {
for (int childSessionId : childSessionIds) {
- mChildSessionIds.put(childSessionId, 0);
+ // Null values will be resolved to actual object references in
+ // #onAfterSessionRead later.
+ mChildSessions.put(childSessionId, null);
}
}
this.mParentSessionId = parentSessionId;
@@ -708,10 +710,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.isStaged = params.isStaged;
info.rollbackDataPolicy = params.rollbackDataPolicy;
info.parentSessionId = mParentSessionId;
- info.childSessionIds = mChildSessionIds.copyKeys();
- if (info.childSessionIds == null) {
- info.childSessionIds = EMPTY_CHILD_SESSION_ARRAY;
- }
+ info.childSessionIds = getChildSessionIdsLocked();
info.isStagedSessionApplied = mStagedSessionApplied;
info.isStagedSessionReady = mStagedSessionReady;
info.isStagedSessionFailed = mStagedSessionFailed;
@@ -1159,27 +1158,22 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
if (isMultiPackage()) {
- final SparseIntArray remainingSessions;
- final int[] childSessionIds;
synchronized (mLock) {
- remainingSessions = mChildSessionIds.clone();
- childSessionIds = mChildSessionIds.copyKeys();
- }
- final IntentSender childIntentSender =
- new ChildStatusIntentReceiver(remainingSessions, statusReceiver)
- .getIntentSender();
- boolean sealFailed = false;
- for (int i = childSessionIds.length - 1; i >= 0; --i) {
- final int childSessionId = childSessionIds[i];
- // seal all children, regardless if any of them fail; we'll throw/return
- // as appropriate once all children have been processed
- if (!mSessionProvider.getSession(childSessionId)
- .markAsSealed(childIntentSender, forTransfer)) {
- sealFailed = true;
+ final IntentSender childIntentSender =
+ new ChildStatusIntentReceiver(mChildSessions.clone(), statusReceiver)
+ .getIntentSender();
+ boolean sealFailed = false;
+ for (int i = mChildSessions.size() - 1; i >= 0; --i) {
+ // seal all children, regardless if any of them fail; we'll throw/return
+ // as appropriate once all children have been processed
+ if (!mChildSessions.valueAt(i)
+ .markAsSealed(childIntentSender, forTransfer)) {
+ sealFailed = true;
+ }
+ }
+ if (sealFailed) {
+ return;
}
- }
- if (sealFailed) {
- return;
}
}
@@ -1218,21 +1212,20 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
if (isMultiPackage()) {
- final int[] childSessionIds;
+ final List<PackageInstallerSession> childSessions;
synchronized (mLock) {
- childSessionIds = mChildSessionIds.copyKeys();
+ childSessions = getChildSessionsLocked();
}
- int childCount = childSessionIds.length;
+ int childCount = childSessions.size();
// This will contain all child sessions that do not encounter an unrecoverable failure
ArrayList<PackageInstallerSession> nonFailingSessions = new ArrayList<>(childCount);
for (int i = childCount - 1; i >= 0; --i) {
- final int childSessionId = childSessionIds[i];
// commit all children, regardless if any of them fail; we'll throw/return
// as appropriate once all children have been processed
try {
- PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
+ PackageInstallerSession session = childSessions.get(i);
allSessionsReady &= session.streamValidateAndCommit();
nonFailingSessions.add(session);
} catch (PackageManagerException e) {
@@ -1293,7 +1286,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
private class ChildStatusIntentReceiver {
- private final SparseIntArray mChildSessionsRemaining;
+ private final SparseArray<PackageInstallerSession> mChildSessionsRemaining;
private final IntentSender mStatusReceiver;
private final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
@Override
@@ -1303,7 +1296,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
};
- private ChildStatusIntentReceiver(SparseIntArray remainingSessions,
+ private ChildStatusIntentReceiver(SparseArray<PackageInstallerSession> remainingSessions,
IntentSender statusReceiver) {
this.mChildSessionsRemaining = remainingSessions;
this.mStatusReceiver = statusReceiver;
@@ -1413,8 +1406,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private boolean markAsSealed(@NonNull IntentSender statusReceiver, boolean forTransfer) {
Objects.requireNonNull(statusReceiver);
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
-
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotDestroyedLocked("commit");
@@ -1446,7 +1437,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
try {
- sealLocked(childSessions);
+ sealLocked();
} catch (PackageManagerException e) {
return false;
}
@@ -1487,21 +1478,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return true;
}
- /** Return a list of child sessions or null if the session is not multipackage
- *
- * <p> This method is handy to prevent potential deadlocks (b/123391593)
- */
- private @Nullable List<PackageInstallerSession> getChildSessionsNotLocked() {
- if (Thread.holdsLock(mLock)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
- + " is holding mLock", new Throwable());
- }
+ @GuardedBy("mLock")
+ private @Nullable List<PackageInstallerSession> getChildSessionsLocked() {
List<PackageInstallerSession> childSessions = null;
if (isMultiPackage()) {
- final int[] childSessionIds = getChildSessionIds();
- childSessions = new ArrayList<>(childSessionIds.length);
- for (int childSessionId : childSessionIds) {
- childSessions.add(mSessionProvider.getSession(childSessionId));
+ int size = mChildSessions.size();
+ childSessions = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ childSessions.add(mChildSessions.valueAt(i));
}
}
return childSessions;
@@ -1563,14 +1547,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* session was sealed this is the only possible exception.
*/
@GuardedBy("mLock")
- private void sealLocked(List<PackageInstallerSession> childSessions)
+ private void sealLocked()
throws PackageManagerException {
try {
assertNoWriteFileTransfersOpenLocked();
assertPreparedAndNotDestroyedLocked("sealing of session");
mSealed = true;
-
+ List<PackageInstallerSession> childSessions = getChildSessionsLocked();
if (childSessions != null) {
assertMultiPackageConsistencyLocked(childSessions);
}
@@ -1657,17 +1641,30 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
*
* <p> This is meant to be called after all of the sessions are loaded and added to
* PackageInstallerService
+ *
+ * @param allSessions All sessions loaded by PackageInstallerService, guaranteed to be
+ * immutable by the caller during the method call. Used to resolve child
+ * sessions Ids to actual object reference.
*/
- void onAfterSessionRead() {
+ void onAfterSessionRead(SparseArray<PackageInstallerSession> allSessions) {
synchronized (mLock) {
+ // Resolve null values to actual object references
+ for (int i = mChildSessions.size() - 1; i >= 0; --i) {
+ int childSessionId = mChildSessions.keyAt(i);
+ PackageInstallerSession childSession = allSessions.get(childSessionId);
+ if (childSession != null) {
+ mChildSessions.setValueAt(i, childSession);
+ } else {
+ Slog.e(TAG, "Child session not existed: " + childSessionId);
+ mChildSessions.removeAt(i);
+ }
+ }
+
if (!mShouldBeSealed || isStagedAndInTerminalState()) {
return;
}
- }
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
- synchronized (mLock) {
try {
- sealLocked(childSessions);
+ sealLocked();
if (isApexInstallation()) {
// APEX installations rely on certain fields to be populated after reboot.
@@ -1708,14 +1705,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new SecurityException("Can only transfer sessions that use public options");
}
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
-
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("transfer");
try {
- sealLocked(childSessions);
+ sealLocked();
} catch (PackageManagerException e) {
throw new IllegalArgumentException("Package is not valid", e);
}
@@ -1746,14 +1741,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- // For a multiPackage session, read the child sessions
- // outside of the lock, because reading the child
- // sessions with the lock held could lead to deadlock
- // (b/123391593).
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
-
try {
- verifyNonStaged(childSessions);
+ verifyNonStaged();
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
@@ -1762,7 +1751,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- private void verifyNonStaged(List<PackageInstallerSession> childSessions)
+ private void verifyNonStaged()
throws PackageManagerException {
final PackageManagerService.VerificationParams verifyingSession =
makeVerificationParams();
@@ -1770,6 +1759,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
if (isMultiPackage()) {
+ final List<PackageInstallerSession> childSessions;
+ synchronized (mLock) {
+ childSessions = getChildSessionsLocked();
+ }
List<PackageManagerService.VerificationParams> verifyingChildSessions =
new ArrayList<>(childSessions.size());
boolean success = true;
@@ -1803,7 +1796,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- private void installNonStaged(List<PackageInstallerSession> childSessions)
+ private void installNonStaged()
throws PackageManagerException {
final PackageManagerService.InstallParams installingSession =
makeInstallParams();
@@ -1811,6 +1804,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
if (isMultiPackage()) {
+ final List<PackageInstallerSession> childSessions;
+ synchronized (mLock) {
+ childSessions = getChildSessionsLocked();
+ }
List<PackageManagerService.InstallParams> installingChildSessions =
new ArrayList<>(childSessions.size());
boolean success = true;
@@ -2004,9 +2001,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
try {
- installNonStaged(childSessions);
+ installNonStaged();
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
@@ -2741,15 +2737,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- /**
- * Adds a child session ID without any safety / sanity checks. This should only be used to
- * build a session from XML or similar.
- */
- @GuardedBy("mLock")
- void addChildSessionIdLocked(int sessionId) {
- mChildSessionIds.put(sessionId, 0);
- }
-
public void open() throws IOException {
if (mActiveCount.getAndIncrement() == 0) {
mCallback.onSessionActiveChanged(this, true);
@@ -2804,7 +2791,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
+ getParentSessionId() + " and may not be abandoned directly.");
}
- List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
synchronized (mLock) {
if (params.isStaged && mDestroyed) {
// If a user abandons staged session in an unsafe state, then system will try to
@@ -2828,7 +2814,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mCallback.onStagedSessionChanged(this);
return;
}
- cleanStageDir(childSessions);
+ cleanStageDir(getChildSessionsLocked());
}
if (mRelinquished) {
@@ -3149,8 +3135,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private int[] getChildSessionIdsLocked() {
- final int[] childSessionIds = mChildSessionIds.copyKeys();
- return childSessionIds != null ? childSessionIds : EMPTY_CHILD_SESSION_ARRAY;
+ int size = mChildSessions.size();
+ if (size == 0) {
+ return EMPTY_CHILD_SESSION_ARRAY;
+ }
+ final int[] childSessionIds = new int[size];
+ for (int i = 0; i < size; ++i) {
+ childSessionIds[i] = mChildSessions.keyAt(i);
+ }
+ return childSessionIds;
}
@Override
@@ -3205,12 +3198,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotSealedLocked("addChildSessionId");
- final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
+ final int indexOfSession = mChildSessions.indexOfKey(childSessionId);
if (indexOfSession >= 0) {
return;
}
childSession.setParentSessionId(this.sessionId);
- addChildSessionIdLocked(childSessionId);
+ mChildSessions.put(childSessionId, childSession);
}
} finally {
releaseTransactionLock();
@@ -3220,30 +3213,23 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public void removeChildSessionId(int sessionId) {
- final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
- try {
- acquireTransactionLock();
- if (session != null) {
- session.acquireTransactionLock();
- }
-
- synchronized (mLock) {
- assertCallerIsOwnerOrRootLocked();
- assertPreparedAndNotSealedLocked("removeChildSessionId");
+ synchronized (mLock) {
+ assertCallerIsOwnerOrRootLocked();
+ assertPreparedAndNotSealedLocked("removeChildSessionId");
- final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
- if (indexOfSession < 0) {
- // not added in the first place; no-op
- return;
- }
- if (session != null) {
- session.setParentSessionId(SessionInfo.INVALID_ID);
- }
- mChildSessionIds.removeAt(indexOfSession);
+ final int indexOfSession = mChildSessions.indexOfKey(sessionId);
+ if (indexOfSession < 0) {
+ // not added in the first place; no-op
+ return;
}
- } finally {
- releaseTransactionLock();
- if (session != null) {
+ PackageInstallerSession session = mChildSessions.valueAt(indexOfSession);
+ try {
+ acquireTransactionLock();
+ session.acquireTransactionLock();
+ session.setParentSessionId(SessionInfo.INVALID_ID);
+ mChildSessions.removeAt(indexOfSession);
+ } finally {
+ releaseTransactionLock();
session.releaseTransactionLock();
}
}
@@ -3334,6 +3320,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
/** {@hide} */
void setStagedSessionFailed(@StagedSessionErrorCode int errorCode, String errorMessage) {
+ List<PackageInstallerSession> childSessions;
synchronized (mLock) {
// Do not allow destroyed/failed staged session to change state
if (mDestroyed || mStagedSessionFailed) return;
@@ -3343,13 +3330,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionErrorCode = errorCode;
mStagedSessionErrorMessage = errorMessage;
Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
+ childSessions = getChildSessionsLocked();
}
- cleanStageDirNotLocked();
+ cleanStageDir(childSessions);
mCallback.onStagedSessionChanged(this);
}
/** {@hide} */
void setStagedSessionApplied() {
+ List<PackageInstallerSession> childSessions;
synchronized (mLock) {
// Do not allow destroyed/failed staged session to change state
if (mDestroyed || mStagedSessionFailed) return;
@@ -3359,8 +3348,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
mStagedSessionErrorMessage = "";
Slog.d(TAG, "Marking session " + sessionId + " as applied");
+ childSessions = getChildSessionsLocked();
}
- cleanStageDirNotLocked();
+ cleanStageDir(childSessions);
mCallback.onStagedSessionChanged(this);
}
@@ -3428,23 +3418,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- /**
- * <b>must not hold {@link #mLock}</b>
- */
- private void cleanStageDirNotLocked() {
- if (Thread.holdsLock(mLock)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
- + " is holding mLock", new Throwable());
- }
- cleanStageDir(getChildSessionsNotLocked());
- }
-
private void cleanStageDir(List<PackageInstallerSession> childSessions) {
if (childSessions != null) {
for (PackageInstallerSession childSession : childSessions) {
- if (childSession != null) {
- childSession.cleanStageDir();
- }
+ childSession.cleanStageDir();
}
} else {
cleanStageDir();
@@ -3504,7 +3481,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
pw.printPair("params.isMultiPackage", params.isMultiPackage);
pw.printPair("params.isStaged", params.isStaged);
pw.printPair("mParentSessionId", mParentSessionId);
- pw.printPair("mChildSessionIds", mChildSessionIds);
+ pw.printPair("mChildSessionIds", getChildSessionIdsLocked());
pw.printPair("mStagedSessionApplied", mStagedSessionApplied);
pw.printPair("mStagedSessionFailed", mStagedSessionFailed);
pw.printPair("mStagedSessionReady", mStagedSessionReady);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index bf9506ad51f1..8b2ba9c98f23 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4786,6 +4786,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
+ pw.println();
pw.println("Device properties:");
pw.println(" Device owner id:" + mDeviceOwnerUserId);
pw.println();
@@ -4814,12 +4815,9 @@ public class UserManagerService extends IUserManager.Stub {
}
pw.println(']');
}
-
synchronized (mUsersLock) {
- pw.println();
- pw.print("Cached user IDs: ");
+ pw.print(" Cached user IDs: ");
pw.println(Arrays.toString(mUserIds));
- pw.println();
}
} // synchronized (mPackagesLock)
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 3c1d189dc102..f7e9e34a4702 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -139,6 +139,11 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_CONFIG_PRIVATE_DNS
});
+ public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE
+ );
+
/**
* Set of user restriction which we don't want to persist.
*/
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 03868e922bdd..548cd70de4d1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -450,7 +450,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile int mPendingWakeKey = PENDING_KEY_NULL;
int mRecentAppsHeldModifiers;
- boolean mLanguageSwitchKeyPressed;
int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
boolean mHaveBuiltInKeyboard;
@@ -933,6 +932,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);
+
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
@@ -952,7 +953,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
- || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
+ || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted
+ || handledByPowerManager;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
@@ -2935,12 +2937,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
return -1;
}
- if (mLanguageSwitchKeyPressed && !down
- && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
- || keyCode == KeyEvent.KEYCODE_SPACE)) {
- mLanguageSwitchKeyPressed = false;
- return -1;
- }
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f9a49c9d8244..882ed1b7960b 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -86,6 +86,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import android.view.KeyEvent;
import com.android.internal.BrightnessSynchronizer;
import com.android.internal.annotations.VisibleForTesting;
@@ -892,19 +893,13 @@ public final class PowerManagerService extends SystemService
|| def == INVALID_BRIGHTNESS_IN_CONFIG) {
mScreenBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessSettingMinimum),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessSettingMinimum));
mScreenBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessSettingMaximum),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessSettingMaximum));
mScreenBrightnessDefault = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessSettingDefault),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessSettingDefault));
} else {
mScreenBrightnessMinimum = min;
mScreenBrightnessMaximum = max;
@@ -913,18 +908,14 @@ public final class PowerManagerService extends SystemService
if (doze == INVALID_BRIGHTNESS_IN_CONFIG) {
mScreenBrightnessDoze = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessDoze), PowerManager.BRIGHTNESS_OFF + 1,
- PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
- PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessDoze));
} else {
mScreenBrightnessDoze = doze;
}
if (dim == INVALID_BRIGHTNESS_IN_CONFIG) {
mScreenBrightnessDim = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessDim), PowerManager.BRIGHTNESS_OFF + 1,
- PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
- PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessDim));
} else {
mScreenBrightnessDim = dim;
}
@@ -939,19 +930,13 @@ public final class PowerManagerService extends SystemService
|| vrDef == INVALID_BRIGHTNESS_IN_CONFIG) {
mScreenBrightnessMinimumVr = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingMinimum),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessForVrSettingMinimum));
mScreenBrightnessMaximumVr = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingMaximum),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessForVrSettingMaximum));
mScreenBrightnessDefaultVr = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingDefault),
- PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
- PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
+ .config_screenBrightnessForVrSettingDefault));
} else {
mScreenBrightnessMinimumVr = vrMin;
mScreenBrightnessMaximumVr = vrMax;
@@ -3590,8 +3575,7 @@ public final class PowerManagerService extends SystemService
mDozeScreenStateOverrideFromDreamManager = screenState;
mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness;
mDozeScreenBrightnessOverrideFromDreamManagerFloat =
- BrightnessSynchronizer.brightnessIntToFloat(mContext,
- mDozeScreenBrightnessOverrideFromDreamManager);
+ BrightnessSynchronizer.brightnessIntToFloat(mDozeScreenBrightnessOverrideFromDreamManager);
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
@@ -5393,6 +5377,29 @@ public final class PowerManagerService extends SystemService
}
}
+ /**
+ * If the user presses power while the proximity sensor is enabled and keeping
+ * the screen off, then turn the screen back on by telling display manager to
+ * ignore the proximity sensor. We don't turn off the proximity sensor because
+ * we still want it to be reenabled if it's state changes.
+ *
+ * @return True if the proximity sensor was successfully ignored and we should
+ * consume the key event.
+ */
+ private boolean interceptPowerKeyDownInternal(KeyEvent event) {
+ synchronized (mLock) {
+ // DisplayPowerController only reports proximity positive (near) if it's
+ // positive and the proximity wasn't already being ignored. So it reliably
+ // also tells us that we're not already ignoring the proximity sensor.
+ if (mDisplayPowerRequest.useProximitySensor && mProximityPositive) {
+ mDisplayManagerInternal.ignoreProximitySensorUntilChanged();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@VisibleForTesting
final class LocalService extends PowerManagerInternal {
@Override
@@ -5525,5 +5532,10 @@ public final class PowerManagerService extends SystemService
public WakeData getLastWakeup() {
return getLastWakeupInternal();
}
+
+ @Override
+ public boolean interceptPowerKeyDown(KeyEvent event) {
+ return interceptPowerKeyDownInternal(event);
+ }
}
}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 4349ca451c36..2a74b3d23829 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -28,6 +28,8 @@ import static android.os.Process.SYSTEM_UID;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.app.AppOpsManager;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceSpec;
import android.app.usage.UsageStatsManagerInternal;
@@ -77,6 +79,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.function.Supplier;
public class SliceManagerService extends ISliceManager.Stub {
@@ -121,6 +124,7 @@ public class SliceManagerService extends ISliceManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
+ mRoleObserver = new RoleObserver();
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
}
@@ -478,10 +482,26 @@ public class SliceManagerService extends ISliceManager.Stub {
return cn.getPackageName();
}
+ /**
+ * A cached value of the default home app
+ */
+ private String mCachedDefaultHome = null;
+
// Based on getDefaultHome in ShortcutService.
// TODO: Unify if possible
@VisibleForTesting
protected String getDefaultHome(int userId) {
+
+ // Set VERIFY to true to run the cache in "shadow" mode for cache
+ // testing. Do not commit set to true;
+ final boolean VERIFY = false;
+
+ if (mCachedDefaultHome != null) {
+ if (!VERIFY) {
+ return mCachedDefaultHome;
+ }
+ }
+
final long token = Binder.clearCallingIdentity();
try {
final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
@@ -490,10 +510,12 @@ public class SliceManagerService extends ISliceManager.Stub {
final ComponentName defaultLauncher = mPackageManagerInternal
.getHomeActivitiesAsUser(allHomeCandidates, userId);
- ComponentName detected = null;
- if (defaultLauncher != null) {
- detected = defaultLauncher;
- }
+ ComponentName detected = defaultLauncher;
+
+ // Cache the default launcher. It is not a problem if the
+ // launcher is null - eventually, the default launcher will be
+ // set to something non-null.
+ mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null);
if (detected == null) {
// If we reach here, that means it's the first check since the user was created,
@@ -517,12 +539,54 @@ public class SliceManagerService extends ISliceManager.Stub {
lastPriority = ri.priority;
}
}
- return detected != null ? detected.getPackageName() : null;
+ final String ret = ((detected != null) ? detected.getPackageName() : null);
+ if (VERIFY) {
+ if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) {
+ Slog.e(TAG, "getDefaultHome() cache failure, is " +
+ mCachedDefaultHome + " should be " + ret);
+ }
+ }
+ return ret;
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ public void invalidateCachedDefaultHome() {
+ mCachedDefaultHome = null;
+ }
+
+ /**
+ * Listen for changes in the roles, and invalidate the cached default
+ * home as necessary.
+ */
+ private RoleObserver mRoleObserver;
+
+ class RoleObserver implements OnRoleHoldersChangedListener {
+ private RoleManager mRm;
+ private final Executor mExecutor;
+
+ RoleObserver() {
+ mExecutor = mContext.getMainExecutor();
+ register();
+ }
+
+ public void register() {
+ mRm = mContext.getSystemService(RoleManager.class);
+ if (mRm != null) {
+ mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
+ invalidateCachedDefaultHome();
+ }
+ }
+
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ if (RoleManager.ROLE_HOME.equals(roleName)) {
+ invalidateCachedDefaultHome();
+ }
+ }
+ }
+
private boolean isGrantedFullAccess(String pkg, int userId) {
return mPermissions.hasFullAccess(pkg, userId);
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index ecba3f9c27c4..1536473ff0a1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -177,7 +177,7 @@ final class AccessibilityController {
public void performComputeChangedWindowsNotLocked(int displayId, boolean forceSend) {
WindowsForAccessibilityObserver observer = null;
- synchronized (mService) {
+ synchronized (mService.mGlobalLock) {
final WindowsForAccessibilityObserver windowsForA11yObserver =
mWindowsForAccessibilityObserver.get(displayId);
if (windowsForA11yObserver != null) {
@@ -266,7 +266,7 @@ final class AccessibilityController {
// Not relevant for the display magnifier.
WindowsForAccessibilityObserver observer = null;
- synchronized (mService) {
+ synchronized (mService.mGlobalLock) {
final WindowsForAccessibilityObserver windowsForA11yObserver =
mWindowsForAccessibilityObserver.get(displayId);
if (windowsForA11yObserver != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e573d362fef4..5b8078729eee 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -107,6 +107,12 @@ import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_UNSET;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
@@ -172,12 +178,6 @@ import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchi
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.Task.ActivityState.DESTROYED;
@@ -294,6 +294,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -305,7 +306,6 @@ import com.android.server.am.AppTimeTracker;
import com.android.server.am.PendingIntentRecord;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriPermissionOwner;
import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 627361d780a2..31a9c5d4242c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2999,13 +2999,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void stopLockTaskModeByToken(IBinder token) {
- synchronized (mGlobalLock) {
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null) {
- return;
- }
- stopLockTaskModeInternal(r.getTask(), false /* isSystemCaller */);
- }
+ stopLockTaskModeInternal(token, false /* isSystemCaller */);
}
/**
@@ -3047,11 +3041,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- private void stopLockTaskModeInternal(@Nullable Task task, boolean isSystemCaller) {
+ private void stopLockTaskModeInternal(@Nullable IBinder token, boolean isSystemCaller) {
final int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
+ Task task = null;
+ if (token != null) {
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ return;
+ }
+ task = r.getTask();
+ }
getLockTaskController().stopLockTaskMode(task, isSystemCaller, callingUid);
}
// Launch in-call UI if a call is ongoing. This is necessary to allow stopping the lock
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 11a468be8f9f..f76108f332d1 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -67,10 +67,10 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe
import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE;
import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -127,11 +127,11 @@ import android.view.animation.TranslateAnimation;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils.Dump;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.AttributeCache;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.animation.ClipRectLRAnimation;
import com.android.server.wm.animation.ClipRectTBAnimation;
import com.android.server.wm.animation.CurvedTranslateAnimation;
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 5720e9b7f193..57d51c51c12b 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -41,14 +41,14 @@ import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -69,7 +69,7 @@ import android.view.WindowManager.TransitionType;
import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.ArrayList;
import java.util.LinkedList;
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index f563e57b363e..0b2c851c4366 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -16,13 +16,13 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import android.graphics.Rect;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.function.Supplier;
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 6ffb48282017..8bd42f03ff86 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -24,11 +24,11 @@ import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.util.Preconditions.checkState;
import static com.android.server.wm.DisplayAreaProto.IS_TASK_DISPLAY_AREA;
import static com.android.server.wm.DisplayAreaProto.NAME;
import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowContainerChildProto.DISPLAY_AREA;
import android.annotation.Nullable;
@@ -38,8 +38,8 @@ import android.util.proto.ProtoOutputStream;
import android.window.DisplayAreaInfo;
import android.window.IDisplayAreaOrganizer;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.util.Comparator;
import java.util.function.BiFunction;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fc170538994c..ba5a38290349 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -74,6 +74,14 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -94,14 +102,6 @@ import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -203,6 +203,7 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -211,7 +212,6 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.utils.DisplayRotationUtil;
import com.android.server.wm.utils.RotationCache;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -4063,9 +4063,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
// Send invalid rect and no width and height since it will screenshot the entire display.
- Rect frame = new Rect(0, 0, -1, -1);
- final Bitmap bitmap = SurfaceControl.screenshot(frame, 0, 0, inRotation,
- mDisplay.getRotation());
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setUseIdentityTransform(inRotation)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (bitmap == null) {
Slog.w(TAG_WM, "Failed to take screenshot");
return null;
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4f6f75d924c4..2e03cb80b189 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -112,6 +112,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
@@ -120,7 +121,6 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -187,6 +187,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.view.AppearanceRegion;
@@ -199,7 +200,6 @@ import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
import com.android.server.policy.WindowOrientationListener;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
import com.android.server.wm.utils.InsetUtils;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index c63128c15e8d..0206787ef226 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -22,8 +22,8 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,12 +58,12 @@ import android.window.WindowContainerTransaction;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowOrientationListener;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 22dd1d332345..133b11116460 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -18,11 +18,11 @@ package com.android.server.wm;
import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.DragDropController.MSG_ANIMATION_END;
import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT;
import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,9 +58,9 @@ import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.IDragAndDropPermissions;
import com.android.server.LocalServices;
-import com.android.server.protolog.common.ProtoLog;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index e7fbc334306e..86e2698302aa 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -16,13 +16,13 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import android.view.InsetsSource;
import android.view.WindowInsets;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 791f47128be0..0fe9735c9e46 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -41,7 +41,7 @@ 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_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -60,8 +60,8 @@ import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.Set;
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index f64149cee8c7..d1eb79556d1d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -24,7 +24,7 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL;
import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED;
@@ -40,8 +40,8 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.TriConsumer;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 9c978fd0c867..ab1074ee2821 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -30,7 +30,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -45,8 +45,8 @@ import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowManager;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.inputmethod.InputMethodManagerInternal;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -105,6 +105,10 @@ class InsetsStateController {
* @return The state stripped of the necessary information.
*/
InsetsState getInsetsForDispatch(@NonNull WindowState target) {
+ final InsetsState rotatedState = target.mToken.getFixedRotationTransformInsetsState();
+ if (rotatedState != null) {
+ return rotatedState;
+ }
final InsetsSourceProvider provider = target.getControllableInsetProvider();
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index d7b43bc5537d..6c416830b59e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -25,8 +25,8 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.TRANSIT_NONE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
@@ -41,9 +41,9 @@ import android.os.Trace;
import android.util.Slog;
import android.view.IRecentsAnimationRunner;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6b3a5d6bf18c..143fbb0fe48b 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -23,10 +23,10 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -56,12 +56,12 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index c255a18190f7..e7461e7d5517 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -37,9 +37,9 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.FastPrintWriter;
-import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1cb483c1d1a0..b3a3ed7eeba4 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -41,6 +41,11 @@ import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -59,11 +64,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATE
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
@@ -146,6 +146,7 @@ import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -155,7 +156,6 @@ import com.android.server.am.ActivityManagerService;
import com.android.server.am.AppTimeTracker;
import com.android.server.am.UserState;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index d7b8fb00d05c..3c8036d4e3b6 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -18,9 +18,9 @@ package com.android.server.wm;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.server.wm.AnimationSpecProto.ROTATE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.server.wm.RotationAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.RotationAnimationSpecProto.END_LUMA;
import static com.android.server.wm.RotationAnimationSpecProto.START_LUMA;
@@ -50,7 +50,7 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import com.android.internal.R;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.RotationAnimationUtils;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 86cbf3e3afe1..3b32a9d76258 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -24,7 +24,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,7 +58,7 @@ import android.view.SurfaceSession;
import android.view.WindowManager;
import com.android.internal.os.logging.MetricsLoggerWrapper;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java
index 1c9743041923..d9365c5d0666 100644
--- a/services/core/java/com/android/server/wm/SurfaceFreezer.java
+++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
@@ -28,7 +28,7 @@ import android.hardware.HardwareBuffer;
import android.view.Surface;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.function.Supplier;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index be0815b06051..ec7b1eed7f91 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -78,6 +78,8 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -116,8 +118,6 @@ import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.Task.ActivityState.PAUSED;
import static com.android.server.wm.Task.ActivityState.PAUSING;
import static com.android.server.wm.Task.ActivityState.RESUMED;
@@ -210,6 +210,7 @@ import android.window.ITaskOrganizer;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
@@ -218,7 +219,6 @@ import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.AppTimeTracker;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.uri.NeededUriGrants;
import org.xmlpull.v1.XmlPullParser;
@@ -7056,17 +7056,21 @@ class Task extends WindowContainer<WindowContainer> {
/**
* Reset local parameters because an app's activity died.
* @param app The app of the activity that died.
+ * @return {@code true} if the process of the pausing activity is died.
*/
- void handleAppDied(WindowProcessController app) {
+ boolean handleAppDied(WindowProcessController app) {
+ boolean isPausingDied = false;
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
mPausingActivity = null;
+ isPausingDied = true;
}
if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
+ return isPausingDied;
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index a847744247c7..32511108836e 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -32,13 +32,13 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
import static com.android.server.wm.DisplayContent.alwaysCreateStack;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.Task.STACK_VISIBILITY_VISIBLE;
@@ -58,10 +58,10 @@ import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 3fbc0373e1a9..a66cd846e8be 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -26,8 +26,8 @@ import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -59,7 +59,7 @@ import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.internal.policy.TaskResizingAlgorithm.CtrlType;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
class TaskPositioner implements IBinder.DeathRecipient {
private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 1103bf19b3bf..3def0911bd76 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -15,14 +15,14 @@
*/
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import android.hardware.HardwareBuffer;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.function.Function;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 9b18ac8f7702..e9ada6be7e7b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -41,7 +41,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.getNavigationBarRect;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -83,9 +83,9 @@ import android.view.WindowManagerGlobal;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DecorView;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.BaseIWindow;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-import com.android.server.protolog.common.ProtoLog;
/**
* This class represents a starting window that shows a snapshot.
diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
index f46701536cf8..38bff9ed3c31 100644
--- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
@@ -15,8 +15,8 @@
*/
package com.android.server.wm;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
@@ -26,7 +26,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6377a2169b34..5c6266a2f8c4 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
@@ -36,8 +36,8 @@ import android.util.TimeUtils;
import android.view.Choreographer;
import android.view.SurfaceControl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e24d185557e8..8a5e70f2e353 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -28,14 +28,14 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
import static android.view.SurfaceControl.Transaction;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
@@ -82,8 +82,8 @@ import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
index b75f886520e6..b9f67a590c2a 100644
--- a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
+++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
@@ -19,7 +19,7 @@ package com.android.server.wm;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
@@ -39,7 +39,7 @@ import android.view.SurfaceControl.Builder;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0b1d6bc0adfd..b33a8e9ef5df 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -84,22 +84,22 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -265,6 +265,8 @@ import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
@@ -281,8 +283,6 @@ import com.android.server.input.InputManagerService;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
import com.android.server.power.ShutdownThread;
-import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.utils.PriorityDump;
import com.android.server.wm.utils.DeviceConfigInterface;
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bdecb8d99752..271d2b1a002f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -31,7 +31,7 @@ import android.view.Surface;
import android.view.ViewDebug;
import com.android.internal.os.ByteTransferPipe;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogImpl;
import java.io.IOException;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index a58c5646858b..ab6e35b452a0 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1177,12 +1177,19 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
boolean handleAppDied() {
mAtm.mStackSupervisor.removeHistoryRecords(this);
- final boolean isRemoved = isRemoved();
boolean hasVisibleActivities = false;
if (mInactiveActivities != null && !mInactiveActivities.isEmpty()) {
// Make sure that all activities in this process are handled.
mActivities.addAll(mInactiveActivities);
}
+ if (isRemoved()) {
+ // The package of the died process should be force-stopped, so make its activities as
+ // finishing to prevent the process from being started again if the next top (or being
+ // visible) activity also resides in the same process. This must be done before removal.
+ for (int i = mActivities.size() - 1; i >= 0; i--) {
+ mActivities.get(i).makeFinishingLocked();
+ }
+ }
for (int i = mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mActivities.get(i);
if (r.mVisibleRequested || r.isVisible()) {
@@ -1191,16 +1198,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// is not yet committed, so isVisible()=true.
hasVisibleActivities = true;
}
- if (isRemoved) {
- // The package of the died process should be force-stopped, so make its activities
- // as finishing to prevent the process from being started again if the next top (or
- // being visible) activity also resides in the same process.
- r.makeFinishingLocked();
- }
final Task rootTask = r.getRootTask();
if (rootTask != null) {
- rootTask.handleAppDied(this);
+ // There may be a pausing activity that hasn't shown any window and was requested
+ // to be hidden. But pausing is also a visible state, it should be regarded as
+ // visible, so the caller can know the next activity should be resumed.
+ hasVisibleActivities |= rootTask.handleAppDied(this);
}
r.handleAppDied();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ab78e74b9e37..ebbd74aa7d1e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -101,6 +101,14 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFO
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RESIZE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
@@ -116,14 +124,6 @@ import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.MoveAnimationSpecProto.FROM;
import static com.android.server.wm.MoveAnimationSpecProto.TO;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -236,10 +236,10 @@ import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -1535,10 +1535,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
InsetsState getInsetsState() {
- final InsetsState insetsState = mToken.getFixedRotationTransformInsetsState();
- if (insetsState != null) {
- return insetsState;
- }
return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index d0101adaabad..16edb55939a3 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -31,13 +31,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_NONE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_DRAW;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
@@ -76,8 +76,8 @@ import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index b89cdd32e132..9b40822c8ab5 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -21,8 +21,8 @@ import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -40,7 +40,7 @@ import android.view.SurfaceControl;
import android.view.WindowContentFrameStats;
import android.view.WindowManager;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 2c1bb3ec51eb..f7cd37fb6748 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -23,10 +23,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -59,8 +59,8 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index ba3dc607f6cc..e8b8bfce21a3 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -34,7 +34,7 @@ import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogImpl;
import com.android.internal.util.TraceBuffer;
import java.io.File;
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 74e2328105dc..b6633ced771b 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -49,6 +49,8 @@ namespace aidl = android::hardware::vibrator;
namespace android {
+static JavaVM* sJvm = nullptr;
+
static jmethodID sMethodIdOnComplete;
static struct {
@@ -228,6 +230,15 @@ bool isValidEffect(jlong effect) {
return val >= *iter.begin() && val <= *std::prev(iter.end());
}
+static void callVibrationOnComplete(jobject vibration) {
+ if (vibration == nullptr) {
+ return;
+ }
+ auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+ jniEnv->CallVoidMethod(vibration, sMethodIdOnComplete);
+ jniEnv->DeleteGlobalRef(vibration);
+}
+
static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
aidl::CompositeEffect effect;
effect.primitive = static_cast<aidl::CompositePrimitive>(
@@ -273,18 +284,16 @@ static jboolean vibratorExists(JNIEnv* env, jclass /* clazz */, jlong controller
return controller->ping().isOk() ? JNI_TRUE : JNI_FALSE;
}
-static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms) {
- if (auto hal = getHal<aidl::IVibrator>()) {
- auto status = hal->call(&aidl::IVibrator::on, timeout_ms, nullptr);
- if (!status.isOk()) {
- ALOGE("vibratorOn command failed: %s", status.toString8().string());
- }
- } else {
- Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
- if (retStatus != Status::OK) {
- ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
- }
+static void vibratorOn(JNIEnv* env, jclass /* clazz */, jlong controllerPtr, jlong timeoutMs,
+ jobject vibration) {
+ vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr);
+ if (controller == nullptr) {
+ ALOGE("vibratorOn failed because controller was not initialized");
+ return;
}
+ jobject vibrationRef = vibration == nullptr ? vibration : MakeGlobalRefOrDie(env, vibration);
+ auto callback = [vibrationRef]() { callVibrationOnComplete(vibrationRef); };
+ controller->on(std::chrono::milliseconds(timeoutMs), callback);
}
static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong controllerPtr) {
@@ -399,10 +408,11 @@ static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong effect
return -1;
}
-static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jobjectArray composition,
- jobject vibration) {
- auto hal = getHal<aidl::IVibrator>();
- if (!hal) {
+static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr,
+ jobjectArray composition, jobject vibration) {
+ vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr);
+ if (controller == nullptr) {
+ ALOGE("vibratorPerformComposedEffect failed because controller was not initialized");
return;
}
size_t size = env->GetArrayLength(composition);
@@ -411,14 +421,9 @@ static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jobje
jobject element = env->GetObjectArrayElement(composition, i);
effects.push_back(effectFromJavaPrimitive(env, element));
}
- sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
-
- auto status = hal->call(&aidl::IVibrator::compose, effects, effectCallback);
- if (!status.isOk()) {
- if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
- ALOGE("Failed to play haptic effect composition");
- }
- }
+ jobject vibrationRef = vibration == nullptr ? vibration : MakeGlobalRefOrDie(env, vibration);
+ auto callback = [vibrationRef]() { callVibrationOnComplete(vibrationRef); };
+ controller->performComposedEffect(effects, callback);
}
static jlong vibratorGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong controllerPtr) {
@@ -456,13 +461,13 @@ static const JNINativeMethod method_table[] = {
{"vibratorInit", "()J", (void*)vibratorInit},
{"vibratorGetFinalizer", "()J", (void*)vibratorGetFinalizer},
{"vibratorExists", "(J)Z", (void*)vibratorExists},
- {"vibratorOn", "(J)V", (void*)vibratorOn},
+ {"vibratorOn", "(JJLcom/android/server/VibratorService$Vibration;)V", (void*)vibratorOn},
{"vibratorOff", "(J)V", (void*)vibratorOff},
{"vibratorSetAmplitude", "(JI)V", (void*)vibratorSetAmplitude},
{"vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;Z)J",
(void*)vibratorPerformEffect},
{"vibratorPerformComposedEffect",
- "([Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
+ "(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
"VibratorService$Vibration;)V",
(void*)vibratorPerformComposedEffect},
{"vibratorGetSupportedEffects", "(J)[I", (void*)vibratorGetSupportedEffects},
@@ -472,7 +477,8 @@ static const JNINativeMethod method_table[] = {
{"vibratorAlwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
};
-int register_android_server_VibratorService(JNIEnv *env) {
+int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env) {
+ sJvm = vm;
sMethodIdOnComplete =
GetMethodIDOrDie(env,
FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 935dffe5021e..9751c46f93c9 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -421,6 +421,10 @@ void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportO
AutoMutex _l(mLock);
mLocked.viewports = viewports;
mLocked.pointerDisplayId = pointerDisplayId;
+ std::shared_ptr<PointerController> controller = mLocked.pointerController.lock();
+ if (controller != nullptr) {
+ controller->onDisplayViewportsUpdated(mLocked.viewports);
+ }
} // release lock
mInputManager->getReader()->requestRefreshConfiguration(
@@ -818,8 +822,8 @@ void NativeInputManager::updateInactivityTimeoutLocked() REQUIRES(mLock) {
}
bool lightsOut = mLocked.systemUiVisibility & ASYSTEM_UI_VISIBILITY_STATUS_BAR_HIDDEN;
- controller->setInactivityTimeout(lightsOut ? PointerController::InactivityTimeout::SHORT
- : PointerController::InactivityTimeout::NORMAL);
+ controller->setInactivityTimeout(lightsOut ? InactivityTimeout::SHORT
+ : InactivityTimeout::NORMAL);
}
void NativeInputManager::setPointerSpeed(int32_t speed) {
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index e904645bda8f..9e2bb45ab341 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -314,31 +314,6 @@ static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shel
return result;
}
-static inline JNIEnv* GetJNIEnvironment(JavaVM* vm) {
- JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- return 0;
- }
- return env;
-}
-
-static inline JNIEnv* GetOrAttachJNIEnvironment(JavaVM* jvm) {
- JNIEnv* env = GetJNIEnvironment(jvm);
- if (!env) {
- int result = jvm->AttachCurrentThread(&env, nullptr);
- CHECK_EQ(result, JNI_OK) << "thread attach failed";
- struct VmDetacher {
- VmDetacher(JavaVM* vm) : mVm(vm) {}
- ~VmDetacher() { mVm->DetachCurrentThread(); }
-
- private:
- JavaVM* const mVm;
- };
- static thread_local VmDetacher detacher(jvm);
- }
- return env;
-}
-
class PMSCDataLoader;
struct OnTraceChanged {
@@ -415,7 +390,7 @@ private:
bool onPrepareImage(dataloader::DataLoaderInstallationFiles addedFiles) final {
ALOGE("onPrepareImage: start.");
- JNIEnv* env = GetOrAttachJNIEnvironment(mJvm);
+ JNIEnv* env = GetOrAttachJNIEnvironment(mJvm, JNI_VERSION_1_6);
const auto& jni = jniIds(env);
jobject shellCommand = env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 6f24e3b580b7..5df1adafed5e 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -37,7 +37,7 @@ int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbMidiDevice(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_vr_VrManagerService(JNIEnv* env);
-int register_android_server_VibratorService(JNIEnv* env);
+int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env);
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_TestNetworkService(JNIEnv* env);
@@ -90,7 +90,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_UsbAlsaJackDetector(env);
register_android_server_UsbHostManager(env);
register_android_server_vr_VrManagerService(env);
- register_android_server_VibratorService(env);
+ register_android_server_VibratorService(vm, env);
register_android_server_SystemServer(env);
register_android_server_location_GnssLocationProvider(env);
register_android_server_connectivity_Vpn(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
new file mode 100644
index 000000000000..6fea2aaf728b
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -0,0 +1,1116 @@
+/*
+ * 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.server.devicepolicy;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.TEXT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.FactoryResetProtectionPolicy;
+import android.app.admin.PasswordPolicy;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.pm.UserRestrictionsUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+
+class ActiveAdmin {
+ private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
+ private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
+ private static final String TAG_DISABLE_CAMERA = "disable-camera";
+ private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
+ private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
+ private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING =
+ "disable-bt-contacts-sharing";
+ private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
+ private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
+ private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
+ private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
+ private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
+ private static final String TAG_ACCOUNT_TYPE = "account-type";
+ private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES =
+ "permitted-accessiblity-services";
+ private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
+ private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
+ private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
+ private static final String TAG_TRUST_AGENT_COMPONENT = "component";
+ private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
+ private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
+ private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
+ private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
+ private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
+ private static final String TAG_PERMITTED_IMES = "permitted-imes";
+ private static final String TAG_PERMITTED_NOTIFICATION_LISTENERS =
+ "permitted-notification-listeners";
+ private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
+ private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
+ private static final String TAG_STRONG_AUTH_UNLOCK_TIMEOUT = "strong-auth-unlock-timeout";
+ private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
+ private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
+ private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
+ private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
+ private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
+ private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
+ private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
+ private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
+ private static final String TAG_PASSWORD_QUALITY = "password-quality";
+ private static final String TAG_POLICIES = "policies";
+ private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
+ "cross-profile-widget-providers";
+ private static final String TAG_PROVIDER = "provider";
+ private static final String TAG_PACKAGE_LIST_ITEM = "item";
+ private static final String TAG_KEEP_UNINSTALLED_PACKAGES = "keep-uninstalled-packages";
+ private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
+ private static final String TAG_DEFAULT_ENABLED_USER_RESTRICTIONS =
+ "default-enabled-user-restrictions";
+ private static final String TAG_RESTRICTION = "restriction";
+ private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
+ private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
+ private static final String TAG_PARENT_ADMIN = "parent-admin";
+ private static final String TAG_ORGANIZATION_COLOR = "organization-color";
+ private static final String TAG_ORGANIZATION_NAME = "organization-name";
+ private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
+ private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
+ private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
+ private static final String TAG_METERED_DATA_DISABLED_PACKAGES =
+ "metered_data_disabled_packages";
+ private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES =
+ "cross-profile-calendar-packages";
+ private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL =
+ "cross-profile-calendar-packages-null";
+ private static final String TAG_CROSS_PROFILE_PACKAGES = "cross-profile-packages";
+ private static final String TAG_FACTORY_RESET_PROTECTION_POLICY =
+ "factory_reset_protection_policy";
+ private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
+ private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
+ private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
+ private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
+ private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
+ private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
+ private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
+
+ DeviceAdminInfo info;
+
+ static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
+ int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
+
+ @NonNull
+ PasswordPolicy mPasswordPolicy = new PasswordPolicy();
+
+ @Nullable
+ FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
+
+ static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
+ long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
+
+ long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
+
+ static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
+ int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
+
+ static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
+ long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
+
+ static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
+ long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
+
+ static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+
+ int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
+
+ boolean encryptionRequested = false;
+ boolean testOnlyAdmin = false;
+ boolean disableCamera = false;
+ boolean disableCallerId = false;
+ boolean disableContactsSearch = false;
+ boolean disableBluetoothContactSharing = true;
+ boolean disableScreenCapture = false;
+ boolean requireAutoTime = false;
+ boolean forceEphemeralUsers = false;
+ boolean isNetworkLoggingEnabled = false;
+ boolean isLogoutEnabled = false;
+
+ // one notification after enabling + one more after reboots
+ static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
+ int numNetworkLoggingNotifications = 0;
+ long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
+
+ ActiveAdmin parentAdmin;
+ final boolean isParent;
+
+ static class TrustAgentInfo {
+ public PersistableBundle options;
+ TrustAgentInfo(PersistableBundle bundle) {
+ options = bundle;
+ }
+ }
+
+ // The list of packages which are not allowed to use metered data.
+ List<String> meteredDisabledPackages;
+
+ final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
+
+ // The list of permitted accessibility services package namesas set by a profile
+ // or device owner. Null means all accessibility services are allowed, empty means
+ // none except system services are allowed.
+ List<String> permittedAccessiblityServices;
+
+ // The list of permitted input methods package names as set by a profile or device owner.
+ // Null means all input methods are allowed, empty means none except system imes are
+ // allowed.
+ List<String> permittedInputMethods;
+
+ // The list of packages allowed to use a NotificationListenerService to receive events for
+ // notifications from this user. Null means that all packages are allowed. Empty list means
+ // that only packages from the system are allowed.
+ List<String> permittedNotificationListeners;
+
+ // List of package names to keep cached.
+ List<String> keepUninstalledPackages;
+
+ // TODO: review implementation decisions with frameworks team
+ boolean specifiesGlobalProxy = false;
+ String globalProxySpec = null;
+ String globalProxyExclusionList = null;
+
+ @NonNull
+ ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
+
+ List<String> crossProfileWidgetProviders;
+
+ Bundle userRestrictions;
+
+ // User restrictions that have already been enabled by default for this admin (either when
+ // setting the device or profile owner, or during a system update if one of those "enabled
+ // by default" restrictions is newly added).
+ final Set<String> defaultEnabledRestrictionsAlreadySet = new ArraySet<>();
+
+ // Support text provided by the admin to display to the user.
+ CharSequence shortSupportMessage = null;
+ CharSequence longSupportMessage = null;
+
+ // Background color of confirm credentials screen. Default: teal.
+ static final int DEF_ORGANIZATION_COLOR = Color.parseColor("#00796B");
+ int organizationColor = DEF_ORGANIZATION_COLOR;
+
+ // Default title of confirm credentials screen
+ String organizationName = null;
+
+ // Message for user switcher
+ String startUserSessionMessage = null;
+ String endUserSessionMessage = null;
+
+ // The allow list of packages that can access cross profile calendar APIs.
+ // This allow list should be in default an empty list, which indicates that no package
+ // is allow listed.
+ List<String> mCrossProfileCalendarPackages = Collections.emptyList();
+
+ // The allow list of packages that the admin has enabled to be able to request consent from
+ // the user to communicate cross-profile. By default, no packages are allowed, which is
+ // represented as an empty list.
+ List<String> mCrossProfilePackages = Collections.emptyList();
+
+ // Whether the admin explicitly requires personal apps to be suspended
+ boolean mSuspendPersonalApps = false;
+ // Maximum time the profile owned by this admin can be off.
+ long mProfileMaximumTimeOffMillis = 0;
+ // Time by which the profile should be turned on according to System.currentTimeMillis().
+ long mProfileOffDeadline = 0;
+
+ public String mAlwaysOnVpnPackage;
+ public boolean mAlwaysOnVpnLockdown;
+ boolean mCommonCriteriaMode;
+
+ ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
+ this.info = info;
+ this.isParent = isParent;
+ }
+
+ ActiveAdmin getParentActiveAdmin() {
+ Preconditions.checkState(!isParent);
+
+ if (parentAdmin == null) {
+ parentAdmin = new ActiveAdmin(info, /* parent */ true);
+ }
+ return parentAdmin;
+ }
+
+ boolean hasParentActiveAdmin() {
+ return parentAdmin != null;
+ }
+
+ int getUid() {
+ return info.getActivityInfo().applicationInfo.uid;
+ }
+
+ public UserHandle getUserHandle() {
+ return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
+ }
+
+ void writeToXml(XmlSerializer out)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ out.startTag(null, TAG_POLICIES);
+ info.writePoliciesToXml(out);
+ out.endTag(null, TAG_POLICIES);
+ if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
+ if (mPasswordPolicy.length != PasswordPolicy.DEF_MINIMUM_LENGTH) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LENGTH, mPasswordPolicy.length);
+ }
+ if (mPasswordPolicy.upperCase != PasswordPolicy.DEF_MINIMUM_UPPER_CASE) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_UPPERCASE, mPasswordPolicy.upperCase);
+ }
+ if (mPasswordPolicy.lowerCase != PasswordPolicy.DEF_MINIMUM_LOWER_CASE) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LOWERCASE, mPasswordPolicy.lowerCase);
+ }
+ if (mPasswordPolicy.letters != PasswordPolicy.DEF_MINIMUM_LETTERS) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LETTERS, mPasswordPolicy.letters);
+ }
+ if (mPasswordPolicy.numeric != PasswordPolicy.DEF_MINIMUM_NUMERIC) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NUMERIC, mPasswordPolicy.numeric);
+ }
+ if (mPasswordPolicy.symbols != PasswordPolicy.DEF_MINIMUM_SYMBOLS) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_SYMBOLS, mPasswordPolicy.symbols);
+ }
+ if (mPasswordPolicy.nonLetter > PasswordPolicy.DEF_MINIMUM_NON_LETTER) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NONLETTER, mPasswordPolicy.nonLetter);
+ }
+ }
+ if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_HISTORY_LENGTH, passwordHistoryLength);
+ }
+ if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
+ writeAttributeValueToXml(
+ out, TAG_MAX_TIME_TO_UNLOCK, maximumTimeToUnlock);
+ }
+ if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
+ writeAttributeValueToXml(
+ out, TAG_STRONG_AUTH_UNLOCK_TIMEOUT, strongAuthUnlockTimeout);
+ }
+ if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
+ writeAttributeValueToXml(
+ out, TAG_MAX_FAILED_PASSWORD_WIPE, maximumFailedPasswordsForWipe);
+ }
+ if (specifiesGlobalProxy) {
+ writeAttributeValueToXml(
+ out, TAG_SPECIFIES_GLOBAL_PROXY, specifiesGlobalProxy);
+ if (globalProxySpec != null) {
+ writeAttributeValueToXml(out, TAG_GLOBAL_PROXY_SPEC, globalProxySpec);
+ }
+ if (globalProxyExclusionList != null) {
+ writeAttributeValueToXml(
+ out, TAG_GLOBAL_PROXY_EXCLUSION_LIST, globalProxyExclusionList);
+ }
+ }
+ if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_TIMEOUT, passwordExpirationTimeout);
+ }
+ if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_DATE, passwordExpirationDate);
+ }
+ if (encryptionRequested) {
+ writeAttributeValueToXml(
+ out, TAG_ENCRYPTION_REQUESTED, encryptionRequested);
+ }
+ if (testOnlyAdmin) {
+ writeAttributeValueToXml(
+ out, TAG_TEST_ONLY_ADMIN, testOnlyAdmin);
+ }
+ if (disableCamera) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CAMERA, disableCamera);
+ }
+ if (disableCallerId) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CALLER_ID, disableCallerId);
+ }
+ if (disableContactsSearch) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CONTACTS_SEARCH, disableContactsSearch);
+ }
+ if (!disableBluetoothContactSharing) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING, disableBluetoothContactSharing);
+ }
+ if (disableScreenCapture) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_SCREEN_CAPTURE, disableScreenCapture);
+ }
+ if (requireAutoTime) {
+ writeAttributeValueToXml(
+ out, TAG_REQUIRE_AUTO_TIME, requireAutoTime);
+ }
+ if (forceEphemeralUsers) {
+ writeAttributeValueToXml(
+ out, TAG_FORCE_EPHEMERAL_USERS, forceEphemeralUsers);
+ }
+ if (isNetworkLoggingEnabled) {
+ out.startTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(isNetworkLoggingEnabled));
+ out.attribute(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS,
+ Integer.toString(numNetworkLoggingNotifications));
+ out.attribute(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION,
+ Long.toString(lastNetworkLoggingNotificationTimeMs));
+ out.endTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
+ }
+ if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_KEYGUARD_FEATURES, disabledKeyguardFeatures);
+ }
+ if (!accountTypesWithManagementDisabled.isEmpty()) {
+ writeAttributeValuesToXml(
+ out, TAG_DISABLE_ACCOUNT_MANAGEMENT, TAG_ACCOUNT_TYPE,
+ accountTypesWithManagementDisabled);
+ }
+ if (!trustAgentInfos.isEmpty()) {
+ Set<Map.Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
+ out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ for (Map.Entry<String, TrustAgentInfo> entry : set) {
+ TrustAgentInfo trustAgentInfo = entry.getValue();
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
+ out.attribute(null, ATTR_VALUE, entry.getKey());
+ if (trustAgentInfo.options != null) {
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+ try {
+ trustAgentInfo.options.saveToXml(out);
+ } catch (XmlPullParserException e) {
+ Log.e(DevicePolicyManagerService.LOG_TAG,
+ "Failed to save TrustAgent options", e);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
+ }
+ out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ }
+ if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
+ writeAttributeValuesToXml(
+ out, TAG_CROSS_PROFILE_WIDGET_PROVIDERS, TAG_PROVIDER,
+ crossProfileWidgetProviders);
+ }
+ writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
+ permittedAccessiblityServices);
+ writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
+ writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
+ permittedNotificationListeners);
+ writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
+ writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
+ if (hasUserRestrictions()) {
+ UserRestrictionsUtils.writeRestrictions(
+ out, userRestrictions, TAG_USER_RESTRICTIONS);
+ }
+ if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
+ writeAttributeValuesToXml(out, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS,
+ TAG_RESTRICTION,
+ defaultEnabledRestrictionsAlreadySet);
+ }
+ if (!TextUtils.isEmpty(shortSupportMessage)) {
+ writeTextToXml(out, TAG_SHORT_SUPPORT_MESSAGE, shortSupportMessage.toString());
+ }
+ if (!TextUtils.isEmpty(longSupportMessage)) {
+ writeTextToXml(out, TAG_LONG_SUPPORT_MESSAGE, longSupportMessage.toString());
+ }
+ if (parentAdmin != null) {
+ out.startTag(null, TAG_PARENT_ADMIN);
+ parentAdmin.writeToXml(out);
+ out.endTag(null, TAG_PARENT_ADMIN);
+ }
+ if (organizationColor != DEF_ORGANIZATION_COLOR) {
+ writeAttributeValueToXml(out, TAG_ORGANIZATION_COLOR, organizationColor);
+ }
+ if (organizationName != null) {
+ writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
+ }
+ if (isLogoutEnabled) {
+ writeAttributeValueToXml(out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
+ }
+ if (startUserSessionMessage != null) {
+ writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
+ }
+ if (endUserSessionMessage != null) {
+ writeTextToXml(out, TAG_END_USER_SESSION_MESSAGE, endUserSessionMessage);
+ }
+ if (mCrossProfileCalendarPackages == null) {
+ out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
+ out.endTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
+ } else {
+ writePackageListToXml(out, TAG_CROSS_PROFILE_CALENDAR_PACKAGES,
+ mCrossProfileCalendarPackages);
+ }
+ writePackageListToXml(out, TAG_CROSS_PROFILE_PACKAGES, mCrossProfilePackages);
+ if (mFactoryResetProtectionPolicy != null) {
+ out.startTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
+ mFactoryResetProtectionPolicy.writeToXml(out);
+ out.endTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
+ }
+ if (mSuspendPersonalApps) {
+ writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
+ }
+ if (mProfileMaximumTimeOffMillis != 0) {
+ writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF,
+ mProfileMaximumTimeOffMillis);
+ }
+ if (mProfileMaximumTimeOffMillis != 0) {
+ writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
+ }
+ if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
+ writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_PACKAGE, mAlwaysOnVpnPackage);
+ }
+ if (mAlwaysOnVpnLockdown) {
+ writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
+ }
+ if (mCommonCriteriaMode) {
+ writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
+ }
+ }
+
+ void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
+ out.startTag(null, tag);
+ out.text(text);
+ out.endTag(null, tag);
+ }
+
+ void writePackageListToXml(XmlSerializer out, String outerTag,
+ List<String> packageList)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ if (packageList == null) {
+ return;
+ }
+ writeAttributeValuesToXml(out, outerTag, TAG_PACKAGE_LIST_ITEM, packageList);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, String value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, value);
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, int value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Integer.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, long value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Long.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, boolean value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValuesToXml(XmlSerializer out, String outerTag, String innerTag,
+ @NonNull Collection<String> values) throws IOException {
+ out.startTag(null, outerTag);
+ for (String value : values) {
+ out.startTag(null, innerTag);
+ out.attribute(null, ATTR_VALUE, value);
+ out.endTag(null, innerTag);
+ }
+ out.endTag(null, outerTag);
+ }
+
+ void readFromXml(XmlPullParser parser, boolean shouldOverridePolicies)
+ throws XmlPullParserException, IOException {
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != END_DOCUMENT
+ && (type != END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == END_TAG || type == TEXT) {
+ continue;
+ }
+ String tag = parser.getName();
+ if (TAG_POLICIES.equals(tag)) {
+ if (shouldOverridePolicies) {
+ Log.d(DevicePolicyManagerService.LOG_TAG,
+ "Overriding device admin policies from XML.");
+ info.readPoliciesFromXml(parser);
+ }
+ } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
+ mPasswordPolicy.quality = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
+ mPasswordPolicy.length = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
+ passwordHistoryLength = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
+ mPasswordPolicy.upperCase = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
+ mPasswordPolicy.lowerCase = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
+ mPasswordPolicy.letters = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
+ mPasswordPolicy.numeric = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
+ mPasswordPolicy.symbols = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
+ mPasswordPolicy.nonLetter = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
+ maximumTimeToUnlock = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_STRONG_AUTH_UNLOCK_TIMEOUT.equals(tag)) {
+ strongAuthUnlockTimeout = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
+ maximumFailedPasswordsForWipe = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
+ specifiesGlobalProxy = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
+ globalProxySpec =
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
+ globalProxyExclusionList =
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
+ passwordExpirationTimeout = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
+ passwordExpirationDate = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
+ encryptionRequested = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_TEST_ONLY_ADMIN.equals(tag)) {
+ testOnlyAdmin = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CAMERA.equals(tag)) {
+ disableCamera = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
+ disableCallerId = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) {
+ disableContactsSearch = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
+ disableBluetoothContactSharing = Boolean.parseBoolean(parser
+ .getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
+ disableScreenCapture = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
+ requireAutoTime = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
+ forceEphemeralUsers = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_IS_NETWORK_LOGGING_ENABLED.equals(tag)) {
+ isNetworkLoggingEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ lastNetworkLoggingNotificationTimeMs = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION));
+ numNetworkLoggingNotifications = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS));
+ } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
+ disabledKeyguardFeatures = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
+ readAttributeValues(
+ parser, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
+ } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
+ trustAgentInfos = getAllTrustAgentInfos(parser, tag);
+ } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
+ crossProfileWidgetProviders = new ArrayList<>();
+ readAttributeValues(parser, TAG_PROVIDER, crossProfileWidgetProviders);
+ } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
+ permittedAccessiblityServices = readPackageList(parser, tag);
+ } else if (TAG_PERMITTED_IMES.equals(tag)) {
+ permittedInputMethods = readPackageList(parser, tag);
+ } else if (TAG_PERMITTED_NOTIFICATION_LISTENERS.equals(tag)) {
+ permittedNotificationListeners = readPackageList(parser, tag);
+ } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
+ keepUninstalledPackages = readPackageList(parser, tag);
+ } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
+ meteredDisabledPackages = readPackageList(parser, tag);
+ } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
+ userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
+ } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
+ readAttributeValues(
+ parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
+ } else if (TAG_SHORT_SUPPORT_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ shortSupportMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading short support message");
+ }
+ } else if (TAG_LONG_SUPPORT_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ longSupportMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading long support message");
+ }
+ } else if (TAG_PARENT_ADMIN.equals(tag)) {
+ Preconditions.checkState(!isParent);
+ parentAdmin = new ActiveAdmin(info, /* parent */ true);
+ parentAdmin.readFromXml(parser, shouldOverridePolicies);
+ } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
+ organizationColor = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ organizationName = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading organization name");
+ }
+ } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
+ isLogoutEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ startUserSessionMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading start session message");
+ }
+ } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ endUserSessionMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading end session message");
+ }
+ } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
+ mCrossProfileCalendarPackages = readPackageList(parser, tag);
+ } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL.equals(tag)) {
+ mCrossProfileCalendarPackages = null;
+ } else if (TAG_CROSS_PROFILE_PACKAGES.equals(tag)) {
+ mCrossProfilePackages = readPackageList(parser, tag);
+ } else if (TAG_FACTORY_RESET_PROTECTION_POLICY.equals(tag)) {
+ mFactoryResetProtectionPolicy = FactoryResetProtectionPolicy.readFromXml(
+ parser);
+ } else if (TAG_SUSPEND_PERSONAL_APPS.equals(tag)) {
+ mSuspendPersonalApps = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
+ mProfileMaximumTimeOffMillis =
+ Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
+ mProfileOffDeadline =
+ Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ALWAYS_ON_VPN_PACKAGE.equals(tag)) {
+ mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
+ mAlwaysOnVpnLockdown = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
+ mCommonCriteriaMode = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ }
+
+ private List<String> readPackageList(XmlPullParser parser,
+ String tag) throws XmlPullParserException, IOException {
+ List<String> result = new ArrayList<String>();
+ int outerDepth = parser.getDepth();
+ int outerType;
+ while ((outerType = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
+ continue;
+ }
+ String outerTag = parser.getName();
+ if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
+ String packageName = parser.getAttributeValue(null, ATTR_VALUE);
+ if (packageName != null) {
+ result.add(packageName);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Package name missing under " + outerTag);
+ }
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + outerTag);
+ }
+ }
+ return result;
+ }
+
+ private void readAttributeValues(
+ XmlPullParser parser, String tag, Collection<String> result)
+ throws XmlPullParserException, IOException {
+ result.clear();
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (tag.equals(tagDAM)) {
+ result.add(parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.e(DevicePolicyManagerService.LOG_TAG,
+ "Expected tag " + tag + " but found " + tagDAM);
+ }
+ }
+ }
+
+ @NonNull
+ private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
+ XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ final ArrayMap<String, TrustAgentInfo> result = new ArrayMap<>();
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
+ final String component = parser.getAttributeValue(null, ATTR_VALUE);
+ final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
+ result.put(component, trustAgentInfo);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
+ throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ TrustAgentInfo result = new TrustAgentInfo(null);
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
+ result.options = PersistableBundle.restoreFromXml(parser);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ boolean hasUserRestrictions() {
+ return userRestrictions != null && userRestrictions.size() > 0;
+ }
+
+ Bundle ensureUserRestrictions() {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
+ return userRestrictions;
+ }
+
+ public void transfer(DeviceAdminInfo deviceAdminInfo) {
+ if (hasParentActiveAdmin()) {
+ parentAdmin.info = deviceAdminInfo;
+ }
+ info = deviceAdminInfo;
+ }
+
+ Bundle addSyntheticRestrictions(Bundle restrictions) {
+ if (disableCamera) {
+ restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
+ }
+ if (requireAutoTime) {
+ restrictions.putBoolean(UserManager.DISALLOW_CONFIG_DATE_TIME, true);
+ }
+ return restrictions;
+ }
+
+ static Bundle removeDeprecatedRestrictions(Bundle restrictions) {
+ for (String deprecatedRestriction: UserRestrictionsUtils.DEPRECATED_USER_RESTRICTIONS) {
+ restrictions.remove(deprecatedRestriction);
+ }
+ return restrictions;
+ }
+
+ static Bundle filterRestrictions(Bundle restrictions, Predicate<String> filter) {
+ Bundle result = new Bundle();
+ for (String key : restrictions.keySet()) {
+ if (!restrictions.getBoolean(key)) {
+ continue;
+ }
+ if (filter.test(key)) {
+ result.putBoolean(key, true);
+ }
+ }
+ return result;
+ }
+
+ Bundle getEffectiveRestrictions() {
+ return addSyntheticRestrictions(
+ removeDeprecatedRestrictions(new Bundle(ensureUserRestrictions())));
+ }
+
+ Bundle getLocalUserRestrictions(int adminType) {
+ return filterRestrictions(getEffectiveRestrictions(),
+ key -> UserRestrictionsUtils.isLocal(adminType, key));
+ }
+
+ Bundle getGlobalUserRestrictions(int adminType) {
+ return filterRestrictions(getEffectiveRestrictions(),
+ key -> UserRestrictionsUtils.isGlobal(adminType, key));
+ }
+
+ void dump(IndentingPrintWriter pw) {
+ pw.print("uid=");
+ pw.println(getUid());
+
+ pw.print("testOnlyAdmin=");
+ pw.println(testOnlyAdmin);
+
+ pw.println("policies:");
+ ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
+ if (pols != null) {
+ pw.increaseIndent();
+ for (int i = 0; i < pols.size(); i++) {
+ pw.println(pols.get(i).tag);
+ }
+ pw.decreaseIndent();
+ }
+
+ pw.print("passwordQuality=0x");
+ pw.println(Integer.toHexString(mPasswordPolicy.quality));
+
+ pw.print("minimumPasswordLength=");
+ pw.println(mPasswordPolicy.length);
+
+ pw.print("passwordHistoryLength=");
+ pw.println(passwordHistoryLength);
+
+ pw.print("minimumPasswordUpperCase=");
+ pw.println(mPasswordPolicy.upperCase);
+
+ pw.print("minimumPasswordLowerCase=");
+ pw.println(mPasswordPolicy.lowerCase);
+
+ pw.print("minimumPasswordLetters=");
+ pw.println(mPasswordPolicy.letters);
+
+ pw.print("minimumPasswordNumeric=");
+ pw.println(mPasswordPolicy.numeric);
+
+ pw.print("minimumPasswordSymbols=");
+ pw.println(mPasswordPolicy.symbols);
+
+ pw.print("minimumPasswordNonLetter=");
+ pw.println(mPasswordPolicy.nonLetter);
+
+ pw.print("maximumTimeToUnlock=");
+ pw.println(maximumTimeToUnlock);
+
+ pw.print("strongAuthUnlockTimeout=");
+ pw.println(strongAuthUnlockTimeout);
+
+ pw.print("maximumFailedPasswordsForWipe=");
+ pw.println(maximumFailedPasswordsForWipe);
+
+ pw.print("specifiesGlobalProxy=");
+ pw.println(specifiesGlobalProxy);
+
+ pw.print("passwordExpirationTimeout=");
+ pw.println(passwordExpirationTimeout);
+
+ pw.print("passwordExpirationDate=");
+ pw.println(passwordExpirationDate);
+
+ if (globalProxySpec != null) {
+ pw.print("globalProxySpec=");
+ pw.println(globalProxySpec);
+ }
+ if (globalProxyExclusionList != null) {
+ pw.print("globalProxyEclusionList=");
+ pw.println(globalProxyExclusionList);
+ }
+ pw.print("encryptionRequested=");
+ pw.println(encryptionRequested);
+
+ pw.print("disableCamera=");
+ pw.println(disableCamera);
+
+ pw.print("disableCallerId=");
+ pw.println(disableCallerId);
+
+ pw.print("disableContactsSearch=");
+ pw.println(disableContactsSearch);
+
+ pw.print("disableBluetoothContactSharing=");
+ pw.println(disableBluetoothContactSharing);
+
+ pw.print("disableScreenCapture=");
+ pw.println(disableScreenCapture);
+
+ pw.print("requireAutoTime=");
+ pw.println(requireAutoTime);
+
+ pw.print("forceEphemeralUsers=");
+ pw.println(forceEphemeralUsers);
+
+ pw.print("isNetworkLoggingEnabled=");
+ pw.println(isNetworkLoggingEnabled);
+
+ pw.print("disabledKeyguardFeatures=");
+ pw.println(disabledKeyguardFeatures);
+
+ pw.print("crossProfileWidgetProviders=");
+ pw.println(crossProfileWidgetProviders);
+
+ if (permittedAccessiblityServices != null) {
+ pw.print("permittedAccessibilityServices=");
+ pw.println(permittedAccessiblityServices);
+ }
+
+ if (permittedInputMethods != null) {
+ pw.print("permittedInputMethods=");
+ pw.println(permittedInputMethods);
+ }
+
+ if (permittedNotificationListeners != null) {
+ pw.print("permittedNotificationListeners=");
+ pw.println(permittedNotificationListeners);
+ }
+
+ if (keepUninstalledPackages != null) {
+ pw.print("keepUninstalledPackages=");
+ pw.println(keepUninstalledPackages);
+ }
+
+ pw.print("organizationColor=");
+ pw.println(organizationColor);
+
+ if (organizationName != null) {
+ pw.print("organizationName=");
+ pw.println(organizationName);
+ }
+
+ pw.println("userRestrictions:");
+ UserRestrictionsUtils.dumpRestrictions(pw, " ", userRestrictions);
+
+ pw.print("defaultEnabledRestrictionsAlreadySet=");
+ pw.println(defaultEnabledRestrictionsAlreadySet);
+
+ pw.print("isParent=");
+ pw.println(isParent);
+
+ if (parentAdmin != null) {
+ pw.println("parentAdmin:");
+ pw.increaseIndent();
+ parentAdmin.dump(pw);
+ pw.decreaseIndent();
+ }
+
+ if (mCrossProfileCalendarPackages != null) {
+ pw.print("mCrossProfileCalendarPackages=");
+ pw.println(mCrossProfileCalendarPackages);
+ }
+
+ pw.print("mCrossProfilePackages=");
+ pw.println(mCrossProfilePackages);
+
+ pw.print("mSuspendPersonalApps=");
+ pw.println(mSuspendPersonalApps);
+
+ pw.print("mProfileMaximumTimeOffMillis=");
+ pw.println(mProfileMaximumTimeOffMillis);
+
+ pw.print("mProfileOffDeadline=");
+ pw.println(mProfileOffDeadline);
+
+ pw.print("mAlwaysOnVpnPackage=");
+ pw.println(mAlwaysOnVpnPackage);
+
+ pw.print("mAlwaysOnVpnLockdown=");
+ pw.println(mAlwaysOnVpnLockdown);
+
+ pw.print("mCommonCriteriaMode=");
+ pw.println(mCommonCriteriaMode);
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
new file mode 100644
index 000000000000..130cfd50b203
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -0,0 +1,566 @@
+/*
+ * 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.server.devicepolicy;
+
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.os.FileUtils;
+import android.os.PersistableBundle;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.JournaledFile;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+class DevicePolicyData {
+ private static final String TAG_ACCEPTED_CA_CERTIFICATES = "accepted-ca-certificate";
+ private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component";
+ private static final String TAG_LOCK_TASK_FEATURES = "lock-task-features";
+ private static final String TAG_STATUS_BAR = "statusbar";
+ private static final String TAG_APPS_SUSPENDED = "apps-suspended";
+ private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
+ private static final String TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT =
+ "do-not-ask-credentials-on-boot";
+ private static final String TAG_AFFILIATION_ID = "affiliation-id";
+ private static final String TAG_LAST_SECURITY_LOG_RETRIEVAL = "last-security-log-retrieval";
+ private static final String TAG_LAST_BUG_REPORT_REQUEST = "last-bug-report-request";
+ private static final String TAG_LAST_NETWORK_LOG_RETRIEVAL = "last-network-log-retrieval";
+ private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";
+ private static final String TAG_CURRENT_INPUT_METHOD_SET = "current-ime-set";
+ private static final String TAG_OWNER_INSTALLED_CA_CERT = "owner-installed-ca-cert";
+ private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";
+ private static final String TAG_PASSWORD_VALIDITY = "password-validity";
+ private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
+ private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_ALIAS = "alias";
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DISABLED = "disabled";
+ private static final String ATTR_SETUP_COMPLETE = "setup-complete";
+ private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
+ private static final String ATTR_PERMISSION_POLICY = "permission-policy";
+ private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
+ "device-provisioning-config-applied";
+ private static final String ATTR_DEVICE_PAIRED = "device-paired";
+
+ int mFailedPasswordAttempts = 0;
+ boolean mPasswordValidAtLastCheckpoint = true;
+
+ int mUserHandle;
+ int mPasswordOwner = -1;
+ long mLastMaximumTimeToLock = -1;
+ boolean mUserSetupComplete = false;
+ boolean mPaired = false;
+ int mUserProvisioningState;
+ int mPermissionPolicy;
+
+ boolean mDeviceProvisioningConfigApplied = false;
+
+ final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
+ final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
+ final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
+
+ // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
+ final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
+
+ // This is the list of component allowed to start lock task mode.
+ List<String> mLockTaskPackages = new ArrayList<>();
+
+ // List of packages protected by device owner
+ List<String> mUserControlDisabledPackages = new ArrayList<>();
+
+ // Bitfield of feature flags to be enabled during LockTask mode.
+ // We default on the power button menu, in order to be consistent with pre-P behaviour.
+ int mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
+
+ boolean mStatusBarDisabled = false;
+
+ ComponentName mRestrictionsProvider;
+
+ // Map of delegate package to delegation scopes
+ final ArrayMap<String, List<String>> mDelegationMap = new ArrayMap<>();
+
+ boolean mDoNotAskCredentialsOnBoot = false;
+
+ Set<String> mAffiliationIds = new ArraySet<>();
+
+ long mLastSecurityLogRetrievalTime = -1;
+
+ long mLastBugReportRequestTime = -1;
+
+ long mLastNetworkLogsRetrievalTime = -1;
+
+ boolean mCurrentInputMethodSet = false;
+
+ boolean mSecondaryLockscreenEnabled = false;
+
+ // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
+ Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
+
+ // Used for initialization of users created by createAndManageUser.
+ boolean mAdminBroadcastPending = false;
+ PersistableBundle mInitBundle = null;
+
+ long mPasswordTokenHandle = 0;
+
+ // Whether user's apps are suspended. This flag should only be written AFTER all the needed
+ // apps were suspended or unsuspended.
+ boolean mAppsSuspended = false;
+
+ DevicePolicyData(int userHandle) {
+ mUserHandle = userHandle;
+ }
+
+ /**
+ * Serializes DevicePolicyData object as XML.
+ */
+ static boolean store(DevicePolicyData policyData, JournaledFile file, boolean isFdeDevice) {
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(file.chooseForWrite(), false);
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, "policies");
+ if (policyData.mRestrictionsProvider != null) {
+ out.attribute(null, ATTR_PERMISSION_PROVIDER,
+ policyData.mRestrictionsProvider.flattenToString());
+ }
+ if (policyData.mUserSetupComplete) {
+ out.attribute(null, ATTR_SETUP_COMPLETE,
+ Boolean.toString(true));
+ }
+ if (policyData.mPaired) {
+ out.attribute(null, ATTR_DEVICE_PAIRED,
+ Boolean.toString(true));
+ }
+ if (policyData.mDeviceProvisioningConfigApplied) {
+ out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
+ Boolean.toString(true));
+ }
+ if (policyData.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
+ out.attribute(null, ATTR_PROVISIONING_STATE,
+ Integer.toString(policyData.mUserProvisioningState));
+ }
+ if (policyData.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
+ out.attribute(null, ATTR_PERMISSION_POLICY,
+ Integer.toString(policyData.mPermissionPolicy));
+ }
+
+ // Serialize delegations.
+ for (int i = 0; i < policyData.mDelegationMap.size(); ++i) {
+ final String delegatePackage = policyData.mDelegationMap.keyAt(i);
+ final List<String> scopes = policyData.mDelegationMap.valueAt(i);
+
+ // Every "delegation" tag serializes the information of one delegate-scope pair.
+ for (String scope : scopes) {
+ out.startTag(null, "delegation");
+ out.attribute(null, "delegatePackage", delegatePackage);
+ out.attribute(null, "scope", scope);
+ out.endTag(null, "delegation");
+ }
+ }
+
+ final int n = policyData.mAdminList.size();
+ for (int i = 0; i < n; i++) {
+ ActiveAdmin ap = policyData.mAdminList.get(i);
+ if (ap != null) {
+ out.startTag(null, "admin");
+ out.attribute(null, "name", ap.info.getComponent().flattenToString());
+ ap.writeToXml(out);
+ out.endTag(null, "admin");
+ }
+ }
+
+ if (policyData.mPasswordOwner >= 0) {
+ out.startTag(null, "password-owner");
+ out.attribute(null, "value", Integer.toString(policyData.mPasswordOwner));
+ out.endTag(null, "password-owner");
+ }
+
+ if (policyData.mFailedPasswordAttempts != 0) {
+ out.startTag(null, "failed-password-attempts");
+ out.attribute(null, "value", Integer.toString(policyData.mFailedPasswordAttempts));
+ out.endTag(null, "failed-password-attempts");
+ }
+
+ // For FDE devices only, we save this flag so we can report on password sufficiency
+ // before the user enters their password for the first time after a reboot. For
+ // security reasons, we don't want to store the full set of active password metrics.
+ if (isFdeDevice) {
+ out.startTag(null, TAG_PASSWORD_VALIDITY);
+ out.attribute(null, ATTR_VALUE,
+ Boolean.toString(policyData.mPasswordValidAtLastCheckpoint));
+ out.endTag(null, TAG_PASSWORD_VALIDITY);
+ }
+
+ for (int i = 0; i < policyData.mAcceptedCaCertificates.size(); i++) {
+ out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
+ out.attribute(null, ATTR_NAME, policyData.mAcceptedCaCertificates.valueAt(i));
+ out.endTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
+ }
+
+ for (int i = 0; i < policyData.mLockTaskPackages.size(); i++) {
+ String component = policyData.mLockTaskPackages.get(i);
+ out.startTag(null, TAG_LOCK_TASK_COMPONENTS);
+ out.attribute(null, "name", component);
+ out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
+ }
+
+ if (policyData.mLockTaskFeatures != DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
+ out.startTag(null, TAG_LOCK_TASK_FEATURES);
+ out.attribute(null, ATTR_VALUE, Integer.toString(policyData.mLockTaskFeatures));
+ out.endTag(null, TAG_LOCK_TASK_FEATURES);
+ }
+
+ if (policyData.mSecondaryLockscreenEnabled) {
+ out.startTag(null, TAG_SECONDARY_LOCK_SCREEN);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(true));
+ out.endTag(null, TAG_SECONDARY_LOCK_SCREEN);
+ }
+
+ if (policyData.mStatusBarDisabled) {
+ out.startTag(null, TAG_STATUS_BAR);
+ out.attribute(null, ATTR_DISABLED, Boolean.toString(policyData.mStatusBarDisabled));
+ out.endTag(null, TAG_STATUS_BAR);
+ }
+
+ if (policyData.mDoNotAskCredentialsOnBoot) {
+ out.startTag(null, TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT);
+ out.endTag(null, TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT);
+ }
+
+ for (String id : policyData.mAffiliationIds) {
+ out.startTag(null, TAG_AFFILIATION_ID);
+ out.attribute(null, ATTR_ID, id);
+ out.endTag(null, TAG_AFFILIATION_ID);
+ }
+
+ if (policyData.mLastSecurityLogRetrievalTime >= 0) {
+ out.startTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastSecurityLogRetrievalTime));
+ out.endTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
+ }
+
+ if (policyData.mLastBugReportRequestTime >= 0) {
+ out.startTag(null, TAG_LAST_BUG_REPORT_REQUEST);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastBugReportRequestTime));
+ out.endTag(null, TAG_LAST_BUG_REPORT_REQUEST);
+ }
+
+ if (policyData.mLastNetworkLogsRetrievalTime >= 0) {
+ out.startTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastNetworkLogsRetrievalTime));
+ out.endTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
+ }
+
+ if (policyData.mAdminBroadcastPending) {
+ out.startTag(null, TAG_ADMIN_BROADCAST_PENDING);
+ out.attribute(null, ATTR_VALUE,
+ Boolean.toString(policyData.mAdminBroadcastPending));
+ out.endTag(null, TAG_ADMIN_BROADCAST_PENDING);
+ }
+
+ if (policyData.mInitBundle != null) {
+ out.startTag(null, TAG_INITIALIZATION_BUNDLE);
+ policyData.mInitBundle.saveToXml(out);
+ out.endTag(null, TAG_INITIALIZATION_BUNDLE);
+ }
+
+ if (policyData.mPasswordTokenHandle != 0) {
+ out.startTag(null, TAG_PASSWORD_TOKEN_HANDLE);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mPasswordTokenHandle));
+ out.endTag(null, TAG_PASSWORD_TOKEN_HANDLE);
+ }
+
+ if (policyData.mCurrentInputMethodSet) {
+ out.startTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+ out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+ }
+
+ for (final String cert : policyData.mOwnerInstalledCaCerts) {
+ out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
+ out.attribute(null, ATTR_ALIAS, cert);
+ out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT);
+ }
+
+ for (int i = 0, size = policyData.mUserControlDisabledPackages.size(); i < size; i++) {
+ String packageName = policyData.mUserControlDisabledPackages.get(i);
+ out.startTag(null, TAG_PROTECTED_PACKAGES);
+ out.attribute(null, ATTR_NAME, packageName);
+ out.endTag(null, TAG_PROTECTED_PACKAGES);
+ }
+
+ if (policyData.mAppsSuspended) {
+ out.startTag(null, TAG_APPS_SUSPENDED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(policyData.mAppsSuspended));
+ out.endTag(null, TAG_APPS_SUSPENDED);
+ }
+
+ out.endTag(null, "policies");
+
+ out.endDocument();
+ stream.flush();
+ FileUtils.sync(stream);
+ stream.close();
+ file.commit();
+ return true;
+ } catch (XmlPullParserException | IOException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "failed writing file", e);
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException ex) {
+ // Ignore
+ }
+ file.rollback();
+ return false;
+ }
+ }
+
+ /**
+ * @param adminInfoSupplier function that queries DeviceAdminInfo from PackageManager
+ * @param ownerComponent device or profile owner component if any.
+ */
+ static boolean load(DevicePolicyData policy, boolean isFdeDevice, JournaledFile journaledFile,
+ Function<ComponentName, DeviceAdminInfo> adminInfoSupplier,
+ ComponentName ownerComponent) {
+ FileInputStream stream = null;
+ File file = journaledFile.chooseForRead();
+ boolean needsRewrite = false;
+ try {
+ stream = new FileInputStream(file);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, StandardCharsets.UTF_8.name());
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+ String tag = parser.getName();
+ if (!"policies".equals(tag)) {
+ throw new XmlPullParserException(
+ "Settings do not start with policies tag: found " + tag);
+ }
+
+ // Extract the permission provider component name if available
+ String permissionProvider = parser.getAttributeValue(null, ATTR_PERMISSION_PROVIDER);
+ if (permissionProvider != null) {
+ policy.mRestrictionsProvider =
+ ComponentName.unflattenFromString(permissionProvider);
+ }
+ String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
+ if (Boolean.toString(true).equals(userSetupComplete)) {
+ policy.mUserSetupComplete = true;
+ }
+ String paired = parser.getAttributeValue(null, ATTR_DEVICE_PAIRED);
+ if (Boolean.toString(true).equals(paired)) {
+ policy.mPaired = true;
+ }
+ String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
+ ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
+ if (Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
+ policy.mDeviceProvisioningConfigApplied = true;
+ }
+ String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
+ if (!TextUtils.isEmpty(provisioningState)) {
+ policy.mUserProvisioningState = Integer.parseInt(provisioningState);
+ }
+ String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
+ if (!TextUtils.isEmpty(permissionPolicy)) {
+ policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
+ }
+
+ parser.next();
+ int outerDepth = parser.getDepth();
+ policy.mLockTaskPackages.clear();
+ policy.mAdminList.clear();
+ policy.mAdminMap.clear();
+ policy.mAffiliationIds.clear();
+ policy.mOwnerInstalledCaCerts.clear();
+ policy.mUserControlDisabledPackages.clear();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tag = parser.getName();
+ if ("admin".equals(tag)) {
+ String name = parser.getAttributeValue(null, "name");
+ try {
+ DeviceAdminInfo dai = adminInfoSupplier.apply(
+ ComponentName.unflattenFromString(name));
+
+ if (dai != null) {
+ // b/123415062: If DA, overwrite with the stored policies that were
+ // agreed by the user to prevent apps from sneaking additional policies
+ // into updates.
+ boolean overwritePolicies = !dai.getComponent().equals(ownerComponent);
+ ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
+ ap.readFromXml(parser, overwritePolicies);
+ policy.mAdminMap.put(ap.info.getComponent(), ap);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Failed loading admin " + name, e);
+ }
+ } else if ("delegation".equals(tag)) {
+ // Parse delegation info.
+ final String delegatePackage = parser.getAttributeValue(null,
+ "delegatePackage");
+ final String scope = parser.getAttributeValue(null, "scope");
+
+ // Get a reference to the scopes list for the delegatePackage.
+ List<String> scopes = policy.mDelegationMap.get(delegatePackage);
+ // Or make a new list if none was found.
+ if (scopes == null) {
+ scopes = new ArrayList<>();
+ policy.mDelegationMap.put(delegatePackage, scopes);
+ }
+ // Add the new scope to the list of delegatePackage if it's not already there.
+ if (!scopes.contains(scope)) {
+ scopes.add(scope);
+ }
+ } else if ("failed-password-attempts".equals(tag)) {
+ policy.mFailedPasswordAttempts = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("password-owner".equals(tag)) {
+ policy.mPasswordOwner = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
+ policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
+ } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
+ policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
+ } else if (TAG_LOCK_TASK_FEATURES.equals(tag)) {
+ policy.mLockTaskFeatures = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_SECONDARY_LOCK_SCREEN.equals(tag)) {
+ policy.mSecondaryLockscreenEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_STATUS_BAR.equals(tag)) {
+ policy.mStatusBarDisabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_DISABLED));
+ } else if (TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT.equals(tag)) {
+ policy.mDoNotAskCredentialsOnBoot = true;
+ } else if (TAG_AFFILIATION_ID.equals(tag)) {
+ policy.mAffiliationIds.add(parser.getAttributeValue(null, ATTR_ID));
+ } else if (TAG_LAST_SECURITY_LOG_RETRIEVAL.equals(tag)) {
+ policy.mLastSecurityLogRetrievalTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_LAST_BUG_REPORT_REQUEST.equals(tag)) {
+ policy.mLastBugReportRequestTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_LAST_NETWORK_LOG_RETRIEVAL.equals(tag)) {
+ policy.mLastNetworkLogsRetrievalTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
+ String pending = parser.getAttributeValue(null, ATTR_VALUE);
+ policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
+ } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
+ policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
+ } else if ("active-password".equals(tag)) {
+ // Remove password metrics from saved settings, as we no longer wish to store
+ // these on disk
+ needsRewrite = true;
+ } else if (TAG_PASSWORD_VALIDITY.equals(tag)) {
+ if (isFdeDevice) {
+ // This flag is only used for FDE devices
+ policy.mPasswordValidAtLastCheckpoint = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ }
+ } else if (TAG_PASSWORD_TOKEN_HANDLE.equals(tag)) {
+ policy.mPasswordTokenHandle = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_CURRENT_INPUT_METHOD_SET.equals(tag)) {
+ policy.mCurrentInputMethodSet = true;
+ } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
+ policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
+ } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
+ policy.mUserControlDisabledPackages.add(
+ parser.getAttributeValue(null, ATTR_NAME));
+ } else if (TAG_APPS_SUSPENDED.equals(tag)) {
+ policy.mAppsSuspended =
+ Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown tag: " + tag);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Don't be noisy, this is normal if we haven't defined any policies.
+ } catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
+ | IndexOutOfBoundsException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "failed parsing " + file, e);
+ }
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+
+ // Generate a list of admins from the admin map
+ policy.mAdminList.addAll(policy.mAdminMap.values());
+ return needsRewrite;
+ }
+
+ void validatePasswordOwner() {
+ if (mPasswordOwner >= 0) {
+ boolean haveOwner = false;
+ for (int i = mAdminList.size() - 1; i >= 0; i--) {
+ if (mAdminList.get(i).getUid() == mPasswordOwner) {
+ haveOwner = true;
+ break;
+ }
+ }
+ if (!haveOwner) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Previous password owner "
+ + mPasswordOwner + " no longer active; disabling");
+ mPasswordOwner = -1;
+ }
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a2bef85860f..cafd56e5198b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -106,10 +106,6 @@ import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.A
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.END_TAG;
-import static org.xmlpull.v1.XmlPullParser.TEXT;
-
import android.Manifest.permission;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accounts.Account;
@@ -189,7 +185,6 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.Color;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -204,7 +199,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -248,7 +242,6 @@ import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.text.format.DateUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
@@ -280,7 +273,6 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
-import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockSettingsInternal;
import com.android.internal.widget.LockscreenCredential;
@@ -290,8 +282,7 @@ import com.android.server.LockGuard;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
-import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
+import com.android.server.devicepolicy.ActiveAdmin.TrustAgentInfo;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.pm.RestrictionsSet;
@@ -328,7 +319,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -350,55 +340,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String TRANSFER_OWNERSHIP_PARAMETERS_XML =
"transfer-ownership-parameters.xml";
- private static final String TAG_ACCEPTED_CA_CERTIFICATES = "accepted-ca-certificate";
-
- private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component";
-
- private static final String TAG_LOCK_TASK_FEATURES = "lock-task-features";
-
- private static final String TAG_STATUS_BAR = "statusbar";
-
- private static final String ATTR_DISABLED = "disabled";
-
- private static final String ATTR_NAME = "name";
-
- private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
- "do-not-ask-credentials-on-boot";
-
- private static final String TAG_AFFILIATION_ID = "affiliation-id";
-
- private static final String TAG_LAST_SECURITY_LOG_RETRIEVAL = "last-security-log-retrieval";
-
- private static final String TAG_LAST_BUG_REPORT_REQUEST = "last-bug-report-request";
-
- private static final String TAG_LAST_NETWORK_LOG_RETRIEVAL = "last-network-log-retrieval";
-
- private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";
-
- private static final String TAG_CURRENT_INPUT_METHOD_SET = "current-ime-set";
-
- private static final String TAG_OWNER_INSTALLED_CA_CERT = "owner-installed-ca-cert";
-
- private static final String ATTR_ID = "id";
-
- private static final String ATTR_VALUE = "value";
-
- private static final String ATTR_ALIAS = "alias";
-
- private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";
-
- private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
-
- private static final String TAG_PASSWORD_VALIDITY = "password-validity";
-
private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle";
- private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
-
- private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
-
- private static final String TAG_APPS_SUSPENDED = "apps-suspended";
-
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572;
@@ -423,17 +366,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
static final String ACTION_PROFILE_OFF_DEADLINE =
"com.android.server.ACTION_PROFILE_OFF_DEADLINE";
- private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
- private static final String ATTR_SETUP_COMPLETE = "setup-complete";
- private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
- private static final String ATTR_PERMISSION_POLICY = "permission-policy";
- private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
- "device-provisioning-config-applied";
- private static final String ATTR_DEVICE_PAIRED = "device-paired";
- private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
- private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
- = "application-restrictions-manager";
-
private static final String CALLED_FROM_PARENT = "calledFromParent";
private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
@@ -488,7 +420,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
private static final Set<Integer> DA_DISALLOWED_POLICIES;
// A collection of user restrictions that are deprecated and should simply be ignored.
- private static final Set<String> DEPRECATED_USER_RESTRICTIONS;
private static final String AB_DEVICE_KEY = "ro.build.ab_update";
static {
@@ -532,10 +463,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
-
- DEPRECATED_USER_RESTRICTIONS = Sets.newHashSet(
- UserManager.DISALLOW_ADD_MANAGED_PROFILE,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
}
/**
@@ -791,76 +718,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- public static class DevicePolicyData {
- int mFailedPasswordAttempts = 0;
- boolean mPasswordValidAtLastCheckpoint = true;
-
- int mUserHandle;
- int mPasswordOwner = -1;
- long mLastMaximumTimeToLock = -1;
- boolean mUserSetupComplete = false;
- boolean mPaired = false;
- int mUserProvisioningState;
- int mPermissionPolicy;
-
- boolean mDeviceProvisioningConfigApplied = false;
-
- final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
- final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
- final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
-
- // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
- final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
-
- // This is the list of component allowed to start lock task mode.
- List<String> mLockTaskPackages = new ArrayList<>();
-
- // List of packages protected by device owner
- List<String> mUserControlDisabledPackages = new ArrayList<>();
-
- // Bitfield of feature flags to be enabled during LockTask mode.
- // We default on the power button menu, in order to be consistent with pre-P behaviour.
- int mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
-
- boolean mStatusBarDisabled = false;
-
- ComponentName mRestrictionsProvider;
-
- // Map of delegate package to delegation scopes
- final ArrayMap<String, List<String>> mDelegationMap = new ArrayMap<>();
-
- boolean doNotAskCredentialsOnBoot = false;
-
- Set<String> mAffiliationIds = new ArraySet<>();
-
- long mLastSecurityLogRetrievalTime = -1;
-
- long mLastBugReportRequestTime = -1;
-
- long mLastNetworkLogsRetrievalTime = -1;
-
- boolean mCurrentInputMethodSet = false;
-
- boolean mSecondaryLockscreenEnabled = false;
-
- // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
- Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
-
- // Used for initialization of users created by createAndManageUser.
- boolean mAdminBroadcastPending = false;
- PersistableBundle mInitBundle = null;
-
- long mPasswordTokenHandle = 0;
-
- // Whether user's apps are suspended. This flag should only be written AFTER all the needed
- // apps were suspended or unsuspended.
- boolean mAppsSuspended = false;
-
- public DevicePolicyData(int userHandle) {
- mUserHandle = userHandle;
- }
- }
-
@GuardedBy("getLockObject()")
final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
@@ -1045,1002 +902,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- static class ActiveAdmin {
- private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
- private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
- private static final String TAG_DISABLE_CAMERA = "disable-camera";
- private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
- private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
- private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING
- = "disable-bt-contacts-sharing";
- private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
- private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
- private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
- private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
- private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
- private static final String TAG_ACCOUNT_TYPE = "account-type";
- private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
- = "permitted-accessiblity-services";
- private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
- private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
- private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
- private static final String TAG_TRUST_AGENT_COMPONENT = "component";
- private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
- private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
- private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
- private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
- private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
- private static final String TAG_PERMITTED_IMES = "permitted-imes";
- private static final String TAG_PERMITTED_NOTIFICATION_LISTENERS =
- "permitted-notification-listeners";
- private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
- private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
- private static final String TAG_STRONG_AUTH_UNLOCK_TIMEOUT = "strong-auth-unlock-timeout";
- private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
- private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
- private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
- private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
- private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
- private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
- private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
- private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
- private static final String ATTR_VALUE = "value";
- private static final String TAG_PASSWORD_QUALITY = "password-quality";
- private static final String TAG_POLICIES = "policies";
- private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
- "cross-profile-widget-providers";
- private static final String TAG_PROVIDER = "provider";
- private static final String TAG_PACKAGE_LIST_ITEM = "item";
- private static final String TAG_KEEP_UNINSTALLED_PACKAGES = "keep-uninstalled-packages";
- private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
- private static final String TAG_DEFAULT_ENABLED_USER_RESTRICTIONS =
- "default-enabled-user-restrictions";
- private static final String TAG_RESTRICTION = "restriction";
- private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
- private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
- private static final String TAG_PARENT_ADMIN = "parent-admin";
- private static final String TAG_ORGANIZATION_COLOR = "organization-color";
- private static final String TAG_ORGANIZATION_NAME = "organization-name";
- private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
- private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
- private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
- private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
- private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
- private static final String TAG_METERED_DATA_DISABLED_PACKAGES =
- "metered_data_disabled_packages";
- private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES =
- "cross-profile-calendar-packages";
- private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL =
- "cross-profile-calendar-packages-null";
- private static final String TAG_CROSS_PROFILE_PACKAGES = "cross-profile-packages";
- private static final String TAG_FACTORY_RESET_PROTECTION_POLICY =
- "factory_reset_protection_policy";
- private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
- private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
- private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
- private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
- private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
- private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
- DeviceAdminInfo info;
-
-
- static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
- int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
-
- @NonNull
- PasswordPolicy mPasswordPolicy = new PasswordPolicy();
-
- @Nullable
- FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
-
- static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
- long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
-
- long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
-
- static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
- int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
-
- static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
- long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
-
- static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
- long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
-
- static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
-
- int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
-
- boolean encryptionRequested = false;
- boolean testOnlyAdmin = false;
- boolean disableCamera = false;
- boolean disableCallerId = false;
- boolean disableContactsSearch = false;
- boolean disableBluetoothContactSharing = true;
- boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
- boolean requireAutoTime = false; // Can only be set by a device owner.
- boolean forceEphemeralUsers = false; // Can only be set by a device owner.
- boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
- boolean isLogoutEnabled = false; // Can only be set by a device owner.
-
- // one notification after enabling + one more after reboots
- static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
- int numNetworkLoggingNotifications = 0;
- long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
-
- ActiveAdmin parentAdmin;
- final boolean isParent;
-
- static class TrustAgentInfo {
- public PersistableBundle options;
- TrustAgentInfo(PersistableBundle bundle) {
- options = bundle;
- }
- }
-
- // The list of packages which are not allowed to use metered data.
- List<String> meteredDisabledPackages;
-
- final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
-
- // The list of permitted accessibility services package namesas set by a profile
- // or device owner. Null means all accessibility services are allowed, empty means
- // none except system services are allowed.
- List<String> permittedAccessiblityServices;
-
- // The list of permitted input methods package names as set by a profile or device owner.
- // Null means all input methods are allowed, empty means none except system imes are
- // allowed.
- List<String> permittedInputMethods;
-
- // The list of packages allowed to use a NotificationListenerService to receive events for
- // notifications from this user. Null means that all packages are allowed. Empty list means
- // that only packages from the system are allowed.
- List<String> permittedNotificationListeners;
-
- // List of package names to keep cached.
- List<String> keepUninstalledPackages;
-
- // TODO: review implementation decisions with frameworks team
- boolean specifiesGlobalProxy = false;
- String globalProxySpec = null;
- String globalProxyExclusionList = null;
-
- @NonNull ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
-
- List<String> crossProfileWidgetProviders;
-
- Bundle userRestrictions;
-
- // User restrictions that have already been enabled by default for this admin (either when
- // setting the device or profile owner, or during a system update if one of those "enabled
- // by default" restrictions is newly added).
- final Set<String> defaultEnabledRestrictionsAlreadySet = new ArraySet<>();
-
- // Support text provided by the admin to display to the user.
- CharSequence shortSupportMessage = null;
- CharSequence longSupportMessage = null;
-
- // Background color of confirm credentials screen. Default: teal.
- static final int DEF_ORGANIZATION_COLOR = Color.parseColor("#00796B");
- int organizationColor = DEF_ORGANIZATION_COLOR;
-
- // Default title of confirm credentials screen
- String organizationName = null;
-
- // Message for user switcher
- String startUserSessionMessage = null;
- String endUserSessionMessage = null;
-
- // The whitelist of packages that can access cross profile calendar APIs.
- // This whitelist should be in default an empty list, which indicates that no package
- // is whitelisted.
- List<String> mCrossProfileCalendarPackages = Collections.emptyList();
-
- // The whitelist of packages that the admin has enabled to be able to request consent from
- // the user to communicate cross-profile. By default, no packages are whitelisted, which is
- // represented as an empty list.
- List<String> mCrossProfilePackages = Collections.emptyList();
-
- // Whether the admin explicitly requires personal apps to be suspended
- boolean mSuspendPersonalApps = false;
- // Maximum time the profile owned by this admin can be off.
- long mProfileMaximumTimeOffMillis = 0;
- // Time by which the profile should be turned on according to System.currentTimeMillis().
- long mProfileOffDeadline = 0;
-
- public String mAlwaysOnVpnPackage;
- public boolean mAlwaysOnVpnLockdown;
- boolean mCommonCriteriaMode;
-
- ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
- info = _info;
- isParent = parent;
- }
-
- ActiveAdmin getParentActiveAdmin() {
- Preconditions.checkState(!isParent);
-
- if (parentAdmin == null) {
- parentAdmin = new ActiveAdmin(info, /* parent */ true);
- }
- return parentAdmin;
- }
-
- boolean hasParentActiveAdmin() {
- return parentAdmin != null;
- }
-
- int getUid() { return info.getActivityInfo().applicationInfo.uid; }
-
- public UserHandle getUserHandle() {
- return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
- }
-
- void writeToXml(XmlSerializer out)
- throws IllegalArgumentException, IllegalStateException, IOException {
- out.startTag(null, TAG_POLICIES);
- info.writePoliciesToXml(out);
- out.endTag(null, TAG_POLICIES);
- if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
- if (mPasswordPolicy.length != PasswordPolicy.DEF_MINIMUM_LENGTH) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LENGTH, mPasswordPolicy.length);
- }
- if (mPasswordPolicy.upperCase != PasswordPolicy.DEF_MINIMUM_UPPER_CASE) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_UPPERCASE, mPasswordPolicy.upperCase);
- }
- if (mPasswordPolicy.lowerCase != PasswordPolicy.DEF_MINIMUM_LOWER_CASE) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LOWERCASE, mPasswordPolicy.lowerCase);
- }
- if (mPasswordPolicy.letters != PasswordPolicy.DEF_MINIMUM_LETTERS) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LETTERS, mPasswordPolicy.letters);
- }
- if (mPasswordPolicy.numeric != PasswordPolicy.DEF_MINIMUM_NUMERIC) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_NUMERIC, mPasswordPolicy.numeric);
- }
- if (mPasswordPolicy.symbols != PasswordPolicy.DEF_MINIMUM_SYMBOLS) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_SYMBOLS, mPasswordPolicy.symbols);
- }
- if (mPasswordPolicy.nonLetter > PasswordPolicy.DEF_MINIMUM_NON_LETTER) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_NONLETTER, mPasswordPolicy.nonLetter);
- }
- }
- if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_HISTORY_LENGTH, passwordHistoryLength);
- }
- if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
- writeAttributeValueToXml(
- out, TAG_MAX_TIME_TO_UNLOCK, maximumTimeToUnlock);
- }
- if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
- writeAttributeValueToXml(
- out, TAG_STRONG_AUTH_UNLOCK_TIMEOUT, strongAuthUnlockTimeout);
- }
- if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
- writeAttributeValueToXml(
- out, TAG_MAX_FAILED_PASSWORD_WIPE, maximumFailedPasswordsForWipe);
- }
- if (specifiesGlobalProxy) {
- writeAttributeValueToXml(
- out, TAG_SPECIFIES_GLOBAL_PROXY, specifiesGlobalProxy);
- if (globalProxySpec != null) {
- writeAttributeValueToXml(out, TAG_GLOBAL_PROXY_SPEC, globalProxySpec);
- }
- if (globalProxyExclusionList != null) {
- writeAttributeValueToXml(
- out, TAG_GLOBAL_PROXY_EXCLUSION_LIST, globalProxyExclusionList);
- }
- }
- if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_EXPIRATION_TIMEOUT, passwordExpirationTimeout);
- }
- if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_EXPIRATION_DATE, passwordExpirationDate);
- }
- if (encryptionRequested) {
- writeAttributeValueToXml(
- out, TAG_ENCRYPTION_REQUESTED, encryptionRequested);
- }
- if (testOnlyAdmin) {
- writeAttributeValueToXml(
- out, TAG_TEST_ONLY_ADMIN, testOnlyAdmin);
- }
- if (disableCamera) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CAMERA, disableCamera);
- }
- if (disableCallerId) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CALLER_ID, disableCallerId);
- }
- if (disableContactsSearch) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CONTACTS_SEARCH, disableContactsSearch);
- }
- if (!disableBluetoothContactSharing) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING, disableBluetoothContactSharing);
- }
- if (disableScreenCapture) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_SCREEN_CAPTURE, disableScreenCapture);
- }
- if (requireAutoTime) {
- writeAttributeValueToXml(
- out, TAG_REQUIRE_AUTO_TIME, requireAutoTime);
- }
- if (forceEphemeralUsers) {
- writeAttributeValueToXml(
- out, TAG_FORCE_EPHEMERAL_USERS, forceEphemeralUsers);
- }
- if (isNetworkLoggingEnabled) {
- out.startTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(isNetworkLoggingEnabled));
- out.attribute(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS,
- Integer.toString(numNetworkLoggingNotifications));
- out.attribute(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION,
- Long.toString(lastNetworkLoggingNotificationTimeMs));
- out.endTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
- }
- if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_KEYGUARD_FEATURES, disabledKeyguardFeatures);
- }
- if (!accountTypesWithManagementDisabled.isEmpty()) {
- writeAttributeValuesToXml(
- out, TAG_DISABLE_ACCOUNT_MANAGEMENT, TAG_ACCOUNT_TYPE,
- accountTypesWithManagementDisabled);
- }
- if (!trustAgentInfos.isEmpty()) {
- Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
- out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
- for (Entry<String, TrustAgentInfo> entry : set) {
- TrustAgentInfo trustAgentInfo = entry.getValue();
- out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
- out.attribute(null, ATTR_VALUE, entry.getKey());
- if (trustAgentInfo.options != null) {
- out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
- try {
- trustAgentInfo.options.saveToXml(out);
- } catch (XmlPullParserException e) {
- Log.e(LOG_TAG, "Failed to save TrustAgent options", e);
- }
- out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
- }
- out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
- }
- out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
- }
- if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
- writeAttributeValuesToXml(
- out, TAG_CROSS_PROFILE_WIDGET_PROVIDERS, TAG_PROVIDER,
- crossProfileWidgetProviders);
- }
- writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
- permittedAccessiblityServices);
- writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
- writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
- permittedNotificationListeners);
- writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
- writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
- if (hasUserRestrictions()) {
- UserRestrictionsUtils.writeRestrictions(
- out, userRestrictions, TAG_USER_RESTRICTIONS);
- }
- if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
- writeAttributeValuesToXml(out, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS,
- TAG_RESTRICTION,
- defaultEnabledRestrictionsAlreadySet);
- }
- if (!TextUtils.isEmpty(shortSupportMessage)) {
- writeTextToXml(out, TAG_SHORT_SUPPORT_MESSAGE, shortSupportMessage.toString());
- }
- if (!TextUtils.isEmpty(longSupportMessage)) {
- writeTextToXml(out, TAG_LONG_SUPPORT_MESSAGE, longSupportMessage.toString());
- }
- if (parentAdmin != null) {
- out.startTag(null, TAG_PARENT_ADMIN);
- parentAdmin.writeToXml(out);
- out.endTag(null, TAG_PARENT_ADMIN);
- }
- if (organizationColor != DEF_ORGANIZATION_COLOR) {
- writeAttributeValueToXml(out, TAG_ORGANIZATION_COLOR, organizationColor);
- }
- if (organizationName != null) {
- writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
- }
- if (isLogoutEnabled) {
- writeAttributeValueToXml(out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
- }
- if (startUserSessionMessage != null) {
- writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
- }
- if (endUserSessionMessage != null) {
- writeTextToXml(out, TAG_END_USER_SESSION_MESSAGE, endUserSessionMessage);
- }
- if (mCrossProfileCalendarPackages == null) {
- out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
- out.endTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
- } else {
- writePackageListToXml(out, TAG_CROSS_PROFILE_CALENDAR_PACKAGES,
- mCrossProfileCalendarPackages);
- }
- writePackageListToXml(out, TAG_CROSS_PROFILE_PACKAGES, mCrossProfilePackages);
- if (mFactoryResetProtectionPolicy != null) {
- out.startTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
- mFactoryResetProtectionPolicy.writeToXml(out);
- out.endTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
- }
- if (mSuspendPersonalApps) {
- writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
- }
- if (mProfileMaximumTimeOffMillis != 0) {
- writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF,
- mProfileMaximumTimeOffMillis);
- }
- if (mProfileMaximumTimeOffMillis != 0) {
- writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
- }
- if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
- writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_PACKAGE, mAlwaysOnVpnPackage);
- }
- if (mAlwaysOnVpnLockdown) {
- writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
- }
- if (mCommonCriteriaMode) {
- writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
- }
- }
-
- void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
- out.startTag(null, tag);
- out.text(text);
- out.endTag(null, tag);
- }
-
- void writePackageListToXml(XmlSerializer out, String outerTag,
- List<String> packageList)
- throws IllegalArgumentException, IllegalStateException, IOException {
- if (packageList == null) {
- return;
- }
- writeAttributeValuesToXml(out, outerTag, TAG_PACKAGE_LIST_ITEM, packageList);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, String value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, value);
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, int value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Integer.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, long value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Long.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, boolean value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Boolean.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValuesToXml(XmlSerializer out, String outerTag, String innerTag,
- @NonNull Collection<String> values) throws IOException {
- out.startTag(null, outerTag);
- for (String value : values) {
- out.startTag(null, innerTag);
- out.attribute(null, ATTR_VALUE, value);
- out.endTag(null, innerTag);
- }
- out.endTag(null, outerTag);
- }
-
- void readFromXml(XmlPullParser parser, boolean shouldOverridePolicies)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != END_DOCUMENT
- && (type != END_TAG || parser.getDepth() > outerDepth)) {
- if (type == END_TAG || type == TEXT) {
- continue;
- }
- String tag = parser.getName();
- if (TAG_POLICIES.equals(tag)) {
- if (shouldOverridePolicies) {
- Log.d(LOG_TAG, "Overriding device admin policies from XML.");
- info.readPoliciesFromXml(parser);
- }
- } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
- mPasswordPolicy.quality = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
- mPasswordPolicy.length = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
- passwordHistoryLength = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
- mPasswordPolicy.upperCase = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
- mPasswordPolicy.lowerCase = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
- mPasswordPolicy.letters = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
- mPasswordPolicy.numeric = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
- mPasswordPolicy.symbols = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
- mPasswordPolicy.nonLetter = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- }else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
- maximumTimeToUnlock = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_STRONG_AUTH_UNLOCK_TIMEOUT.equals(tag)) {
- strongAuthUnlockTimeout = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
- maximumFailedPasswordsForWipe = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
- specifiesGlobalProxy = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
- globalProxySpec =
- parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
- globalProxyExclusionList =
- parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
- passwordExpirationTimeout = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
- passwordExpirationDate = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
- encryptionRequested = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_TEST_ONLY_ADMIN.equals(tag)) {
- testOnlyAdmin = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CAMERA.equals(tag)) {
- disableCamera = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
- disableCallerId = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) {
- disableContactsSearch = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
- disableBluetoothContactSharing = Boolean.parseBoolean(parser
- .getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
- disableScreenCapture = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
- requireAutoTime = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
- forceEphemeralUsers = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_IS_NETWORK_LOGGING_ENABLED.equals(tag)) {
- isNetworkLoggingEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- lastNetworkLoggingNotificationTimeMs = Long.parseLong(
- parser.getAttributeValue(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION));
- numNetworkLoggingNotifications = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS));
- } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
- disabledKeyguardFeatures = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
- readAttributeValues(
- parser, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
- } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
- trustAgentInfos = getAllTrustAgentInfos(parser, tag);
- } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
- crossProfileWidgetProviders = new ArrayList<>();
- readAttributeValues(parser, TAG_PROVIDER, crossProfileWidgetProviders);
- } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
- permittedAccessiblityServices = readPackageList(parser, tag);
- } else if (TAG_PERMITTED_IMES.equals(tag)) {
- permittedInputMethods = readPackageList(parser, tag);
- } else if (TAG_PERMITTED_NOTIFICATION_LISTENERS.equals(tag)) {
- permittedNotificationListeners = readPackageList(parser, tag);
- } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
- keepUninstalledPackages = readPackageList(parser, tag);
- } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
- meteredDisabledPackages = readPackageList(parser, tag);
- } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
- userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
- } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
- readAttributeValues(
- parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
- } else if (TAG_SHORT_SUPPORT_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- shortSupportMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading short support message");
- }
- } else if (TAG_LONG_SUPPORT_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- longSupportMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading long support message");
- }
- } else if (TAG_PARENT_ADMIN.equals(tag)) {
- Preconditions.checkState(!isParent);
- parentAdmin = new ActiveAdmin(info, /* parent */ true);
- parentAdmin.readFromXml(parser, shouldOverridePolicies);
- } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
- organizationColor = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- organizationName = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading organization name");
- }
- } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
- isLogoutEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- startUserSessionMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading start session message");
- }
- } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- endUserSessionMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading end session message");
- }
- } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
- mCrossProfileCalendarPackages = readPackageList(parser, tag);
- } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL.equals(tag)) {
- mCrossProfileCalendarPackages = null;
- } else if (TAG_CROSS_PROFILE_PACKAGES.equals(tag)) {
- mCrossProfilePackages = readPackageList(parser, tag);
- } else if (TAG_FACTORY_RESET_PROTECTION_POLICY.equals(tag)) {
- mFactoryResetProtectionPolicy = FactoryResetProtectionPolicy.readFromXml(
- parser);
- } else if (TAG_SUSPEND_PERSONAL_APPS.equals(tag)) {
- mSuspendPersonalApps = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
- mProfileMaximumTimeOffMillis =
- Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
- mProfileOffDeadline =
- Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ALWAYS_ON_VPN_PACKAGE.equals(tag)) {
- mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
- mAlwaysOnVpnLockdown = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
- mCommonCriteriaMode = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- }
-
- private List<String> readPackageList(XmlPullParser parser,
- String tag) throws XmlPullParserException, IOException {
- List<String> result = new ArrayList<String>();
- int outerDepth = parser.getDepth();
- int outerType;
- while ((outerType=parser.next()) != XmlPullParser.END_DOCUMENT
- && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
- continue;
- }
- String outerTag = parser.getName();
- if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
- String packageName = parser.getAttributeValue(null, ATTR_VALUE);
- if (packageName != null) {
- result.add(packageName);
- } else {
- Slog.w(LOG_TAG, "Package name missing under " + outerTag);
- }
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + outerTag);
- }
- }
- return result;
- }
-
- private void readAttributeValues(
- XmlPullParser parser, String tag, Collection<String> result)
- throws XmlPullParserException, IOException {
- result.clear();
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (tag.equals(tagDAM)) {
- result.add(parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.e(LOG_TAG, "Expected tag " + tag + " but found " + tagDAM);
- }
- }
- }
-
- @NonNull
- private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
- XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- final ArrayMap<String, TrustAgentInfo> result = new ArrayMap<>();
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
- final String component = parser.getAttributeValue(null, ATTR_VALUE);
- final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
- result.put(component, trustAgentInfo);
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
- }
- }
- return result;
- }
-
- private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
- throws XmlPullParserException, IOException {
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- TrustAgentInfo result = new TrustAgentInfo(null);
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
- result.options = PersistableBundle.restoreFromXml(parser);
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
- }
- }
- return result;
- }
-
- boolean hasUserRestrictions() {
- return userRestrictions != null && userRestrictions.size() > 0;
- }
-
- Bundle ensureUserRestrictions() {
- if (userRestrictions == null) {
- userRestrictions = new Bundle();
- }
- return userRestrictions;
- }
-
- public void transfer(DeviceAdminInfo deviceAdminInfo) {
- if (hasParentActiveAdmin()) {
- parentAdmin.info = deviceAdminInfo;
- }
- info = deviceAdminInfo;
- }
-
- Bundle addSyntheticRestrictions(Bundle restrictions) {
- if (disableCamera) {
- restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
- }
- if (requireAutoTime) {
- restrictions.putBoolean(UserManager.DISALLOW_CONFIG_DATE_TIME, true);
- }
- return restrictions;
- }
-
- static Bundle removeDeprecatedRestrictions(Bundle restrictions) {
- for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) {
- restrictions.remove(deprecatedRestriction);
- }
- return restrictions;
- }
-
- static Bundle filterRestrictions(Bundle restrictions, Predicate<String> filter) {
- Bundle result = new Bundle();
- for (String key : restrictions.keySet()) {
- if (!restrictions.getBoolean(key)) {
- continue;
- }
- if (filter.test(key)) {
- result.putBoolean(key, true);
- }
- }
- return result;
- }
-
- Bundle getEffectiveRestrictions() {
- return addSyntheticRestrictions(
- removeDeprecatedRestrictions(new Bundle(ensureUserRestrictions())));
- }
-
- Bundle getLocalUserRestrictions(int adminType) {
- return filterRestrictions(getEffectiveRestrictions(),
- key -> UserRestrictionsUtils.isLocal(adminType, key));
- }
-
- Bundle getGlobalUserRestrictions(int adminType) {
- return filterRestrictions(getEffectiveRestrictions(),
- key -> UserRestrictionsUtils.isGlobal(adminType, key));
- }
-
- void dump(IndentingPrintWriter pw) {
- pw.print("uid="); pw.println(getUid());
- pw.print("testOnlyAdmin=");
- pw.println(testOnlyAdmin);
- pw.println("policies:");
- ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
- if (pols != null) {
- pw.increaseIndent();
- for (int i=0; i<pols.size(); i++) {
- pw.println(pols.get(i).tag);
- }
- pw.decreaseIndent();
- }
- pw.print("passwordQuality=0x");
- pw.println(Integer.toHexString(mPasswordPolicy.quality));
- pw.print("minimumPasswordLength=");
- pw.println(mPasswordPolicy.length);
- pw.print("passwordHistoryLength=");
- pw.println(passwordHistoryLength);
- pw.print("minimumPasswordUpperCase=");
- pw.println(mPasswordPolicy.upperCase);
- pw.print("minimumPasswordLowerCase=");
- pw.println(mPasswordPolicy.lowerCase);
- pw.print("minimumPasswordLetters=");
- pw.println(mPasswordPolicy.letters);
- pw.print("minimumPasswordNumeric=");
- pw.println(mPasswordPolicy.numeric);
- pw.print("minimumPasswordSymbols=");
- pw.println(mPasswordPolicy.symbols);
- pw.print("minimumPasswordNonLetter=");
- pw.println(mPasswordPolicy.nonLetter);
- pw.print("maximumTimeToUnlock=");
- pw.println(maximumTimeToUnlock);
- pw.print("strongAuthUnlockTimeout=");
- pw.println(strongAuthUnlockTimeout);
- pw.print("maximumFailedPasswordsForWipe=");
- pw.println(maximumFailedPasswordsForWipe);
- pw.print("specifiesGlobalProxy=");
- pw.println(specifiesGlobalProxy);
- pw.print("passwordExpirationTimeout=");
- pw.println(passwordExpirationTimeout);
- pw.print("passwordExpirationDate=");
- pw.println(passwordExpirationDate);
- if (globalProxySpec != null) {
- pw.print("globalProxySpec=");
- pw.println(globalProxySpec);
- }
- if (globalProxyExclusionList != null) {
- pw.print("globalProxyEclusionList=");
- pw.println(globalProxyExclusionList);
- }
- pw.print("encryptionRequested=");
- pw.println(encryptionRequested);
- pw.print("disableCamera=");
- pw.println(disableCamera);
- pw.print("disableCallerId=");
- pw.println(disableCallerId);
- pw.print("disableContactsSearch=");
- pw.println(disableContactsSearch);
- pw.print("disableBluetoothContactSharing=");
- pw.println(disableBluetoothContactSharing);
- pw.print("disableScreenCapture=");
- pw.println(disableScreenCapture);
- pw.print("requireAutoTime=");
- pw.println(requireAutoTime);
- pw.print("forceEphemeralUsers=");
- pw.println(forceEphemeralUsers);
- pw.print("isNetworkLoggingEnabled=");
- pw.println(isNetworkLoggingEnabled);
- pw.print("disabledKeyguardFeatures=");
- pw.println(disabledKeyguardFeatures);
- pw.print("crossProfileWidgetProviders=");
- pw.println(crossProfileWidgetProviders);
- if (permittedAccessiblityServices != null) {
- pw.print("permittedAccessibilityServices=");
- pw.println(permittedAccessiblityServices);
- }
- if (permittedInputMethods != null) {
- pw.print("permittedInputMethods=");
- pw.println(permittedInputMethods);
- }
- if (permittedNotificationListeners != null) {
- pw.print("permittedNotificationListeners=");
- pw.println(permittedNotificationListeners);
- }
- if (keepUninstalledPackages != null) {
- pw.print("keepUninstalledPackages=");
- pw.println(keepUninstalledPackages);
- }
- pw.print("organizationColor=");
- pw.println(organizationColor);
- if (organizationName != null) {
- pw.print("organizationName=");
- pw.println(organizationName);
- }
- pw.println("userRestrictions:");
- UserRestrictionsUtils.dumpRestrictions(pw, " ", userRestrictions);
- pw.print("defaultEnabledRestrictionsAlreadySet=");
- pw.println(defaultEnabledRestrictionsAlreadySet);
- pw.print("isParent=");
- pw.println(isParent);
- if (parentAdmin != null) {
- pw.println("parentAdmin:");
- pw.increaseIndent();
- parentAdmin.dump(pw);
- pw.decreaseIndent();
- }
- if (mCrossProfileCalendarPackages != null) {
- pw.print("mCrossProfileCalendarPackages=");
- pw.println(mCrossProfileCalendarPackages);
- }
- pw.print("mCrossProfilePackages=");
- pw.println(mCrossProfilePackages);
- pw.print("mSuspendPersonalApps=");
- pw.println(mSuspendPersonalApps);
- pw.print("mProfileMaximumTimeOffMillis=");
- pw.println(mProfileMaximumTimeOffMillis);
- pw.print("mProfileOffDeadline=");
- pw.println(mProfileOffDeadline);
- pw.print("mAlwaysOnVpnPackage=");
- pw.println(mAlwaysOnVpnPackage);
- pw.print("mAlwaysOnVpnLockdown=");
- pw.println(mAlwaysOnVpnLockdown);
- pw.print("mCommonCriteriaMode=");
- pw.println(mCommonCriteriaMode);
- }
- }
-
private void handlePackagesChanged(@Nullable String packageName, int userHandle) {
boolean removedAdmin = false;
if (VERBOSE_LOG) {
@@ -2073,7 +934,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
if (removedAdmin) {
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
}
boolean removedDelegate = false;
@@ -3514,13 +2375,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
-
- public DeviceAdminInfo findAdmin(final ComponentName adminName, final int userHandle,
+ private DeviceAdminInfo findAdmin(final ComponentName adminName, final int userHandle,
boolean throwForMissingPermission) {
- if (!mHasFeature) {
- return null;
- }
- enforceFullCrossUsersPermission(userHandle);
final ActivityInfo ai = mInjector.binderWithCleanCallingIdentity(() -> {
try {
return mIPackageManager.getReceiverInfo(adminName,
@@ -3583,213 +2439,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void saveSettingsLocked(int userHandle) {
- DevicePolicyData policy = getUserData(userHandle);
- JournaledFile journal = makeJournaledFile(userHandle);
- FileOutputStream stream = null;
- try {
- stream = new FileOutputStream(journal.chooseForWrite(), false);
- XmlSerializer out = new FastXmlSerializer();
- out.setOutput(stream, StandardCharsets.UTF_8.name());
- out.startDocument(null, true);
-
- out.startTag(null, "policies");
- if (policy.mRestrictionsProvider != null) {
- out.attribute(null, ATTR_PERMISSION_PROVIDER,
- policy.mRestrictionsProvider.flattenToString());
- }
- if (policy.mUserSetupComplete) {
- out.attribute(null, ATTR_SETUP_COMPLETE,
- Boolean.toString(true));
- }
- if (policy.mPaired) {
- out.attribute(null, ATTR_DEVICE_PAIRED,
- Boolean.toString(true));
- }
- if (policy.mDeviceProvisioningConfigApplied) {
- out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
- Boolean.toString(true));
- }
- if (policy.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
- out.attribute(null, ATTR_PROVISIONING_STATE,
- Integer.toString(policy.mUserProvisioningState));
- }
- if (policy.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
- out.attribute(null, ATTR_PERMISSION_POLICY,
- Integer.toString(policy.mPermissionPolicy));
- }
-
- // Serialize delegations.
- for (int i = 0; i < policy.mDelegationMap.size(); ++i) {
- final String delegatePackage = policy.mDelegationMap.keyAt(i);
- final List<String> scopes = policy.mDelegationMap.valueAt(i);
-
- // Every "delegation" tag serializes the information of one delegate-scope pair.
- for (String scope : scopes) {
- out.startTag(null, "delegation");
- out.attribute(null, "delegatePackage", delegatePackage);
- out.attribute(null, "scope", scope);
- out.endTag(null, "delegation");
- }
- }
-
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin ap = policy.mAdminList.get(i);
- if (ap != null) {
- out.startTag(null, "admin");
- out.attribute(null, "name", ap.info.getComponent().flattenToString());
- ap.writeToXml(out);
- out.endTag(null, "admin");
- }
- }
-
- if (policy.mPasswordOwner >= 0) {
- out.startTag(null, "password-owner");
- out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
- out.endTag(null, "password-owner");
- }
-
- if (policy.mFailedPasswordAttempts != 0) {
- out.startTag(null, "failed-password-attempts");
- out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
- out.endTag(null, "failed-password-attempts");
- }
-
- // For FDE devices only, we save this flag so we can report on password sufficiency
- // before the user enters their password for the first time after a reboot. For
- // security reasons, we don't want to store the full set of active password metrics.
- if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
- out.startTag(null, TAG_PASSWORD_VALIDITY);
- out.attribute(null, ATTR_VALUE,
- Boolean.toString(policy.mPasswordValidAtLastCheckpoint));
- out.endTag(null, TAG_PASSWORD_VALIDITY);
- }
-
- for (int i = 0; i < policy.mAcceptedCaCertificates.size(); i++) {
- out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
- out.attribute(null, ATTR_NAME, policy.mAcceptedCaCertificates.valueAt(i));
- out.endTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
- }
-
- for (int i=0; i<policy.mLockTaskPackages.size(); i++) {
- String component = policy.mLockTaskPackages.get(i);
- out.startTag(null, TAG_LOCK_TASK_COMPONENTS);
- out.attribute(null, "name", component);
- out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
- }
-
- if (policy.mLockTaskFeatures != DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
- out.startTag(null, TAG_LOCK_TASK_FEATURES);
- out.attribute(null, ATTR_VALUE, Integer.toString(policy.mLockTaskFeatures));
- out.endTag(null, TAG_LOCK_TASK_FEATURES);
- }
-
- if (policy.mSecondaryLockscreenEnabled) {
- out.startTag(null, TAG_SECONDARY_LOCK_SCREEN);
- out.attribute(null, ATTR_VALUE, Boolean.toString(true));
- out.endTag(null, TAG_SECONDARY_LOCK_SCREEN);
- }
-
- if (policy.mStatusBarDisabled) {
- out.startTag(null, TAG_STATUS_BAR);
- out.attribute(null, ATTR_DISABLED, Boolean.toString(policy.mStatusBarDisabled));
- out.endTag(null, TAG_STATUS_BAR);
- }
-
- if (policy.doNotAskCredentialsOnBoot) {
- out.startTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML);
- out.endTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML);
- }
-
- for (String id : policy.mAffiliationIds) {
- out.startTag(null, TAG_AFFILIATION_ID);
- out.attribute(null, ATTR_ID, id);
- out.endTag(null, TAG_AFFILIATION_ID);
- }
-
- if (policy.mLastSecurityLogRetrievalTime >= 0) {
- out.startTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastSecurityLogRetrievalTime));
- out.endTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
- }
-
- if (policy.mLastBugReportRequestTime >= 0) {
- out.startTag(null, TAG_LAST_BUG_REPORT_REQUEST);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastBugReportRequestTime));
- out.endTag(null, TAG_LAST_BUG_REPORT_REQUEST);
- }
-
- if (policy.mLastNetworkLogsRetrievalTime >= 0) {
- out.startTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastNetworkLogsRetrievalTime));
- out.endTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
- }
-
- if (policy.mAdminBroadcastPending) {
- out.startTag(null, TAG_ADMIN_BROADCAST_PENDING);
- out.attribute(null, ATTR_VALUE,
- Boolean.toString(policy.mAdminBroadcastPending));
- out.endTag(null, TAG_ADMIN_BROADCAST_PENDING);
- }
-
- if (policy.mInitBundle != null) {
- out.startTag(null, TAG_INITIALIZATION_BUNDLE);
- policy.mInitBundle.saveToXml(out);
- out.endTag(null, TAG_INITIALIZATION_BUNDLE);
- }
-
- if (policy.mPasswordTokenHandle != 0) {
- out.startTag(null, TAG_PASSWORD_TOKEN_HANDLE);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mPasswordTokenHandle));
- out.endTag(null, TAG_PASSWORD_TOKEN_HANDLE);
- }
-
- if (policy.mCurrentInputMethodSet) {
- out.startTag(null, TAG_CURRENT_INPUT_METHOD_SET);
- out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
- }
-
- for (final String cert : policy.mOwnerInstalledCaCerts) {
- out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
- out.attribute(null, ATTR_ALIAS, cert);
- out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT);
- }
-
- for (int i = 0, size = policy.mUserControlDisabledPackages.size(); i < size; i++) {
- String packageName = policy.mUserControlDisabledPackages.get(i);
- out.startTag(null, TAG_PROTECTED_PACKAGES);
- out.attribute(null, ATTR_NAME, packageName);
- out.endTag(null, TAG_PROTECTED_PACKAGES);
- }
-
- if (policy.mAppsSuspended) {
- out.startTag(null, TAG_APPS_SUSPENDED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mAppsSuspended));
- out.endTag(null, TAG_APPS_SUSPENDED);
- }
-
- out.endTag(null, "policies");
-
- out.endDocument();
- stream.flush();
- FileUtils.sync(stream);
- stream.close();
- journal.commit();
+ if (DevicePolicyData.store(
+ getUserData(userHandle),
+ makeJournaledFile(userHandle),
+ !mInjector.storageManagerIsFileBasedEncryptionEnabled())) {
sendChangedNotification(userHandle);
- } catch (XmlPullParserException | IOException e) {
- Slog.w(LOG_TAG, "failed writing file", e);
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException ex) {
- // Ignore
- }
- journal.rollback();
}
}
@@ -3801,225 +2455,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
- JournaledFile journal = makeJournaledFile(userHandle);
- FileInputStream stream = null;
- File file = journal.chooseForRead();
- boolean needsRewrite = false;
- try {
- stream = new FileInputStream(file);
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
-
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
- String tag = parser.getName();
- if (!"policies".equals(tag)) {
- throw new XmlPullParserException(
- "Settings do not start with policies tag: found " + tag);
- }
-
- // Extract the permission provider component name if available
- String permissionProvider = parser.getAttributeValue(null, ATTR_PERMISSION_PROVIDER);
- if (permissionProvider != null) {
- policy.mRestrictionsProvider = ComponentName.unflattenFromString(permissionProvider);
- }
- String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
- if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
- policy.mUserSetupComplete = true;
- }
- String paired = parser.getAttributeValue(null, ATTR_DEVICE_PAIRED);
- if (paired != null && Boolean.toString(true).equals(paired)) {
- policy.mPaired = true;
- }
- String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
- ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
- if (deviceProvisioningConfigApplied != null
- && Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
- policy.mDeviceProvisioningConfigApplied = true;
- }
- String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
- if (!TextUtils.isEmpty(provisioningState)) {
- policy.mUserProvisioningState = Integer.parseInt(provisioningState);
- }
- String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
- if (!TextUtils.isEmpty(permissionPolicy)) {
- policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
- }
- // Check for delegation compatibility with pre-O.
- // TODO(edmanp) remove in P.
- {
- final String certDelegate = parser.getAttributeValue(null,
- ATTR_DELEGATED_CERT_INSTALLER);
- if (certDelegate != null) {
- List<String> scopes = policy.mDelegationMap.get(certDelegate);
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(certDelegate, scopes);
- }
- if (!scopes.contains(DELEGATION_CERT_INSTALL)) {
- scopes.add(DELEGATION_CERT_INSTALL);
- needsRewrite = true;
- }
- }
- final String appRestrictionsDelegate = parser.getAttributeValue(null,
- ATTR_APPLICATION_RESTRICTIONS_MANAGER);
- if (appRestrictionsDelegate != null) {
- List<String> scopes = policy.mDelegationMap.get(appRestrictionsDelegate);
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(appRestrictionsDelegate, scopes);
- }
- if (!scopes.contains(DELEGATION_APP_RESTRICTIONS)) {
- scopes.add(DELEGATION_APP_RESTRICTIONS);
- needsRewrite = true;
- }
- }
- }
-
- type = parser.next();
- int outerDepth = parser.getDepth();
- policy.mLockTaskPackages.clear();
- policy.mAdminList.clear();
- policy.mAdminMap.clear();
- policy.mAffiliationIds.clear();
- policy.mOwnerInstalledCaCerts.clear();
- policy.mUserControlDisabledPackages.clear();
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- tag = parser.getName();
- if ("admin".equals(tag)) {
- String name = parser.getAttributeValue(null, "name");
- try {
- DeviceAdminInfo dai = findAdmin(
- ComponentName.unflattenFromString(name), userHandle,
- /* throwForMissingPermission= */ false);
- if (VERBOSE_LOG
- && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
- != userHandle)) {
- Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
- + dai.getActivityInfo().applicationInfo.uid + " for user "
- + userHandle);
- }
- if (dai != null) {
- boolean shouldOverwritePolicies =
- shouldOverwritePoliciesFromXml(dai.getComponent(), userHandle);
- ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
- ap.readFromXml(parser, shouldOverwritePolicies);
- policy.mAdminMap.put(ap.info.getComponent(), ap);
- }
- } catch (RuntimeException e) {
- Slog.w(LOG_TAG, "Failed loading admin " + name, e);
- }
- } else if ("delegation".equals(tag)) {
- // Parse delegation info.
- final String delegatePackage = parser.getAttributeValue(null,
- "delegatePackage");
- final String scope = parser.getAttributeValue(null, "scope");
-
- // Get a reference to the scopes list for the delegatePackage.
- List<String> scopes = policy.mDelegationMap.get(delegatePackage);
- // Or make a new list if none was found.
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(delegatePackage, scopes);
- }
- // Add the new scope to the list of delegatePackage if it's not already there.
- if (!scopes.contains(scope)) {
- scopes.add(scope);
- }
- } else if ("failed-password-attempts".equals(tag)) {
- policy.mFailedPasswordAttempts = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("password-owner".equals(tag)) {
- policy.mPasswordOwner = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
- policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
- } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
- policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
- } else if (TAG_LOCK_TASK_FEATURES.equals(tag)) {
- policy.mLockTaskFeatures = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_SECONDARY_LOCK_SCREEN.equals(tag)) {
- policy.mSecondaryLockscreenEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_STATUS_BAR.equals(tag)) {
- policy.mStatusBarDisabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_DISABLED));
- } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
- policy.doNotAskCredentialsOnBoot = true;
- } else if (TAG_AFFILIATION_ID.equals(tag)) {
- policy.mAffiliationIds.add(parser.getAttributeValue(null, ATTR_ID));
- } else if (TAG_LAST_SECURITY_LOG_RETRIEVAL.equals(tag)) {
- policy.mLastSecurityLogRetrievalTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_LAST_BUG_REPORT_REQUEST.equals(tag)) {
- policy.mLastBugReportRequestTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_LAST_NETWORK_LOG_RETRIEVAL.equals(tag)) {
- policy.mLastNetworkLogsRetrievalTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
- String pending = parser.getAttributeValue(null, ATTR_VALUE);
- policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
- } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
- policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
- } else if ("active-password".equals(tag)) {
- // Remove password metrics from saved settings, as we no longer wish to store
- // these on disk
- needsRewrite = true;
- } else if (TAG_PASSWORD_VALIDITY.equals(tag)) {
- if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
- // This flag is only used for FDE devices
- policy.mPasswordValidAtLastCheckpoint = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- }
- } else if (TAG_PASSWORD_TOKEN_HANDLE.equals(tag)) {
- policy.mPasswordTokenHandle = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_CURRENT_INPUT_METHOD_SET.equals(tag)) {
- policy.mCurrentInputMethodSet = true;
- } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
- policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
- } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
- policy.mUserControlDisabledPackages.add(
- parser.getAttributeValue(null, ATTR_NAME));
- } else if (TAG_APPS_SUSPENDED.equals(tag)) {
- policy.mAppsSuspended =
- Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.w(LOG_TAG, "Unknown tag: " + tag);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- } catch (FileNotFoundException e) {
- // Don't be noisy, this is normal if we haven't defined any policies.
- } catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
- | IndexOutOfBoundsException e) {
- Slog.w(LOG_TAG, "failed parsing " + file, e);
- }
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // Ignore
- }
-
- // Generate a list of admins from the admin map
- policy.mAdminList.addAll(policy.mAdminMap.values());
+ boolean needsRewrite = DevicePolicyData.load(policy,
+ !mInjector.storageManagerIsFileBasedEncryptionEnabled(),
+ makeJournaledFile(userHandle),
+ component -> findAdmin(
+ component, userHandle, /* throwForMissingPermission= */ false),
+ getOwnerComponent(userHandle));
// Might need to upgrade the file by rewriting it
if (needsRewrite) {
saveSettingsLocked(userHandle);
}
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
updateMaximumTimeToLockLocked(userHandle);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
@@ -4029,14 +2477,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean shouldOverwritePoliciesFromXml(
- ComponentName deviceAdminComponent, int userHandle) {
- // http://b/123415062: If DA, overwrite with the stored policies that were agreed by the
- // user to prevent apps from sneaking additional policies into updates.
- return !isProfileOwner(deviceAdminComponent, userHandle)
- && !isDeviceOwner(deviceAdminComponent, userHandle);
- }
-
private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -4098,23 +2538,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ Integer.toHexString(quality));
}
- void validatePasswordOwnerLocked(DevicePolicyData policy) {
- if (policy.mPasswordOwner >= 0) {
- boolean haveOwner = false;
- for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
- if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
- haveOwner = true;
- break;
- }
- }
- if (!haveOwner) {
- Slog.w(LOG_TAG, "Previous password owner " + policy.mPasswordOwner
- + " no longer active; disabling");
- policy.mPasswordOwner = -1;
- }
- }
- }
-
@VisibleForTesting
@Override
void systemReady(int phase) {
@@ -5842,8 +4265,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void setDoNotAskCredentialsOnBoot() {
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
- if (!policyData.doNotAskCredentialsOnBoot) {
- policyData.doNotAskCredentialsOnBoot = true;
+ if (!policyData.mDoNotAskCredentialsOnBoot) {
+ policyData.mDoNotAskCredentialsOnBoot = true;
saveSettingsLocked(UserHandle.USER_SYSTEM);
}
}
@@ -5855,7 +4278,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
- return policyData.doNotAskCredentialsOnBoot;
+ return policyData.mDoNotAskCredentialsOnBoot;
}
}
@@ -14363,7 +12786,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
policy.mAdminList.remove(admin);
policy.mAdminMap.remove(adminReceiver);
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
if (doProxyCleanup) {
resetGlobalProxyLocked(policy);
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index a5f0d045948c..f7082a9a1a0c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -23,7 +23,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/AppOpsManager.h>
-#include <binder/Nullable.h>
#include <binder/Status.h>
#include <sys/stat.h>
#include <uuid/uuid.h>
@@ -1404,7 +1403,7 @@ void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderPara
}
FileSystemControlParcel fsControlParcel;
- fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
+ fsControlParcel.incremental = std::make_optional<IncrementalFileSystemControlParcel>();
fsControlParcel.incremental->cmd.reset(dup(ifs.control.cmd()));
fsControlParcel.incremental->pendingReads.reset(dup(ifs.control.pendingReads()));
fsControlParcel.incremental->log.reset(dup(ifs.control.logs()));
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index cffcdd8f94bd..e4e7e2288590 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -32,6 +32,7 @@ java_test_host {
":PackageManagerTestAppVersion3Invalid",
":PackageManagerTestAppVersion4",
":PackageManagerTestAppOriginalOverride",
+ ":PackageManagerServiceDeviceSideTests",
],
}
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt
new file mode 100644
index 000000000000..3847658def6a
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/FactoryPackageTest.kt
@@ -0,0 +1,71 @@
+package com.android.server.pm.test
+
+import com.android.internal.util.test.SystemPreparer
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+
+@RunWith(DeviceJUnit4ClassRunner::class)
+class FactoryPackageTest : BaseHostJUnit4Test() {
+
+ companion object {
+ private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
+
+ private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
+ private const val VERSION_TWO = "PackageManagerTestAppVersion2.apk"
+ private const val DEVICE_SIDE = "PackageManagerServiceDeviceSideTests.apk"
+
+ @get:ClassRule
+ val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
+ }
+
+ private val tempFolder = TemporaryFolder()
+ private val preparer: SystemPreparer = SystemPreparer(tempFolder,
+ SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device }
+
+ @get:Rule
+ val rules = RuleChain.outerRule(tempFolder).around(preparer)!!
+ private val filePath =
+ HostUtils.makePathForApk("PackageManagerTestApp.apk", Partition.SYSTEM)
+
+ @Before
+ @After
+ fun removeApk() {
+ device.uninstallPackage(TEST_PKG_NAME)
+ device.deleteFile(filePath.parent.toString())
+ device.reboot()
+ }
+
+ @Test
+ fun testGetInstalledPackagesFactoryOnlyFlag() {
+ // First, push a system app to the device and then update it so there's a data variant
+ preparer.pushResourceFile(VERSION_ONE, filePath.toString())
+ .reboot()
+
+ val versionTwoFile = HostUtils.copyResourceToHostFile(VERSION_TWO, tempFolder.newFile())
+
+ assertThat(device.installPackage(versionTwoFile, true)).isNull()
+
+ runDeviceTest("testGetInstalledPackagesWithFactoryOnly")
+ }
+
+ /**
+ * Run a device side test from com.android.server.pm.test.deviceside.DeviceSide
+ *
+ * @param method the method to run
+ */
+ fun runDeviceTest(method: String) {
+ val deviceSideFile = HostUtils.copyResourceToHostFile(DEVICE_SIDE, tempFolder.newFile())
+ assertThat(device.installPackage(deviceSideFile, true)).isNull()
+ runDeviceTests(device, "com.android.server.pm.test.deviceside",
+ "com.android.server.pm.test.deviceside.DeviceSide", method)
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
new file mode 100644
index 000000000000..af0ac77eaadd
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+android_test_helper_app {
+ name: "PackageManagerServiceDeviceSideTests",
+ sdk_version: "test_current",
+ srcs: ["src/**/*.kt"],
+ libs: [
+ "android.test.base",
+ ],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "junit",
+ "junit-params",
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "truth-prebuilt",
+ ],
+ platform_apis: true,
+}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/AndroidManifest.xml
new file mode 100644
index 000000000000..286ad56435fd
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.pm.test.deviceside">
+
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.pm.test.deviceside" />
+</manifest>
+
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/src/com/android/server/pm/cts/test/deviceside/DeviceSide.kt b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/src/com/android/server/pm/cts/test/deviceside/DeviceSide.kt
new file mode 100644
index 000000000000..d140662a24c2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/src/com/android/server/pm/cts/test/deviceside/DeviceSide.kt
@@ -0,0 +1,42 @@
+package com.android.server.pm.test.deviceside
+
+import android.content.pm.PackageManager.MATCH_FACTORY_ONLY
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class DeviceSide {
+ companion object {
+ private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
+ }
+
+ @Test
+ fun testGetInstalledPackagesWithFactoryOnly() {
+ val instrumentation = InstrumentationRegistry.getInstrumentation()
+ val uiAutomation = instrumentation.uiAutomation
+ val ctx = instrumentation.context
+
+ uiAutomation.adoptShellPermissionIdentity()
+ try {
+ val packages1 = ctx.packageManager.getInstalledPackages(0)
+ .filter { it.packageName == TEST_PKG_NAME }
+ val packages2 = ctx.packageManager.getInstalledPackages(MATCH_FACTORY_ONLY)
+ .filter { it.packageName == TEST_PKG_NAME }
+
+ Truth.assertWithMessage("Incorrect number of packages found")
+ .that(packages1.size).isEqualTo(1)
+ Truth.assertWithMessage("Incorrect number of packages found")
+ .that(packages2.size).isEqualTo(1)
+
+ Truth.assertWithMessage("Incorrect version code for updated package")
+ .that(packages1[0].longVersionCode).isEqualTo(2)
+ Truth.assertWithMessage("Incorrect version code for factory package")
+ .that(packages2[0].longVersionCode).isEqualTo(1)
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ }
+ }
+}
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 1cb004a6dc1e..fdcadf3e3088 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -25,6 +25,7 @@ import static android.location.Criteria.ACCURACY_COARSE;
import static android.location.Criteria.ACCURACY_FINE;
import static android.location.Criteria.POWER_HIGH;
import static android.location.LocationManager.PASSIVE_PROVIDER;
+import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static androidx.test.ext.truth.location.LocationSubject.assertThat;
@@ -907,6 +908,21 @@ public class LocationProviderManagerTest {
assertThat(mProvider.getRequest().interval).isEqualTo(5);
}
+ @Test
+ public void testProviderRequest_BatterySaver_ScreenOnOff() {
+ mInjector.getLocationPowerSaveModeHelper().setLocationPowerSaveMode(
+ LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF);
+
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false);
+ mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+
+ assertThat(mProvider.getRequest().reportLocation).isTrue();
+
+ mInjector.getScreenInteractiveHelper().setScreenInteractive(false);
+ assertThat(mProvider.getRequest().reportLocation).isFalse();
+ }
+
private ILocationListener createMockLocationListener() {
return spy(new ILocationListener.Stub() {
@Override
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml
index 597600303acb..597600303acb 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml
index 196ca28192e4..196ca28192e4 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml
index 4b7724c05d8d..4b7724c05d8d 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml
index 5b1c03ce170e..5b1c03ce170e 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml
index bec2371cff6f..bec2371cff6f 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 1b6ac3c84210..7d6d90c4578c 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -26,7 +26,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -65,6 +67,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
@@ -277,7 +280,7 @@ public class VibratorServiceTest {
assertTrue(service.isVibrating());
verify(mNativeWrapperMock).vibratorOff();
- verify(mNativeWrapperMock).vibratorOn(eq(100L));
+ verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
verify(mNativeWrapperMock).vibratorSetAmplitude(eq(128));
}
@@ -290,7 +293,7 @@ public class VibratorServiceTest {
assertTrue(service.isVibrating());
verify(mNativeWrapperMock).vibratorOff();
- verify(mNativeWrapperMock).vibratorOn(eq(100L));
+ verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
verify(mNativeWrapperMock, never()).vibratorSetAmplitude(anyInt());
}
@@ -344,76 +347,157 @@ public class VibratorServiceTest {
Mockito.clearInvocations(mNativeWrapperMock);
VibrationEffect effect = VibrationEffect.createWaveform(
- new long[] { 10, 10, 10 }, new int[] { 100, 200, 50 }, -1);
+ new long[]{10, 10, 10}, new int[]{100, 200, 50}, -1);
vibrate(service, effect);
verify(mNativeWrapperMock).vibratorOff();
+ // Wait for VibrateThread to turn vibrator ON with total timing and no callback.
Thread.sleep(5);
- verify(mNativeWrapperMock).vibratorOn(eq(30L));
+ verify(mNativeWrapperMock).vibratorOn(eq(30L), isNull());
+
+ // First amplitude set right away.
verify(mNativeWrapperMock).vibratorSetAmplitude(eq(100));
+ // Second amplitude set after first timing is finished.
Thread.sleep(10);
verify(mNativeWrapperMock).vibratorSetAmplitude(eq(200));
+ // Third amplitude set after second timing is finished.
Thread.sleep(10);
verify(mNativeWrapperMock).vibratorSetAmplitude(eq(50));
}
@Test
- public void vibrate_withCallback_finishesVibrationWhenCallbackTriggered() {
- mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
+ public void vibrate_withOneShotAndNativeCallbackTriggered_finishesVibration() {
+ doAnswer(invocation -> {
+ ((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
+ return null;
+ }).when(mNativeWrapperMock).vibratorOn(anyLong(), any(VibratorService.Vibration.class));
+ VibratorService service = createService();
+ Mockito.clearInvocations(mNativeWrapperMock);
+
+ vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+
+ InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(100L),
+ any(VibratorService.Vibration.class));
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ }
+
+ @Test
+ public void vibrate_withOneShotAndNativeCallbackNotTriggered_finishesVibrationViaFallback() {
VibratorService service = createService();
Mockito.clearInvocations(mNativeWrapperMock);
+ vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+
+ verify(mNativeWrapperMock).vibratorOff();
+ verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
+ Mockito.clearInvocations(mNativeWrapperMock);
+
+ // Run the scheduled callback to finish one-shot vibration.
+ mTestLooper.moveTimeForward(200);
+ mTestLooper.dispatchAll();
+
+ verify(mNativeWrapperMock).vibratorOff();
+ }
+
+ @Test
+ public void vibrate_withWaveformAndNativeCallback_callbackCannotBeTriggeredByNative()
+ throws Exception {
+ VibratorService service = createService();
+ Mockito.clearInvocations(mNativeWrapperMock);
+
+ VibrationEffect effect = VibrationEffect.createWaveform(new long[]{1, 3, 1, 2}, -1);
+ vibrate(service, effect);
+
+ // Wait for VibrateThread to finish: 1ms OFF, 3ms ON, 1ms OFF, 2ms ON.
+ Thread.sleep(15);
+ InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(3L), isNull());
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(2L), isNull());
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ }
+
+ @Test
+ public void vibrate_withComposedAndNativeCallbackTriggered_finishesVibration() {
+ mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
doAnswer(invocation -> {
((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
return null;
}).when(mNativeWrapperMock).vibratorPerformComposedEffect(
any(), any(VibratorService.Vibration.class));
+ VibratorService service = createService();
+ Mockito.clearInvocations(mNativeWrapperMock);
- // Use vibration with delay so there is time for the callback to be triggered.
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10)
.compose();
vibrate(service, effect);
- // Vibration canceled once before perform and once by native callback.
- verify(mNativeWrapperMock, times(2)).vibratorOff();
- verify(mNativeWrapperMock).vibratorPerformComposedEffect(
+ InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformComposedEffect(
any(VibrationEffect.Composition.PrimitiveEffect[].class),
any(VibratorService.Vibration.class));
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
}
@Test
- public void vibrate_whenBinderDies_cancelsVibration() {
+ public void vibrate_withComposedAndNativeCallbackNotTriggered_finishesVibrationViaFallback() {
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
VibratorService service = createService();
Mockito.clearInvocations(mNativeWrapperMock);
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10)
+ .compose();
+ vibrate(service, effect);
+
+ verify(mNativeWrapperMock).vibratorOff();
+ verify(mNativeWrapperMock).vibratorPerformComposedEffect(
+ any(VibrationEffect.Composition.PrimitiveEffect[].class),
+ any(VibratorService.Vibration.class));
+ Mockito.clearInvocations(mNativeWrapperMock);
+
+ // Run the scheduled callback to finish one-shot vibration.
+ mTestLooper.moveTimeForward(10000); // 10s
+ mTestLooper.dispatchAll();
+
+ verify(mNativeWrapperMock).vibratorOff();
+ }
+
+ @Test
+ public void vibrate_whenBinderDies_cancelsVibration() {
+ mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
doAnswer(invocation -> {
((VibratorService.Vibration) invocation.getArgument(1)).binderDied();
return null;
}).when(mNativeWrapperMock).vibratorPerformComposedEffect(
any(), any(VibratorService.Vibration.class));
+ VibratorService service = createService();
+ Mockito.clearInvocations(mNativeWrapperMock);
- // Use vibration with delay so there is time for the callback to be triggered.
VibrationEffect effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10)
.compose();
vibrate(service, effect);
- // Vibration canceled once before perform and once by native binder death.
- verify(mNativeWrapperMock, times(2)).vibratorOff();
- verify(mNativeWrapperMock).vibratorPerformComposedEffect(
+ InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformComposedEffect(
any(VibrationEffect.Composition.PrimitiveEffect[].class),
any(VibratorService.Vibration.class));
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
}
@Test
public void cancelVibrate_withDeviceVibrating_callsVibratorOff() {
VibratorService service = createService();
- vibrate(service, VibrationEffect.createOneShot(100, 128));
+ vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
assertTrue(service.isVibrating());
Mockito.clearInvocations(mNativeWrapperMock);
@@ -434,18 +518,20 @@ public class VibratorServiceTest {
@Test
public void registerVibratorStateListener_callbacksAreTriggered() throws Exception {
+ doAnswer(invocation -> {
+ ((VibratorService.Vibration) invocation.getArgument(1)).onComplete();
+ return null;
+ }).when(mNativeWrapperMock).vibratorOn(anyLong(), any(VibratorService.Vibration.class));
VibratorService service = createService();
service.registerVibratorStateListener(mVibratorStateListenerMock);
verify(mVibratorStateListenerMock).onVibrating(false);
+ Mockito.clearInvocations(mVibratorStateListenerMock);
vibrate(service, VibrationEffect.createOneShot(10, VibrationEffect.DEFAULT_AMPLITUDE));
- verify(mVibratorStateListenerMock).onVibrating(true);
-
- // Run the scheduled callback to finish one-shot vibration.
- mTestLooper.moveTimeForward(10);
- mTestLooper.dispatchAll();
- verify(mVibratorStateListenerMock, times(2)).onVibrating(false);
+ InOrder inOrderVerifier = inOrder(mVibratorStateListenerMock);
+ inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(true));
+ inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(false));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 9a465a91e84e..8fc228734f37 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1604,7 +1604,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setApplicationRestrictionsManagingPackage(admin1, RESTRICTIONS_DELEGATE);
// DPMS correctly stores and retrieves the delegates
- DevicePolicyManagerService.DevicePolicyData policy = dpms.mUserData.get(userHandle);
+ DevicePolicyData policy = dpms.mUserData.get(userHandle);
assertEquals(2, policy.mDelegationMap.size());
MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(CERT_DELEGATE),
DELEGATION_CERT_INSTALL);
@@ -1846,11 +1846,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
reset(getServices().userManagerInternal);
}
- private DevicePolicyManagerService.ActiveAdmin getDeviceOwner() {
+ private ActiveAdmin getDeviceOwner() {
ComponentName component = dpms.mOwners.getDeviceOwnerComponent();
- DevicePolicyManagerService.DevicePolicyData policy =
+ DevicePolicyData policy =
dpms.getUserData(dpms.mOwners.getDeviceOwnerUserId());
- for (DevicePolicyManagerService.ActiveAdmin admin : policy.mAdminList) {
+ for (ActiveAdmin admin : policy.mAdminList) {
if (component.equals(admin.info.getComponent())) {
return admin;
}
@@ -3745,8 +3745,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUserSetupCompleteForUser(false, userId);
// GIVEN userComplete is true in DPM
- DevicePolicyManagerService.DevicePolicyData userData =
- new DevicePolicyManagerService.DevicePolicyData(userId);
+ DevicePolicyData userData = new DevicePolicyData(userId);
userData.mUserSetupComplete = true;
dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
@@ -3770,8 +3769,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUserSetupCompleteForUser(false, userId);
// GIVEN userComplete is true in DPM
- DevicePolicyManagerService.DevicePolicyData userData =
- new DevicePolicyManagerService.DevicePolicyData(userId);
+ DevicePolicyData userData = new DevicePolicyData(userId);
userData.mUserSetupComplete = true;
dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
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 960a7ab52c22..ef2365e6da3e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -16,7 +16,6 @@
package com.android.server.hdmi;
import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
-import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -62,6 +61,7 @@ public class HdmiCecLocalDevicePlaybackTest {
private TestLooper mTestLooper = new TestLooper();
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
private int mPlaybackPhysicalAddress;
+ private int mPlaybackLogicalAddress;
private boolean mWokenUp;
private boolean mStandby;
@@ -129,6 +129,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress = 0x2000;
mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress);
mTestLooper.dispatchAll();
+ mPlaybackLogicalAddress = mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress();
mNativeWrapper.clearResultMessages();
}
@@ -144,7 +145,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
@@ -165,7 +166,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
@@ -186,7 +187,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
@@ -207,7 +208,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
@@ -230,7 +231,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
@@ -253,7 +254,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mPlaybackPhysicalAddress);
HdmiCecMessage expectedMessage =
- HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
@@ -262,6 +263,112 @@ public class HdmiCecLocalDevicePlaybackTest {
assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
}
+ @Test
+ public void handleRoutingChange_otherDevice_None() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingChange_otherDevice_StandbyNow() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
+ public void handleRoutingChange_otherDevice_StandbyNow_InactiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingChange_sameDevice_StandbyNow_ActiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingInformation_otherDevice_None() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingInformation_otherDevice_StandbyNow() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
+ public void handleRoutingInformation_otherDevice_StandbyNow_InactiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingInformation_sameDevice_StandbyNow_ActiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mStandby).isFalse();
+ }
+
// Playback device does not handle routing control related feature right now
@Ignore("b/120845532")
@Test
@@ -442,7 +549,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
mStandby = false;
- HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
@@ -465,7 +572,7 @@ public class HdmiCecLocalDevicePlaybackTest {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
mStandby = false;
- HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
@@ -629,4 +736,43 @@ public class HdmiCecLocalDevicePlaybackTest {
mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress());
assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
}
+
+ @Test
+ public void handleSetStreamPath_otherDevice_None() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleSetStreamPath_otherDevice_StandbyNow() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
+ public void handleSetStreamPath_otherDevice_StandbyNow_InactiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mStandby).isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 12b144f2b778..1f66c7c02658 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -129,7 +129,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID);
// verify credential
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- firstUnifiedPassword, 0, PRIMARY_USER_ID)
+ firstUnifiedPassword, PRIMARY_USER_ID, 0 /* flags */)
.getResponseCode());
// Verify that we have a new auth token for the profile
@@ -186,13 +186,13 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
// verify primary credential
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- primaryPassword, 0, PRIMARY_USER_ID)
+ primaryPassword, PRIMARY_USER_ID, 0 /* flags */)
.getResponseCode());
assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
// verify profile credential
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- profilePassword, 0, MANAGED_PROFILE_USER_ID)
+ profilePassword, MANAGED_PROFILE_USER_ID, 0 /* flags */)
.getResponseCode());
assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
@@ -203,7 +203,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
newPassword("pwd"), primaryPassword, PRIMARY_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- profilePassword, 0, MANAGED_PROFILE_USER_ID)
+ profilePassword, MANAGED_PROFILE_USER_ID, 0 /* flags */)
.getResponseCode());
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
}
@@ -389,7 +389,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
initializeStorageWithCredential(PRIMARY_USER_ID, password, 1234);
reset(mRecoverableKeyStoreManager);
- mService.verifyCredential(password, 1, PRIMARY_USER_ID);
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */);
verify(mRecoverableKeyStoreManager)
.lockScreenSecretAvailable(
@@ -406,7 +406,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
MANAGED_PROFILE_USER_ID));
reset(mRecoverableKeyStoreManager);
- mService.verifyCredential(pattern, 1, MANAGED_PROFILE_USER_ID);
+ mService.verifyCredential(pattern, MANAGED_PROFILE_USER_ID, 0 /* flags */);
verify(mRecoverableKeyStoreManager)
.lockScreenSecretAvailable(
@@ -421,7 +421,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
reset(mRecoverableKeyStoreManager);
- mService.verifyCredential(pattern, 1, PRIMARY_USER_ID);
+ mService.verifyCredential(pattern, PRIMARY_USER_ID, 0 /* flags */);
// Parent sends its credentials for both the parent and profile.
verify(mRecoverableKeyStoreManager)
@@ -484,9 +484,8 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
private void assertVerifyCredentials(int userId, LockscreenCredential credential, long sid)
throws RemoteException{
- final long challenge = 54321;
- VerifyCredentialResponse response = mService.verifyCredential(credential,
- challenge, userId);
+ VerifyCredentialResponse response = mService.verifyCredential(credential, userId,
+ 0 /* flags */);
assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
@@ -508,7 +507,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
badCredential = LockscreenCredential.createPin("0");
}
assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
- badCredential, challenge, userId).getResponseCode());
+ badCredential, userId, 0 /* flags */).getResponseCode());
}
private void initializeStorageWithCredential(int userId, LockscreenCredential credential,
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
index 4b3f7b5d08ef..9c0239b2b6a6 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
@@ -52,7 +52,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@Test
@@ -61,7 +62,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPattern("4321"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPattern("4321"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@Test
@@ -70,7 +72,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPassword("4321"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPassword("4321"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@Test
@@ -80,7 +83,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPattern("5678"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPattern("5678"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@Test
@@ -98,7 +102,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
mSettings.setDeviceProvisioned(true);
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
- mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@Test
@@ -113,7 +118,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
@@ -129,6 +135,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
- mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+ mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
+ .getResponseCode());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index ba851992cbad..2bd0e55f7d21 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -119,8 +119,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ newPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
@@ -131,12 +130,10 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
- badPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
}
@Test
@@ -153,8 +150,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
// set a new password
mService.setLockCredential(badPassword, nonePassword(), PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- badPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
@@ -166,8 +162,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- badPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
// Check the same secret was passed each time
ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
@@ -183,8 +178,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
reset(mAuthSecretService);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
}
@@ -194,8 +188,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, SECONDARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, SECONDARY_USER_ID)
- .getResponseCode());
+ password, SECONDARY_USER_ID, 0 /* flags */).getResponseCode());
verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
}
@@ -246,7 +239,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
- mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
@@ -259,8 +253,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- pattern, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ pattern, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
@@ -275,7 +268,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mLocalService.setLockCredentialWithToken(nonePassword(), handle, token, PRIMARY_USER_ID);
@@ -284,8 +278,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- pattern, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ pattern, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
@@ -301,7 +294,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.setLockCredential(pattern, password, PRIMARY_USER_ID);
@@ -309,8 +303,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ newPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
}
@@ -357,8 +350,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
// Activate token (password gets migrated to SP at the same time)
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
// Verify token is activated
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
}
@@ -488,8 +480,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
+ password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
}
@@ -503,7 +494,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
reset(mDevicePolicyManager);
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
- mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
+ mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
+ .getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
mService.onCleanupUser(PRIMARY_USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 128177b073b0..58b71d4b702a 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -462,7 +462,7 @@ public class NetworkPolicyManagerServiceTest {
@Test
public void testTurnRestrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
+ assertRestrictBackgroundOff();
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(futureIntent, null);
@@ -471,7 +471,7 @@ public class NetworkPolicyManagerServiceTest {
@Test
@NetPolicyXml("restrict-background-on.xml")
public void testTurnRestrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(false);
@@ -479,28 +479,27 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Adds whitelist when restrict background is on - app should receive an intent.
+ * Adds allowlist when restrict background is on - app should receive an intent.
*/
@Test
@NetPolicyXml("restrict-background-on.xml")
- public void testAddRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ public void testAddRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- addRestrictBackgroundWhitelist(true);
+ addRestrictBackgroundAllowlist(true);
}
/**
- * Adds whitelist when restrict background is off - app should not receive an intent.
+ * Adds allowlist when restrict background is off - app should not receive an intent.
*/
@Test
- public void testAddRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- addRestrictBackgroundWhitelist(false);
+ public void testAddRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ addRestrictBackgroundAllowlist(false);
}
- private void addRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
- // Sanity checks.
- assertWhitelistUids();
+ private void addRestrictBackgroundAllowlist(boolean expectIntent) throws Exception {
+ assertAllowlistUids();
assertUidPolicy(UID_A, POLICY_NONE);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
@@ -508,7 +507,7 @@ public class NetworkPolicyManagerServiceTest {
mService.setUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
mPolicyListener.waitAndVerify()
.onUidPoliciesChanged(APP_ID_A, POLICY_ALLOW_METERED_BACKGROUND);
@@ -520,24 +519,24 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Removes whitelist when restrict background is on - app should receive an intent.
+ * Removes allowlist when restrict background is on - app should receive an intent.
*/
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- removeRestrictBackgroundWhitelist(true);
+ removeRestrictBackgroundAllowlist(true);
}
/**
- * Removes whitelist when restrict background is off - app should not receive an intent.
+ * Removes allowlist when restrict background is off - app should not receive an intent.
*/
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-off.xml")
- public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- removeRestrictBackgroundWhitelist(false);
+ @NetPolicyXml("uidA-allowlisted-restrict-background-off.xml")
+ public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ removeRestrictBackgroundAllowlist(false);
}
@Test
@@ -688,9 +687,8 @@ public class NetworkPolicyManagerServiceTest {
assertFalse(mService.getRestrictBackground());
}
- private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
- // Sanity checks.
- assertWhitelistUids(UID_A);
+ private void removeRestrictBackgroundAllowlist(boolean expectIntent) throws Exception {
+ assertAllowlistUids(UID_A);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
@@ -698,7 +696,7 @@ public class NetworkPolicyManagerServiceTest {
mService.setUidPolicy(UID_A, POLICY_NONE);
- assertWhitelistUids();
+ assertAllowlistUids();
assertUidPolicy(UID_A, POLICY_NONE);
mPolicyListener.waitAndVerify().onUidPoliciesChanged(APP_ID_A, POLICY_NONE);
if (expectIntent) {
@@ -709,27 +707,27 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Adds blacklist when restrict background is on - app should not receive an intent.
+ * Adds denylist when restrict background is on - app should not receive an intent.
*/
@Test
@NetPolicyXml("restrict-background-on.xml")
- public void testAddRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ public void testAddRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- addRestrictBackgroundBlacklist(false);
+ addRestrictBackgroundDenylist(false);
}
/**
- * Adds blacklist when restrict background is off - app should receive an intent.
+ * Adds denylist when restrict background is off - app should receive an intent.
*/
@Test
- public void testAddRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- addRestrictBackgroundBlacklist(true);
+ public void testAddRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ addRestrictBackgroundDenylist(true);
}
- private void addRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
- assertUidPolicy(UID_A, POLICY_NONE); // Sanity check.
+ private void addRestrictBackgroundDenylist(boolean expectIntent) throws Exception {
+ assertUidPolicy(UID_A, POLICY_NONE);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt());
@@ -746,28 +744,28 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Removes blacklist when restrict background is on - app should not receive an intent.
+ * Removes denylist when restrict background is on - app should not receive an intent.
*/
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
- public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ @NetPolicyXml("uidA-denylisted-restrict-background-on.xml")
+ public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- removeRestrictBackgroundBlacklist(false);
+ removeRestrictBackgroundDenylist(false);
}
/**
- * Removes blacklist when restrict background is off - app should receive an intent.
+ * Removes denylist when restrict background is off - app should receive an intent.
*/
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-off.xml")
- public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- removeRestrictBackgroundBlacklist(true);
+ @NetPolicyXml("uidA-denylisted-restrict-background-off.xml")
+ public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ removeRestrictBackgroundDenylist(true);
}
- private void removeRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
- assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); // Sanity check.
+ private void removeRestrictBackgroundDenylist(boolean expectIntent) throws Exception {
+ assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt());
@@ -784,9 +782,8 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
- public void testBlacklistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-denylisted-restrict-background-on.xml")
+ public void testDenylistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
@@ -797,12 +794,11 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testWhitelistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testAllowlistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(true);
@@ -810,12 +806,11 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testWhitelistedAppIsNotifiedWhenBlacklisted() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testAllowlistedAppIsNotifiedWhenDenylisted() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
@@ -823,8 +818,8 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("restrict-background-lists-whitelist-format.xml")
- public void testRestrictBackgroundLists_whitelistFormat() throws Exception {
+ @NetPolicyXml("restrict-background-lists-allowlist-format.xml")
+ public void testRestrictBackgroundLists_allowlistFormat() throws Exception {
restrictBackgroundListsTest();
}
@@ -835,33 +830,33 @@ public class NetworkPolicyManagerServiceTest {
}
private void restrictBackgroundListsTest() throws Exception {
- // UIds that are whitelisted.
- assertWhitelistUids(UID_A, UID_B, UID_C);
+ // UIds that are allowlisted.
+ assertAllowlistUids(UID_A, UID_B, UID_C);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_B, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_C, POLICY_ALLOW_METERED_BACKGROUND);
- // UIDs that are blacklisted.
+ // UIDs that are denylisted.
assertUidPolicy(UID_D, POLICY_NONE);
assertUidPolicy(UID_E, POLICY_REJECT_METERED_BACKGROUND);
// UIDS that have legacy policies.
assertUidPolicy(UID_F, 2); // POLICY_ALLOW_BACKGROUND_BATTERY_SAVE
- // Remove whitelist.
+ // Remove allowlist.
mService.setUidPolicy(UID_A, POLICY_NONE);
assertUidPolicy(UID_A, POLICY_NONE);
- assertWhitelistUids(UID_B, UID_C);
+ assertAllowlistUids(UID_B, UID_C);
- // Add whitelist when blacklisted.
+ // Add allowlist when denylisted.
mService.setUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
- assertWhitelistUids(UID_B, UID_C, UID_E);
+ assertAllowlistUids(UID_B, UID_C, UID_E);
- // Add blacklist when whitelisted.
+ // Add denylist when allowlisted.
mService.setUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
- assertWhitelistUids(UID_C, UID_E);
+ assertAllowlistUids(UID_C, UID_E);
}
/**
@@ -870,9 +865,9 @@ public class NetworkPolicyManagerServiceTest {
@Test
@NetPolicyXml("restrict-background-lists-mixed-format.xml")
public void testRestrictBackgroundLists_mixedFormat() throws Exception {
- assertWhitelistUids(UID_A, UID_C, UID_D);
+ assertAllowlistUids(UID_A, UID_C, UID_D);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
- assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Blacklist prevails.
+ assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Denylist prevails.
assertUidPolicy(UID_C, (POLICY_ALLOW_METERED_BACKGROUND | 2));
assertUidPolicy(UID_D, POLICY_ALLOW_METERED_BACKGROUND);
}
@@ -2045,7 +2040,7 @@ public class NetworkPolicyManagerServiceTest {
}
}
- private void assertWhitelistUids(int... uids) {
+ private void assertAllowlistUids(int... uids) {
assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND), uids);
}
@@ -2133,7 +2128,6 @@ public class NetworkPolicyManagerServiceTest {
private void setRestrictBackground(boolean flag) throws Exception {
mService.setRestrictBackground(flag);
- // Sanity check.
assertEquals("restrictBackground not set", flag, mService.getRestrictBackground());
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 980772bb08bc..5b2d738eb760 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4856,6 +4856,70 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
+ Exception {
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = true;
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ // notifications from this package are blocked by the user
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE);
+
+ setAppInForegroundForToasts(mUid, false);
+
+ // enqueue toast -> toast should still enqueue
+ ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(),
+ new TestableToastCallback(), 2000, 0);
+ assertEquals(1, mService.mToastQueue.size());
+ verify(mAm).setProcessImportant(any(), anyInt(), eq(true), any());
+ }
+
+ @Test
+ public void foregroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
+ Exception {
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = false;
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ setAppInForegroundForToasts(mUid, true);
+
+ // enqueue toast -> toast should still enqueue
+ ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
+ "Text", 2000, 0, null);
+ assertEquals(1, mService.mToastQueue.size());
+ verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
+ }
+
+ @Test
+ public void backgroundTextToast_callsSetProcessImportantAsNotForegroundForToast() throws
+ Exception {
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = false;
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ setAppInForegroundForToasts(mUid, false);
+
+ // enqueue toast -> toast should still enqueue
+ ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(),
+ "Text", 2000, 0, null);
+ assertEquals(1, mService.mToastQueue.size());
+ verify(mAm).setProcessImportant(any(), anyInt(), eq(false), any());
+ }
+
+ @Test
public void testTextToastsCallStatusBar() throws Exception {
final String testPackage = "testPackageName";
assertEquals(0, mService.mToastQueue.size());
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index b3d75d31cb60..4ca5b9e4b14f 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -2,15 +2,37 @@
// Build WmTests package
//########################################################################
+// Include all test java files.
+filegroup {
+ name: "wmtests-sources",
+ srcs: [
+ "src/**/*.java",
+ ],
+}
+
+genrule {
+ name: "wmtests.protologsrc",
+ srcs: [
+ ":protolog-groups",
+ ":wmtests-sources",
+ ],
+ tools: ["protologtool"],
+ cmd: "$(location protologtool) transform-protolog-calls " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
+ "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
+ "--output-srcjar $(out) " +
+ "$(locations :wmtests-sources)",
+ out: ["wmtests.protolog.srcjar"],
+}
+
android_test {
name: "WmTests",
// We only want this apk build for tests.
-
- // Include all test java files.
- srcs: [
- "src/**/*.java",
- ],
+ srcs: [":wmtests.protologsrc"],
static_libs: [
"frameworks-base-testutils",
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 6061f13fcee5..f860e174fd15 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1506,7 +1506,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
params.width = params.height = WindowManager.LayoutParams.MATCH_PARENT;
- final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
+ final TestWindowState w = new TestWindowState(
mAtm.mWindowManager, mock(Session.class), new TestIWindow(), params, mActivity);
mActivity.addWindow(w);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 2e988af29638..567610018fc1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -225,5 +225,27 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
mockSession.finishMocking();
}
+
+ @Test
+ public void testResumeNextActivityOnCrashedAppDied() {
+ mSupervisor.beginDeferResume();
+ final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
+ .setTask(mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootHomeTask())
+ .build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ mSupervisor.endDeferResume();
+ // Assume the activity is finishing and hidden because it was crashed.
+ activity.finishing = true;
+ activity.mVisibleRequested = false;
+ activity.setVisible(false);
+ activity.getRootTask().mPausingActivity = activity;
+ homeActivity.setState(Task.ActivityState.PAUSED, "test");
+
+ // Even the visibility states are invisible, the next activity should be resumed because
+ // the crashed activity was pausing.
+ mAtm.mInternal.handleAppDied(activity.app, false /* restarting */,
+ null /* finishInstrumentationCallback */);
+ assertEquals(Task.ActivityState.RESUMED, homeActivity.getState());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 7adceade0b9b..1b2192035213 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -133,10 +133,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
@@ -162,13 +162,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (closing, invisible)
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (opening, visible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
activity1.setVisible(true);
activity1.mVisibleRequested = true;
activity1.mRequestForceTransition = true;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
activity2.mRequestForceTransition = true;
@@ -193,10 +193,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_exitingBeforeTransition() {
// Create another non-empty task so the animation target won't promote to task display area.
- WindowTestUtils.createTestActivityRecord(
+ createTestActivityRecord(
mDisplayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(stack);
+ final ActivityRecord activity = createTestActivityRecord(stack);
activity.setVisible(false);
activity.mIsExiting = true;
@@ -218,20 +218,20 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
// +- [AppWindow2] (being-replaced)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow1");
- final WindowTestUtils.TestWindowState appWindow1 = createWindowState(attrs, activity1);
+ final TestWindowState appWindow1 = createWindowState(attrs, activity1);
appWindow1.mWillReplaceWindow = true;
activity1.addWindow(appWindow1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
attrs.setTitle("AppWindow2");
- final WindowTestUtils.TestWindowState appWindow2 = createWindowState(attrs, activity2);
+ final TestWindowState appWindow2 = createWindowState(attrs, activity2);
appWindow2.mWillReplaceWindow = true;
activity2.addWindow(appWindow2);
@@ -262,21 +262,17 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord4] (invisible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
activity4.setVisible(false);
activity4.mVisibleRequested = false;
@@ -303,12 +299,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -337,22 +331,18 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -381,24 +371,20 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
activity2.setVisible(false);
activity2.mVisibleRequested = true;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -425,13 +411,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [Task2] - [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
final Task task2 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 17914e7fb68c..ee030af36b8f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -151,8 +151,7 @@ public class AppTransitionTests extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(dc1);
+ final ActivityRecord activity1 = createTestActivityRecord(dc1);
task1.addChild(activity1, 0);
// Simulate same app is during opening / closing transition set stage.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 888935ef9747..085b8dec2cb7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -92,7 +92,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mActivity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ mActivity = createTestActivityRecord(mDisplayContent);
mTask.addChild(mActivity, 0);
}
@@ -165,7 +165,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
mActivity.addWindow(appWindow);
// Set initial orientation and update.
@@ -198,7 +198,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("RotationByPolicy");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
mActivity.addWindow(appWindow);
// Set initial orientation and update.
@@ -244,7 +244,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
TYPE_BASE_APPLICATION);
attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
attrs.setTitle("AppWindow");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
// Add window with show when locked flag
mActivity.addWindow(appWindow);
@@ -307,7 +307,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertEquals(Configuration.ORIENTATION_PORTRAIT, displayConfig.orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, activityConfig.orientation);
- final ActivityRecord topActivity = WindowTestUtils.createTestActivityRecord(mStack);
+ final ActivityRecord topActivity = createTestActivityRecord(mStack);
topActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertEquals(Configuration.ORIENTATION_LANDSCAPE, displayConfig.orientation);
@@ -490,8 +490,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
}
private ActivityRecord createTestActivityRecordForGivenTask(Task task) {
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
task.addChild(activity, 0);
waitUntilHandlersIdle();
return activity;
@@ -562,7 +561,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void testHasStartingWindow() {
final WindowManager.LayoutParams attrs =
new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
- final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mActivity);
+ final TestWindowState startingWindow = createWindowState(attrs, mActivity);
mActivity.startingDisplayed = true;
mActivity.addWindow(startingWindow);
assertTrue("Starting window should be present", mActivity.hasStartingWindow());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 0cc61599c2ac..d54b4a0a72f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -326,7 +326,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
+ final ActivityRecord activity = createTestActivityRecord(dc);
task.addChild(activity, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, activity.getDisplayContent());
@@ -397,16 +397,14 @@ public class DisplayContentTests extends WindowTestsBase {
// Add stack with activity.
final Task stack0 = createTaskStackOnDisplay(dc0);
final Task task0 = createTaskInStack(stack0, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(dc0);
+ final ActivityRecord activity = createTestActivityRecord(dc0);
task0.addChild(activity, 0);
dc0.configureDisplayPolicy();
assertNotNull(dc0.mTapDetector);
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(dc0);
+ final ActivityRecord activity1 = createTestActivityRecord(dc0);
task1.addChild(activity1, 0);
dc1.configureDisplayPolicy();
assertNotNull(dc1.mTapDetector);
@@ -1296,7 +1294,7 @@ public class DisplayContentTests extends WindowTestsBase {
final ActivityRecord pinnedActivity = createActivityRecord(displayContent,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
final Task pinnedTask = pinnedActivity.getRootTask();
- final ActivityRecord homeActivity = WindowTestUtils.createTestActivityRecord(
+ final ActivityRecord homeActivity = createTestActivityRecord(
displayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
if (displayConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
homeActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
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 4ea5b97decf4..0675c6d04422 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -48,12 +48,14 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_RIGHT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -874,6 +876,19 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
@Test
+ public void testFixedRotationInsetsSourceFrame() {
+ mDisplayPolicy.beginLayoutLw(mFrames, mDisplayContent.getConfiguration().uiMode);
+ doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent)
+ .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
+ final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+ mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
+ final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+
+ assertEquals(DISPLAY_WIDTH, frame.width());
+ assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
+ }
+
+ @Test
public void testScreenDecorWindows() {
final WindowState decorWindow = spy(
createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow"));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index e18d93d82686..45369975fcc5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -95,8 +95,7 @@ public class DragDropControllerTests extends WindowTestsBase {
* Creates a window state which can be used as a drop target.
*/
private WindowState createDropTargetWindow(String name, int ownerId) {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(
- mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, ownerId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 5e83e66536ed..085230d35c6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -28,6 +28,9 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -40,6 +43,7 @@ import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.util.IntArray;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
@@ -328,6 +332,27 @@ public class InsetsStateControllerTest extends WindowTestsBase {
assertNull(getController().getControlsForDispatch(app));
}
+ @Test
+ public void testTransientVisibilityOfFixedRotationState() {
+ final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final InsetsSourceProvider provider = getController().getSourceProvider(ITYPE_STATUS_BAR);
+ provider.setWindow(statusBar, null, null);
+
+ final InsetsState rotatedState = new InsetsState(app.getInsetsState(),
+ true /* copySources */);
+ spyOn(app.mToken);
+ doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
+ assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+
+ provider.getSource().setVisible(false);
+ mDisplayContent.getInsetsPolicy().showTransient(
+ IntArray.wrap(new int[] { ITYPE_STATUS_BAR }));
+
+ assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
+ assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
+ }
+
private InsetsStateController getController() {
return mDisplayContent.getInsetsStateController();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
index d1510cf811fb..8223024234fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
@@ -25,9 +25,12 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogGroup;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import org.junit.After;
+import org.junit.Ignore;
import org.junit.Test;
/**
@@ -35,6 +38,7 @@ import org.junit.Test;
*/
@SmallTest
@Presubmit
+@Ignore("b/163095037")
public class ProtoLogIntegrationTest {
@After
public void tearDown() {
@@ -44,17 +48,21 @@ public class ProtoLogIntegrationTest {
@Test
public void testProtoLogToolIntegration() {
ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class);
- runWith(mockedProtoLog, () -> {
- ProtoLogGroup.testProtoLog();
- });
+ runWith(mockedProtoLog, this::testProtoLog);
verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP),
anyInt(), eq(0b0010101001010111),
- eq(ProtoLogGroup.TEST_GROUP.isLogToLogcat()
+ eq(com.android.internal.protolog.ProtoLogGroup.TEST_GROUP.isLogToLogcat()
? "Test completed successfully: %b %d %o %x %e %g %f %% %s"
: null),
eq(new Object[]{true, 1L, 2L, 3L, 0.4, 0.5, 0.6, "ok"}));
}
+ private void testProtoLog() {
+ ProtoLog.e(ProtoLogGroup.TEST_GROUP,
+ "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
+ true, 1, 2, 3, 0.4, 0.5, 0.6, "ok");
+ }
+
/**
* Starts protolog for the duration of {@code runnable}, with a ProtoLogImpl instance installed.
*/
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 0e1d4dc4aa0d..982e469cba92 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -568,7 +568,9 @@ public class SizeCompatTests extends WindowTestsBase {
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
- final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
+ params.setFitInsetsSides(0);
+ params.setFitInsetsTypes(0);
+ final TestWindowState w = new TestWindowState(
activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
WindowTestsBase.makeWindowVisible(w);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
@@ -581,7 +583,7 @@ public class SizeCompatTests extends WindowTestsBase {
doReturn(true).when(displayPolicy).hasStatusBar();
displayPolicy.onConfigurationChanged();
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
+ final TestWindowToken token = createTestWindowToken(
WindowManager.LayoutParams.TYPE_STATUS_BAR, displayContent);
final WindowManager.LayoutParams attrs =
new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_STATUS_BAR);
@@ -589,7 +591,7 @@ public class SizeCompatTests extends WindowTestsBase {
attrs.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
attrs.setFitInsetsTypes(0 /* types */);
- final WindowTestUtils.TestWindowState statusBar = new WindowTestUtils.TestWindowState(
+ final TestWindowState statusBar = new TestWindowState(
displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
token.addWindow(statusBar);
statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 3492556b3682..260f1e9a9259 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -76,8 +76,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
- final ActivityRecord pinnedApp =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord pinnedApp = createTestActivityRecord(mDisplayContent);
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
assertTrue(mPinnedStack.isVisible());
}
@@ -92,7 +91,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
task.addChild(activity, 0 /* addPos */);
final TaskDisplayArea taskDisplayArea = activity.getDisplayArea();
activity.mNeedsAnimationBoundsLayer = true;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 205b842253b7..7cf30c0c9f35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -85,14 +85,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testClosingAppDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2=
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -105,14 +103,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testMoveTaskToBackDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
@@ -221,7 +217,7 @@ public class TaskStackTests extends WindowTestsBase {
public void testActivityAndTaskGetsProperType() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
// First activity should become standard
task1.addChild(activity1, 0);
@@ -229,7 +225,7 @@ public class TaskStackTests extends WindowTestsBase {
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
// Second activity should also become standard
- ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity2, WindowContainer.POSITION_TOP);
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, activity2.getActivityType());
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 92b6e6ef8ec9..ace0400bc293 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -56,8 +56,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
task.removeIfPossible();
// Assert that the container was removed.
@@ -70,8 +69,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer_deferRemoval() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
doReturn(true).when(task).shouldDeferRemoval();
@@ -153,10 +151,8 @@ public class TaskTests extends WindowTestsBase {
public void testIsInStack() {
final Task task1 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task1);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
assertEquals(activity1, task1.isInTask(activity1));
assertNull(task1.isInTask(activity2));
}
@@ -165,12 +161,9 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveChildForOverlayTask() {
final Task task = createTaskStackOnDisplay(mDisplayContent);
final int taskId = task.mTaskId;
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity3 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task);
activity1.setTaskOverlay(true);
activity2.setTaskOverlay(true);
activity3.setTaskOverlay(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 75ed928b08a0..6ed762283524 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -44,7 +44,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testFlow() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
@@ -56,8 +56,8 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testMultiple() {
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity2);
@@ -72,7 +72,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testClear() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.clear();
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
@@ -80,7 +80,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testRemoveFinishingInvisibleActivityFromUnknown() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
activity.finishing = true;
activity.mVisibleRequested = true;
@@ -90,7 +90,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testAppRemoved() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(activity);
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 8ac44f2afcfd..4163a9a546a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -810,8 +810,7 @@ public class WindowContainerTests extends WindowTestsBase {
public void testOnDisplayChanged() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
final DisplayContent newDc = createNewDisplay();
stack.getDisplayArea().removeStack(stack);
@@ -854,19 +853,17 @@ public class WindowContainerTests extends WindowTestsBase {
public void testTaskCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
verifyWindowContainerApplyAnimation(task, activity1, activity2);
}
@Test
public void testStackCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
verifyWindowContainerApplyAnimation(stack, activity1, activity2);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 8cfa4f00c8b6..91352972e772 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -931,8 +931,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord record = WindowTestUtils.createActivityRecordInTask(
- stack.mDisplayContent, task);
+ final ActivityRecord record = createActivityRecordInTask(stack.mDisplayContent, task);
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
@@ -966,8 +965,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
public void testInterceptBackPressedOnTaskRoot() throws RemoteException {
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(
- stack.mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
// Setup the task to be controlled by the MW mode organizer
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3894a2eaa461..f095fd42900b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -357,8 +357,7 @@ public class WindowStateTests extends WindowTestsBase {
// Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
// activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
- final WindowToken windowToken = WindowTestUtils.createTestWindowToken(FIRST_SUB_WINDOW,
- mDisplayContent);
+ final WindowToken windowToken = createTestWindowToken(FIRST_SUB_WINDOW, mDisplayContent);
final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
"firstWindow");
final WindowState secondWindow = createWindow(null, TYPE_APPLICATION, windowToken,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
deleted file mode 100644
index 0180d87290a1..000000000000
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.AppOpsManager.OP_NONE;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-
-import android.os.IBinder;
-import android.view.IWindow;
-import android.view.WindowManager;
-
-import com.android.server.wm.WindowTestsBase.ActivityBuilder;
-
-/**
- * A collection of static functions that provide access to WindowManager related test functionality.
- */
-class WindowTestUtils {
-
- /** Creates a {@link Task} and adds it to the specified {@link Task}. */
- static Task createTaskInStack(WindowManagerService service, Task stack, int userId) {
- final Task task = new WindowTestsBase.TaskBuilder(stack.mStackSupervisor)
- .setUserId(userId)
- .setStack(stack)
- .build();
- return task;
- }
-
- /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
- static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
- final ActivityRecord activity = createTestActivityRecord(dc);
- task.addChild(activity, POSITION_TOP);
- return activity;
- }
-
- static ActivityRecord createTestActivityRecord(Task stack) {
- final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
- .setStack(stack)
- .setCreateTask(true)
- .build();
- postCreateActivitySetup(activity, stack.getDisplayContent());
- return activity;
- }
-
- static ActivityRecord createTestActivityRecord(DisplayContent dc) {
- final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
- postCreateActivitySetup(activity, dc);
- return activity;
- }
-
- private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
- activity.onDisplayChanged(dc);
- activity.setOccludesParent(true);
- activity.setVisible(true);
- activity.mVisibleRequested = true;
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
- return createTestWindowToken(type, dc, false /* persistOnEmpty */);
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
- boolean persistOnEmpty) {
- SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);
-
- return new TestWindowToken(type, dc, persistOnEmpty);
- }
-
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- static class TestWindowToken extends WindowToken {
-
- private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
- false /* ownerCanManageAppTokens */);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
- }
-
- /** Used to track resize reports. */
- static class TestWindowState extends WindowState {
- boolean mResizeReported;
-
- TestWindowState(WindowManagerService service, Session session, IWindow window,
- WindowManager.LayoutParams attrs, WindowToken token) {
- super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, 0,
- false /* ownerCanAddInternalSystemWindow */);
- }
-
- @Override
- void reportResized() {
- super.reportResized();
- mResizeReported = true;
- }
-
- @Override
- public boolean isGoneForLayoutLw() {
- return false;
- }
-
- @Override
- void updateResizingWindowIfNeeded() {
- // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
- // the system that it can actually update the window.
- boolean hadSurface = mHasSurface;
- mHasSurface = true;
-
- super.updateResizingWindowIfNeeded();
-
- mHasSurface = hadSurface;
- }
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index ec19a58b17c4..5ce61b4e4916 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -47,6 +47,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -66,6 +67,7 @@ import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
@@ -239,7 +241,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
private WindowToken createWindowToken(
DisplayContent dc, int windowingMode, int activityType, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return WindowTestUtils.createTestWindowToken(type, dc);
+ return createTestWindowToken(type, dc);
}
return createActivityRecord(dc, windowingMode, activityType);
@@ -249,10 +251,39 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createTestActivityRecord(dc, windowingMode, activityType);
}
- ActivityRecord createTestActivityRecord(DisplayContent dc, int
- windowingMode, int activityType) {
+ ActivityRecord createTestActivityRecord(DisplayContent dc, int windowingMode,
+ int activityType) {
final Task stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
- return WindowTestUtils.createTestActivityRecord(stack);
+ return createTestActivityRecord(stack);
+ }
+
+ /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
+ static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
+ final ActivityRecord activity = createTestActivityRecord(dc);
+ task.addChild(activity, POSITION_TOP);
+ return activity;
+ }
+
+ static ActivityRecord createTestActivityRecord(DisplayContent dc) {
+ final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
+ postCreateActivitySetup(activity, dc);
+ return activity;
+ }
+
+ static ActivityRecord createTestActivityRecord(Task stack) {
+ final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
+ .setStack(stack)
+ .setCreateTask(true)
+ .build();
+ postCreateActivitySetup(activity, stack.getDisplayContent());
+ return activity;
+ }
+
+ private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
+ activity.onDisplayChanged(dc);
+ activity.setOccludesParent(true);
+ activity.setVisible(true);
+ activity.mVisibleRequested = true;
}
WindowState createWindow(WindowState parent, int type, String name) {
@@ -274,8 +305,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
WindowState createAppWindow(Task task, int type, String name) {
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(task.getDisplayContent());
+ final ActivityRecord activity = createTestActivityRecord(task.getDisplayContent());
task.addChild(activity, 0);
return createWindow(null, type, activity, name);
}
@@ -390,7 +420,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
/** Creates a {@link Task} and adds it to the specified {@link Task}. */
Task createTaskInStack(Task stack, int userId) {
- return WindowTestUtils.createTaskInStack(mWm, stack, userId);
+ final Task task = new TaskBuilder(stack.mStackSupervisor)
+ .setUserId(userId)
+ .setStack(stack)
+ .build();
+ return task;
}
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
@@ -432,12 +466,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createNewDisplay(displayInfo, true /* supportIme */);
}
- /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
- WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
- WindowToken token) {
+ /** Creates a {@link TestWindowState} */
+ TestWindowState createWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
- return new WindowTestUtils.TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
+ return new TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
}
/** Creates a {@link DisplayContent} as parts of simulate display info for test. */
@@ -1055,4 +1088,66 @@ class WindowTestsBase extends SystemServiceTestsBase {
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
}
}
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
+ return createTestWindowToken(type, dc, false /* persistOnEmpty */);
+ }
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
+ boolean persistOnEmpty) {
+ SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);
+
+ return new TestWindowToken(type, dc, persistOnEmpty);
+ }
+
+ /** Used so we can gain access to some protected members of the {@link WindowToken} class */
+ static class TestWindowToken extends WindowToken {
+
+ private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+
+ /** Used to track resize reports. */
+ static class TestWindowState extends WindowState {
+ boolean mResizeReported;
+
+ TestWindowState(WindowManagerService service, Session session, IWindow window,
+ WindowManager.LayoutParams attrs, WindowToken token) {
+ super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ mResizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index f185da395754..d9c48fc4ba37 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -58,8 +58,7 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testAddWindow() {
- final WindowTestUtils.TestWindowToken token =
- WindowTestUtils.createTestWindowToken(0, mDisplayContent);
+ final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -93,7 +92,7 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testChildRemoval() {
final DisplayContent dc = mDisplayContent;
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(0, dc);
+ final TestWindowToken token = createTestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
@@ -116,7 +115,7 @@ public class WindowTokenTests extends WindowTestsBase {
*/
@Test
public void testTokenRemovalProcess() {
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
+ final TestWindowToken token = createTestWindowToken(
TYPE_TOAST, mDisplayContent, true /* persistOnEmpty */);
// Verify that the token is on the display
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index bcb1736f416e..464f318a8bac 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1209,11 +1209,14 @@ public class TelecomManager {
/**
* Returns a list of all {@link PhoneAccount}s registered for the calling package.
*
+ * @deprecated Use {@link #getSelfManagedPhoneAccounts()} instead to get only self-managed
+ * {@link PhoneAccountHandle} for the calling package.
* @return A list of {@code PhoneAccountHandle} objects.
* @hide
*/
@SystemApi
@SuppressLint("Doclava125")
+ @Deprecated
public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
try {
if (isServiceConnected()) {
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index e233fed7e785..9da17db6a573 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -11,6 +11,7 @@ android_test {
"androidx.test.rules",
"mockito-target-minus-junit4",
"truth-prebuilt",
+ "platform-test-annotations",
],
java_resource_dirs: ["res"],
certificate: "platform",
diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
index 3e9f625ecdd9..3db011683a86 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package com.android.server.protolog;
+package com.android.internal.protolog;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.server.protolog.ProtoLogImpl.PROTOLOG_VERSION;
+import static com.android.internal.protolog.ProtoLogImpl.PROTOLOG_VERSION;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -42,7 +42,7 @@ import android.util.proto.ProtoInputStream;
import androidx.test.filters.SmallTest;
-import com.android.server.protolog.common.IProtoLogGroup;
+import com.android.internal.protolog.common.IProtoLogGroup;
import org.junit.After;
import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
index 02540559fbd0..ae5021638745 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog;
+package com.android.internal.protolog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
diff --git a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java
index 4c7f5fdc821c..e20ca3df57c7 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
import static org.junit.Assert.assertEquals;
diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt b/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
index c3d689c5209d..9b15b0445642 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
@@ -26,10 +26,10 @@ import android.widget.LinearLayout
import android.widget.TextView
import com.android.test.silkfx.R
import com.android.test.silkfx.app.WindowObserver
-import java.lang.Exception
class ColorModeControls : LinearLayout, WindowObserver {
private val COLOR_MODE_HDR10 = 3
+ private val SDR_WHITE_POINTS = floatArrayOf(200f, 250f, 300f, 350f, 400f, 100f, 150f)
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
@@ -37,14 +37,17 @@ class ColorModeControls : LinearLayout, WindowObserver {
}
private var window: Window? = null
- private var currentMode: TextView? = null
+ private var currentModeDisplay: TextView? = null
private val displayManager: DisplayManager
+ private var targetSdrWhitePointIndex = 0
+
+ private val whitePoint get() = SDR_WHITE_POINTS[targetSdrWhitePointIndex]
override fun onFinishInflate() {
super.onFinishInflate()
val window = window ?: throw IllegalStateException("Failed to attach window")
- currentMode = findViewById(R.id.current_mode)!!
+ currentModeDisplay = findViewById(R.id.current_mode)!!
setColorMode(window.colorMode)
findViewById<Button>(R.id.mode_default)!!.setOnClickListener {
@@ -63,21 +66,30 @@ class ColorModeControls : LinearLayout, WindowObserver {
private fun setColorMode(newMode: Int) {
val window = window!!
+ var sdrWhitepointChanged = false
// Need to do this before setting the colorMode, as setting the colorMode will
// trigger the attribute change listener
if (newMode == ActivityInfo.COLOR_MODE_HDR ||
newMode == COLOR_MODE_HDR10) {
+ if (window.colorMode == newMode) {
+ targetSdrWhitePointIndex = (targetSdrWhitePointIndex + 1) % SDR_WHITE_POINTS.size
+ sdrWhitepointChanged = true
+ }
setBrightness(1.0f)
} else {
setBrightness(.4f)
}
window.colorMode = newMode
- currentMode?.run {
+ if (sdrWhitepointChanged) {
+ threadedRenderer?.setColorMode(newMode, whitePoint)
+ }
+ val whitePoint = whitePoint.toInt()
+ currentModeDisplay?.run {
text = "Current Mode: " + when (newMode) {
ActivityInfo.COLOR_MODE_DEFAULT -> "Default/SRGB"
ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT -> "Wide Gamut"
- ActivityInfo.COLOR_MODE_HDR -> "HDR (sdr white point 150)"
- COLOR_MODE_HDR10 -> "HDR10 (sdr white point 150)"
+ ActivityInfo.COLOR_MODE_HDR -> "HDR (sdr white point $whitePoint)"
+ COLOR_MODE_HDR10 -> "HDR10 (sdr white point $whitePoint)"
else -> "Unknown"
}
}
@@ -101,4 +113,10 @@ class ColorModeControls : LinearLayout, WindowObserver {
}
}
}
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+
+ threadedRenderer?.setColorMode(window!!.colorMode, whitePoint)
+ }
} \ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
index e517c3c62e2a..4ad21faec9d4 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
@@ -71,9 +71,9 @@ class BlingyNotification : BaseDrawingView {
paint.shader = LinearGradient(0f, 0f, w.toFloat(), 0f,
longArrayOf(
color(1f, 1f, 1f, 0f),
- color(1f, 1f, 1f, .4f),
- color(2f, 2f, 2f, .8f),
- color(1f, 1f, 1f, .4f),
+ color(1f, 1f, 1f, .1f),
+ color(2f, 2f, 2f, .3f),
+ color(1f, 1f, 1f, .2f),
color(1f, 1f, 1f, 0f)
),
floatArrayOf(.2f, .4f, .5f, .6f, .8f),
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 5285b04f67d7..55def498a0cd 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -22,7 +22,8 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import com.android.cts.install.lib.host.InstallUtilsHost;
+import android.cts.install.lib.host.InstallUtilsHost;
+
import com.android.ddmlib.Log;
import com.android.tests.rollback.host.AbandonSessionsRule;
import com.android.tests.util.ModuleTestUtils;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index f9c54f645e2c..d84ca3d92f67 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -78,6 +78,8 @@ using ::android::base::StringPrintf;
namespace aapt {
+constexpr uint8_t kAndroidPackageId = 0x01;
+
class LinkContext : public IAaptContext {
public:
explicit LinkContext(IDiagnostics* diagnostics)
@@ -1805,7 +1807,7 @@ class Linker {
// Override the package ID when it is "android".
if (context_->GetCompilationPackage() == "android") {
- context_->SetPackageId(0x01);
+ context_->SetPackageId(kAndroidPackageId);
// Verify we're building a regular app.
if (context_->GetPackageType() != PackageType::kApp) {
@@ -1862,7 +1864,8 @@ class Linker {
if (context_->GetPackageType() != PackageType::kStaticLib) {
PrivateAttributeMover mover;
- if (!mover.Consume(context_, &final_table_)) {
+ if (context_->GetPackageId() == kAndroidPackageId &&
+ !mover.Consume(context_, &final_table_)) {
context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes");
return 1;
}
diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp
index ce551bd0cc10..0be80d31990a 100644
--- a/tools/protologtool/Android.bp
+++ b/tools/protologtool/Android.bp
@@ -2,9 +2,9 @@ java_library_host {
name: "protologtool-lib",
srcs: [
"src/com/android/protolog/tool/**/*.kt",
+ ":protolog-common-src",
],
static_libs: [
- "protolog-common",
"javaparser",
"platformprotos",
"jsonlib",
diff --git a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
index a59038fc99a0..645c5672da64 100644
--- a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
@@ -16,16 +16,15 @@
package com.android.protolog.tool
+import com.android.internal.protolog.ProtoLogFileProto
+import com.android.internal.protolog.ProtoLogMessage
+import com.android.internal.protolog.common.InvalidFormatStringException
+import com.android.internal.protolog.common.LogDataType
import com.android.json.stream.JsonReader
-import com.android.server.protolog.common.InvalidFormatStringException
-import com.android.server.protolog.common.LogDataType
-import com.android.server.protolog.ProtoLogMessage
-import com.android.server.protolog.ProtoLogFileProto
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.PrintStream
-import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
index 75493b6427cb..42b628b0e262 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
@@ -17,7 +17,7 @@
package com.android.protolog.tool
import com.android.protolog.tool.Constants.ENUM_VALUES_METHOD
-import com.android.server.protolog.common.IProtoLogGroup
+import com.android.internal.protolog.common.IProtoLogGroup
import java.io.File
import java.net.URLClassLoader
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 36ea41129450..27e61a139451 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -16,7 +16,7 @@
package com.android.protolog.tool
-import com.android.server.protolog.common.LogDataType
+import com.android.internal.protolog.common.LogDataType
import com.github.javaparser.StaticJavaParser
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.NodeList
@@ -89,7 +89,7 @@ class SourceTransformer(
// Out: ProtoLog.e(GROUP, 1234, 0, null, arg)
newCall.arguments.add(2, IntegerLiteralExpr(typeMask))
// Replace call to a stub method with an actual implementation.
- // Out: com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, null, arg)
+ // Out: ProtoLogImpl.e(GROUP, 1234, null, arg)
newCall.setScope(protoLogImplClassNode)
// Create a call to ProtoLog$Cache.GROUP_enabled
// Out: com.android.server.protolog.ProtoLog$Cache.GROUP_enabled
@@ -119,9 +119,9 @@ class SourceTransformer(
}
blockStmt.addStatement(ExpressionStmt(newCall))
// Create an IF-statement with the previously created condition.
- // Out: if (com.android.server.protolog.ProtoLogImpl.isEnabled(GROUP)) {
+ // Out: if (ProtoLogImpl.isEnabled(GROUP)) {
// long protoLogParam0 = arg;
- // com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0);
+ // ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0);
// }
ifStmt = IfStmt(isLogEnabled, blockStmt, null)
} else {
diff --git a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
index cf36651c3e39..3cfbb435a764 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
@@ -31,7 +31,7 @@ class CommandOptionsTest {
private const val TEST_PROTOLOG_CLASS = "com.android.server.wm.ProtoLog"
private const val TEST_PROTOLOGIMPL_CLASS = "com.android.server.wm.ProtoLogImpl"
private const val TEST_PROTOLOGCACHE_CLASS = "com.android.server.wm.ProtoLog\$Cache"
- private const val TEST_PROTOLOGGROUP_CLASS = "com.android.server.wm.ProtoLogGroup"
+ private const val TEST_PROTOLOGGROUP_CLASS = "com.android.internal.protolog.ProtoLogGroup"
private const val TEST_PROTOLOGGROUP_JAR = "out/soong/.intermediates/frameworks/base/" +
"services/core/services.core.wm.protologgroups/android_common/javac/" +
"services.core.wm.protologgroups.jar"
diff --git a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
index dd8a0b1c50b4..0d2b91d6cfb8 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
@@ -33,8 +33,8 @@ class EndToEndTest {
val output = run(
src = "frameworks/base/org/example/Example.java" to """
package org.example;
- import com.android.server.protolog.common.ProtoLog;
- import static com.android.server.wm.ProtoLogGroup.GROUP;
+ import com.android.internal.protolog.common.ProtoLog;
+ import static com.android.internal.protolog.ProtoLogGroup.GROUP;
class Example {
void method() {
@@ -46,11 +46,11 @@ class EndToEndTest {
""".trimIndent(),
logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
commandOptions = CommandOptions(arrayOf("transform-protolog-calls",
- "--protolog-class", "com.android.server.protolog.common.ProtoLog",
- "--protolog-impl-class", "com.android.server.protolog.ProtoLogImpl",
+ "--protolog-class", "com.android.internal.protolog.common.ProtoLog",
+ "--protolog-impl-class", "com.android.internal.protolog.ProtoLogImpl",
"--protolog-cache-class",
- "com.android.server.protolog.ProtoLog${"\$\$"}Cache",
- "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "com.android.server.wm.ProtoLogCache",
+ "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup",
"--loggroups-jar", "not_required.jar",
"--output-srcjar", "out.srcjar",
"frameworks/base/org/example/Example.java"))
@@ -64,8 +64,8 @@ class EndToEndTest {
val output = run(
src = "frameworks/base/org/example/Example.java" to """
package org.example;
- import com.android.server.protolog.common.ProtoLog;
- import static com.android.server.wm.ProtoLogGroup.GROUP;
+ import com.android.internal.protolog.common.ProtoLog;
+ import static com.android.internal.protolog.ProtoLogGroup.GROUP;
class Example {
void method() {
@@ -77,8 +77,8 @@ class EndToEndTest {
""".trimIndent(),
logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
commandOptions = CommandOptions(arrayOf("generate-viewer-config",
- "--protolog-class", "com.android.server.protolog.common.ProtoLog",
- "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "--protolog-class", "com.android.internal.protolog.common.ProtoLog",
+ "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup",
"--loggroups-jar", "not_required.jar",
"--viewer-conf", "out.json",
"frameworks/base/org/example/Example.java"))
diff --git a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
index 04a3bfa499d8..67a31da87081 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
@@ -17,8 +17,8 @@
package com.android.protolog.tool
import com.android.json.stream.JsonReader
-import com.android.server.protolog.ProtoLogMessage
-import com.android.server.protolog.ProtoLogFileProto
+import com.android.internal.protolog.ProtoLogMessage
+import com.android.internal.protolog.ProtoLogFileProto
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test