summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp8
-rw-r--r--StubLibraries.bp2
-rw-r--r--apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java5
-rw-r--r--apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java12
-rw-r--r--apct-tests/perftests/multiuser/AndroidTest.xml2
-rw-r--r--apct-tests/perftests/packagemanager/Android.bp1
-rw-r--r--apct-tests/perftests/packagemanager/AndroidManifest.xml6
-rw-r--r--apct-tests/perftests/packagemanager/AndroidTest.xml4
-rw-r--r--apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java313
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java15
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java345
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java3
-rw-r--r--apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java446
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java36
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Agent.java80
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java5
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java166
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Ledger.java5
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java15
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java16
-rw-r--r--api/Android.bp8
-rw-r--r--boot/Android.bp4
-rw-r--r--cmds/bootanimation/Android.bp2
-rw-r--r--cmds/bootanimation/BootAnimation.cpp271
-rw-r--r--cmds/bootanimation/BootAnimation.h10
-rw-r--r--core/api/current.txt17
-rwxr-xr-xcore/api/system-current.txt168
-rw-r--r--core/java/Android.bp17
-rw-r--r--core/java/android/app/ActivityManagerInternal.java20
-rw-r--r--core/java/android/app/ActivityOptions.java24
-rw-r--r--core/java/android/app/ActivityThread.java13
-rw-r--r--core/java/android/app/AppOpsManager.java60
-rw-r--r--core/java/android/app/ApplicationPackageManager.java8
-rw-r--r--core/java/android/app/ContextImpl.java2
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/app/Instrumentation.java44
-rw-r--r--core/java/android/app/Service.java56
-rw-r--r--core/java/android/app/SystemServiceRegistry.java11
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java9
-rw-r--r--core/java/android/app/backup/FullBackup.java22
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java3
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java9
-rw-r--r--core/java/android/bluetooth/BluetoothUuid.java10
-rw-r--r--core/java/android/content/ContentProvider.java3
-rw-r--r--core/java/android/content/Context.java7
-rw-r--r--core/java/android/content/Intent.java92
-rw-r--r--core/java/android/content/pm/PackageInstaller.java4
-rw-r--r--core/java/android/content/pm/PackageManager.java63
-rw-r--r--core/java/android/content/pm/PackageParser.java66
-rw-r--r--core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java2
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackage.java2
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java6
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedActivity.java6
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedComponent.java4
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedInstrumentation.java2
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedIntentInfo.java2
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedPermission.java2
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedProcess.java1
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedProvider.java1
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedService.java2
-rw-r--r--core/java/android/content/rollback/PackageRollbackInfo.java4
-rw-r--r--core/java/android/debug/FingerprintAndPairDevice.aidl (renamed from core/java/android/uwb/UwbAddress.aidl)15
-rw-r--r--core/java/android/debug/IAdbCallback.aidl (renamed from core/java/android/uwb/MeasurementStatus.aidl)30
-rw-r--r--core/java/android/debug/IAdbManager.aidl18
-rw-r--r--core/java/android/debug/PairDevice.aidl (renamed from core/java/android/uwb/IUwbAdapterStateCallbacks.aidl)30
-rw-r--r--core/java/android/debug/PairDevice.java112
-rw-r--r--core/java/android/hardware/ISensorPrivacyManager.aidl2
-rw-r--r--core/java/android/hardware/SensorPrivacyManager.java22
-rw-r--r--core/java/android/hardware/camera2/MultiResolutionImageReader.java2
-rw-r--r--core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java35
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java8
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java34
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionUtils.java2
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java21
-rw-r--r--core/java/android/hardware/camera2/params/InputConfiguration.java10
-rw-r--r--core/java/android/hardware/camera2/utils/SurfaceUtils.java17
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java23
-rw-r--r--core/java/android/hardware/display/VirtualDisplayConfig.java56
-rw-r--r--core/java/android/inputmethodservice/RemoteInputConnection.java10
-rw-r--r--core/java/android/os/DropBoxManager.java4
-rw-r--r--core/java/android/os/FileUtils.java2
-rw-r--r--core/java/android/os/PowerManager.java4
-rw-r--r--core/java/android/os/ServiceManager.java7
-rw-r--r--core/java/android/permission/PermissionUsageHelper.java84
-rw-r--r--core/java/android/provider/ContactsContract.java16
-rw-r--r--core/java/android/provider/DeviceConfig.java8
-rw-r--r--core/java/android/provider/Settings.java55
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java3
-rw-r--r--core/java/android/service/voice/SoftwareHotwordDetector.java3
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java6
-rw-r--r--core/java/android/uwb/AdapterStateListener.java199
-rw-r--r--core/java/android/uwb/AngleMeasurement.java157
-rw-r--r--core/java/android/uwb/AngleOfArrivalMeasurement.java169
-rw-r--r--core/java/android/uwb/DistanceMeasurement.java214
-rw-r--r--core/java/android/uwb/IUwbAdapter.aidl191
-rw-r--r--core/java/android/uwb/IUwbRangingCallbacks.aidl136
-rw-r--r--core/java/android/uwb/OWNERS6
-rw-r--r--core/java/android/uwb/RangingChangeReason.aidl63
-rw-r--r--core/java/android/uwb/RangingManager.java256
-rw-r--r--core/java/android/uwb/RangingMeasurement.java308
-rw-r--r--core/java/android/uwb/RangingReport.java160
-rw-r--r--core/java/android/uwb/RangingSession.java496
-rw-r--r--core/java/android/uwb/SessionHandle.java86
-rw-r--r--core/java/android/uwb/StateChangeReason.aidl50
-rw-r--r--core/java/android/uwb/TEST_MAPPING10
-rw-r--r--core/java/android/uwb/UwbAddress.java131
-rw-r--r--core/java/android/uwb/UwbManager.java308
-rw-r--r--core/java/android/view/Display.java6
-rw-r--r--core/java/android/view/DisplayInfo.java15
-rw-r--r--core/java/android/view/InputEventReceiver.java10
-rw-r--r--core/java/android/view/Surface.java15
-rw-r--r--core/java/android/view/SurfaceView.java151
-rw-r--r--core/java/android/view/View.java6
-rw-r--r--core/java/android/view/ViewConfiguration.java2
-rw-r--r--core/java/android/view/ViewRootImpl.java5
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java25
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java21
-rw-r--r--core/java/android/view/translation/Translator.java29
-rw-r--r--core/java/android/window/TransitionInfo.java49
-rw-r--r--core/java/com/android/internal/app/IAppOpsStartedCallback.aidl3
-rw-r--r--core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java (renamed from core/java/com/android/internal/view/IInputConnectionWrapper.java)222
-rw-r--r--core/java/com/android/internal/widget/NotificationActionListLayout.java53
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java52
-rw-r--r--core/jni/android_media_AudioSystem.cpp8
-rw-r--r--core/jni/android_os_ServiceManager.cpp16
-rw-r--r--core/jni/android_view_InputEventReceiver.cpp13
-rw-r--r--core/proto/android/server/accessibilitytrace.proto1
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/drawable/btn_notification_emphasized.xml4
-rw-r--r--core/res/res/layout/splash_screen_view.xml1
-rw-r--r--core/res/res/values-de/strings.xml2
-rw-r--r--core/res/res/values-fa/strings.xml2
-rw-r--r--core/res/res/values-ka/strings.xml2
-rw-r--r--core/res/res/values-te/strings.xml114
-rw-r--r--core/res/res/values-ur/strings.xml2
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/res/res/xml/sms_short_codes.xml9
-rw-r--r--core/tests/coretests/src/android/app/backup/FullBackupTest.java33
-rw-r--r--core/tests/coretests/src/android/view/ViewInputConnectionTest.java301
-rw-r--r--core/tests/uwbtests/AndroidManifest.xml31
-rw-r--r--core/tests/uwbtests/OWNERS1
-rw-r--r--core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java288
-rw-r--r--core/tests/uwbtests/src/android/uwb/RangingManagerTest.java267
-rw-r--r--core/tests/uwbtests/src/android/uwb/UwbTestUtils.java90
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/BinderIdentityChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/ClientSidePermissionCheckChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientCollectionsChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/RethrowFromSystemChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java2
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/UidChecker.java2
-rw-r--r--graphics/java/android/graphics/HardwareRendererObserver.java26
-rw-r--r--graphics/java/android/graphics/Paint.java16
-rw-r--r--graphics/java/android/graphics/RenderNode.java58
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java113
-rw-r--r--graphics/java/android/graphics/drawable/RippleAnimationSession.java12
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java7
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java24
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java70
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java105
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java12
-rw-r--r--libs/WindowManager/Shell/res/layout/bubble_manage_button.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml1
-rw-r--r--libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml19
-rw-r--r--libs/WindowManager/Shell/res/values-te/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java56
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt81
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt60
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java83
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java80
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java265
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java86
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java241
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java147
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java132
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt57
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt110
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt106
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt131
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt)39
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt92
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt)83
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt)44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt)45
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt166
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt113
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java193
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java174
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp6
-rw-r--r--libs/hwui/DisplayListOps.in1
-rw-r--r--libs/hwui/RecordingCanvas.cpp16
-rw-r--r--libs/hwui/RecordingCanvas.h2
-rw-r--r--libs/hwui/SkiaCanvas.cpp16
-rw-r--r--libs/hwui/SkiaCanvas.h3
-rw-r--r--libs/hwui/canvas/CanvasFrontend.cpp7
-rw-r--r--libs/hwui/hwui/Canvas.h6
-rw-r--r--libs/hwui/jni/android_graphics_Canvas.cpp23
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp31
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRendererObserver.h3
-rw-r--r--libs/hwui/jni/android_graphics_RenderNode.cpp94
-rw-r--r--libs/hwui/pipeline/skia/DumpOpsCanvas.h2
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp6
-rw-r--r--libs/hwui/tests/unit/SkiaPipelineTests.cpp2
-rw-r--r--libs/input/SpriteController.cpp3
-rw-r--r--location/java/android/location/Location.java18
-rw-r--r--location/java/android/location/LocationListener.java23
-rw-r--r--media/java/android/media/AudioManagerInternal.java11
-rw-r--r--media/java/android/media/AudioSystem.java7
-rw-r--r--media/java/android/media/projection/MediaProjection.java28
-rw-r--r--media/java/android/media/session/ISessionManager.aidl7
-rw-r--r--media/java/android/media/session/MediaSessionManager.java65
-rw-r--r--media/java/android/media/tv/tuner/Lnb.java44
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java64
-rw-r--r--media/java/android/media/tv/tuner/TunerUtils.java68
-rw-r--r--media/java/android/media/tv/tuner/TunerVersionChecker.java9
-rw-r--r--media/java/android/media/tv/tuner/dvr/DvrPlayback.java11
-rw-r--r--media/java/android/media/tv/tuner/dvr/DvrSettings.java10
-rw-r--r--media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java8
-rw-r--r--media/java/android/media/tv/tuner/filter/AvSettings.java70
-rw-r--r--media/java/android/media/tv/tuner/filter/Filter.java33
-rw-r--r--media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java4
-rw-r--r--media/java/android/media/tv/tuner/filter/RecordSettings.java100
-rw-r--r--media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java69
-rw-r--r--media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java98
-rw-r--r--media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java10
-rw-r--r--media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java92
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java97
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java88
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java165
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendSettings.java105
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendStatus.java88
-rw-r--r--media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java48
-rw-r--r--media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java37
-rw-r--r--media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java36
-rw-r--r--media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java8
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/Android.bp3
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java1
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl2
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl41
-rw-r--r--media/jni/Android.bp6
-rw-r--r--media/jni/android_media_tv_Tuner.cpp2743
-rw-r--r--media/jni/android_media_tv_Tuner.h157
-rw-r--r--media/jni/tuner/ClientHelper.h15
-rw-r--r--media/jni/tuner/DemuxClient.cpp269
-rw-r--r--media/jni/tuner/DemuxClient.h55
-rw-r--r--media/jni/tuner/DescramblerClient.cpp77
-rw-r--r--media/jni/tuner/DescramblerClient.h24
-rw-r--r--media/jni/tuner/DvrClient.cpp247
-rw-r--r--media/jni/tuner/DvrClient.h63
-rw-r--r--media/jni/tuner/DvrClientCallback.h12
-rw-r--r--media/jni/tuner/FilterClient.cpp890
-rw-r--r--media/jni/tuner/FilterClient.h147
-rw-r--r--media/jni/tuner/FilterClientCallback.h17
-rw-r--r--media/jni/tuner/FrontendClient.cpp1159
-rw-r--r--media/jni/tuner/FrontendClient.h144
-rw-r--r--media/jni/tuner/FrontendClientCallback.h14
-rw-r--r--media/jni/tuner/LnbClient.cpp91
-rw-r--r--media/jni/tuner/LnbClient.h48
-rw-r--r--media/jni/tuner/LnbClientCallback.h9
-rw-r--r--media/jni/tuner/TimeFilterClient.cpp87
-rw-r--r--media/jni/tuner/TimeFilterClient.h30
-rw-r--r--media/jni/tuner/TunerClient.cpp578
-rw-r--r--media/jni/tuner/TunerClient.h93
-rw-r--r--mms/OWNERS8
-rw-r--r--packages/CarrierDefaultApp/OWNERS7
-rw-r--r--packages/DynamicSystemInstallationService/AndroidManifest.xml4
-rw-r--r--packages/PackageInstaller/res/values-te/strings.xml4
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-af/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-am/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ar/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-as/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-be/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-bn/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ca/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-cs/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-da/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-de/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-el/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-es-rUS/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-et/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-eu/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-fi/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr-rCA/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-gl/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-gu/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-hi/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-in/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-is/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-kn/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-lt/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-lv/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-mk/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ml/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-mr/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ms/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-my/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-nb/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ne/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-pa/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-pl/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ro/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ru/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sk/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sq/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ta/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-te/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-th/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-tr/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-ur/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rCN/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml21
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml21
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml16
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java95
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java34
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java40
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java4
-rw-r--r--packages/Shell/res/values-te/strings.xml24
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/flags/Flag.kt52
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/flags/Flags.java (renamed from core/java/android/uwb/SessionHandle.aidl)10
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/FlagReaderPlugin.java71
-rw-r--r--packages/SystemUI/res-keyguard/layout/footer_actions.xml105
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml10
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml71
-rw-r--r--packages/SystemUI/res/anim/fp_to_unlock.xml8
-rw-r--r--packages/SystemUI/res/anim/lock_to_unlock.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_unlock.xml4
-rw-r--r--packages/SystemUI/res/drawable/settingslib_thumb_off.xml2
-rw-r--r--packages/SystemUI/res/drawable/settingslib_thumb_on.xml2
-rw-r--r--packages/SystemUI/res/drawable/settingslib_track_off_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/settingslib_track_on_background.xml2
-rw-r--r--packages/SystemUI/res/layout/internet_connectivity_dialog.xml117
-rw-r--r--packages/SystemUI/res/layout/internet_list_item.xml12
-rw-r--r--packages/SystemUI/res/layout/qs_footer_impl.xml88
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml13
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml14
-rw-r--r--packages/SystemUI/res/layout/udfps_keyguard_view.xml4
-rw-r--r--packages/SystemUI/res/raw/udfps_aod_fp.json1748
-rw-r--r--packages/SystemUI/res/raw/udfps_lockscreen_fp.json2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml3
-rw-r--r--packages/SystemUI/res/values-am/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml4
-rw-r--r--packages/SystemUI/res/values-as/strings.xml4
-rw-r--r--packages/SystemUI/res/values-az/strings.xml4
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-be/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml5
-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.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml3
-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.xml7
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml4
-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.xml4
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml3
-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.xml4
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml5
-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.xml4
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml4
-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.xml6
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/strings.xml3
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml7
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-or/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml4
-rw-r--r--packages/SystemUI/res/values-si/strings.xml3
-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.xml7
-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-ldrtl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-te/strings.xml22
-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.xml4
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml3
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml4
-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.xml4
-rw-r--r--packages/SystemUI/res/values/config.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml20
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt146
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl5
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java2
-rw-r--r--packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java56
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt28
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt77
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt67
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java234
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java132
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java146
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java594
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt217
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt67
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt161
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooter.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java126
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java187
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt (renamed from core/java/android/uwb/RangingReport.aidl)15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java119
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt93
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java171
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java (renamed from services/uwb/java/com/android/server/uwb/UwbService.java)31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java21
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt101
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java127
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsTest.java111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java119
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java573
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java91
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java251
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt173
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java114
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java97
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt60
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java65
-rw-r--r--packages/VpnDialogs/res/values-eu/strings.xml2
-rw-r--r--services/Android.bp2
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java2
-rw-r--r--services/core/Android.bp3
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/IntentResolver.java41
-rw-r--r--services/core/java/com/android/server/SensorPrivacyService.java23
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java4
-rw-r--r--services/core/java/com/android/server/VpnManagerService.java30
-rw-r--r--services/core/java/com/android/server/adb/AdbDebuggingManager.java12
-rw-r--r--services/core/java/com/android/server/adb/AdbService.java55
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java481
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java92
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java186
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java19
-rw-r--r--services/core/java/com/android/server/am/AppNotRespondingDialog.java4
-rw-r--r--services/core/java/com/android/server/am/AppProfiler.java44
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java6
-rw-r--r--services/core/java/com/android/server/am/ConnectionRecord.java19
-rw-r--r--services/core/java/com/android/server/am/ContentProviderConnection.java19
-rw-r--r--services/core/java/com/android/server/am/ContentProviderRecord.java15
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java35
-rw-r--r--services/core/java/com/android/server/am/ProcessErrorStateRecord.java16
-rw-r--r--services/core/java/com/android/server/am/ProcessStateRecord.java56
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java28
-rw-r--r--services/core/java/com/android/server/am/SettingsToPropertiesMapper.java1
-rw-r--r--services/core/java/com/android/server/am/UidRecord.java12
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java31
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java18
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java44
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java85
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java26
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java6
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java30
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java59
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerShellCommand.java16
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java91
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java2
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java25
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java25
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessage.java11
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java10
-rw-r--r--services/core/java/com/android/server/hdmi/RequestSadAction.java176
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java74
-rw-r--r--services/core/java/com/android/server/input/InputShellCommand.java7
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java19
-rw-r--r--services/core/java/com/android/server/location/eventlog/LocationEventLog.java4
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java87
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java26
-rw-r--r--services/core/java/com/android/server/pm/InstallParams.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java303
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java48
-rw-r--r--services/core/java/com/android/server/pm/PackageSignatures.java11
-rw-r--r--services/core/java/com/android/server/pm/ScanResult.java7
-rw-r--r--services/core/java/com/android/server/pm/Settings.java4
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java5
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java6
-rw-r--r--services/core/java/com/android/server/rollback/AppDataRollbackHelper.java8
-rw-r--r--services/core/java/com/android/server/rollback/Rollback.java2
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java2
-rw-r--r--services/core/java/com/android/server/rollback/RollbackStore.java2
-rw-r--r--services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java2
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationThread.java30
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java19
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java232
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java10
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java14
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java3
-rw-r--r--services/core/java/com/android/server/wm/BlurController.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java194
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java12
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java46
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java8
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java17
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java23
-rw-r--r--services/core/java/com/android/server/wm/Task.java147
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java160
-rw-r--r--services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java31
-rw-r--r--services/core/java/com/android/server/wm/Transition.java29
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowOrientationListener.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java12
-rw-r--r--services/core/jni/Android.bp6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java46
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java9
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java16
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/OwnerShellData.java98
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/Owners.java28
-rw-r--r--services/java/com/android/server/SystemServer.java4
-rw-r--r--services/net/Android.bp1
-rw-r--r--services/tests/PackageManagerServiceTests/unit/Android.bp1
-rw-r--r--services/tests/PackageManagerServiceTests/unit/TEST_MAPPING7
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt572
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt413
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt59
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt47
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt73
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt36
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt95
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt34
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt152
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt53
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt35
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt55
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt43
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt78
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt (renamed from core/java/android/uwb/AdapterState.aidl)34
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt35
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java56
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java41
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java118
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt53
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java284
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java38
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/devicepolicy/OwnerShellDataTest.java129
-rw-r--r--services/tests/servicestests/Android.bp1
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java171
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java104
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java66
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java596
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/OWNERS4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/tare/LedgerTest.java53
-rw-r--r--services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/uwb/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java365
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java2
-rw-r--r--services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java3
-rw-r--r--services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java67
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java41
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java113
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java33
-rw-r--r--services/usb/java/com/android/server/usb/UsbUserPermissionManager.java62
-rw-r--r--services/uwb/Android.bp26
-rw-r--r--services/uwb/OWNERS1
-rw-r--r--services/uwb/java/com/android/server/uwb/UwbInjector.java83
-rw-r--r--services/uwb/java/com/android/server/uwb/UwbServiceImpl.java325
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java16
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java29
-rw-r--r--telecomm/java/android/telecom/CallRedirectionService.java25
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java6
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl6
-rw-r--r--telephony/OWNERS7
-rw-r--r--telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java4
-rw-r--r--telephony/java/android/telephony/ims/stub/SipTransportImplBase.java46
-rw-r--r--tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java17
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt10
-rw-r--r--tests/Input/src/com/android/test/input/AnrTest.kt54
-rw-r--r--tests/InputMethodStressTest/Android.bp (renamed from core/tests/uwbtests/Android.bp)27
-rw-r--r--tests/InputMethodStressTest/AndroidManifest.xml28
-rw-r--r--tests/InputMethodStressTest/AndroidTest.xml (renamed from core/tests/uwbtests/AndroidTest.xml)21
-rw-r--r--tests/InputMethodStressTest/OWNERS3
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java79
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java64
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java386
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java4
-rw-r--r--tests/utils/testutils/Android.bp2
-rw-r--r--tools/aapt2/SdkConstants.cpp2
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt3
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt82
-rw-r--r--tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt217
831 files changed, 22954 insertions, 18492 deletions
diff --git a/Android.bp b/Android.bp
index 62dce7fab6a1..c156774a1c51 100644
--- a/Android.bp
+++ b/Android.bp
@@ -101,6 +101,7 @@ filegroup {
// AIDL sources from external directories
":android.hardware.security.keymint-V1-java-source",
":android.hardware.security.secureclock-V1-java-source",
+ ":android.hardware.tv.tuner-V1-java-source",
":android.security.apc-java-source",
":android.security.authorization-java-source",
":android.security.legacykeystore-java-source",
@@ -155,6 +156,7 @@ java_library {
"framework-sdkextensions.stubs.module_lib",
"framework-statsd.stubs.module_lib",
"framework-tethering.stubs.module_lib",
+ "framework-uwb.stubs.module_lib",
"framework-wifi.stubs.module_lib",
],
sdk_version: "module_current",
@@ -177,6 +179,7 @@ java_library {
"framework-sdkextensions.impl",
"framework-statsd.impl",
"framework-tethering.impl",
+ "framework-uwb.impl",
"framework-wifi.impl",
"updatable-media",
],
@@ -250,8 +253,6 @@ java_library {
"android.hardware.thermal-V1.1-java",
"android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.1-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb-V1.2-java-constants",
@@ -331,6 +332,7 @@ java_defaults {
],
sdk_version: "core_platform",
static_libs: [
+ "android.hardware.common.fmq-V1-java",
// TODO(b/184162091)
"android.hardware.soundtrigger3-V1-java",
"bouncycastle-repackaged-unbundled",
@@ -559,8 +561,6 @@ stubs_defaults {
"android.hardware.thermal-V1.0-java-constants",
"android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.0-java-constants",
- "android.hardware.tv.tuner-V1.1-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb.gadget-V1.0-java",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 44c55c26153d..1904c1f34da0 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -250,6 +250,7 @@ modules_public_stubs = [
"framework-sdkextensions.stubs",
"framework-statsd.stubs",
"framework-tethering.stubs",
+ "framework-uwb.stubs",
"framework-wifi.stubs",
"i18n.module.public.api.stubs",
]
@@ -269,6 +270,7 @@ modules_system_stubs = [
"framework-sdkextensions.stubs.system",
"framework-statsd.stubs.system",
"framework-tethering.stubs.system",
+ "framework-uwb.stubs.system",
"framework-wifi.stubs.system",
"i18n.module.public.api.stubs", // Only has public stubs
]
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index 5a04ba303b66..faf61a756170 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -85,10 +85,7 @@ public class BlobStorePerfTests {
@After
public void tearDown() {
- // TODO: Add a blob_store shell command to trigger idle maintenance to avoid hardcoding
- // job id like this.
- // From BlobStoreConfig.IDLE_JOB_ID = 191934935.
- runShellCommand("cmd jobscheduler run -f android 191934935");
+ runShellCommand("cmd blob_store idle-maintenance");
}
@Test
diff --git a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
index d07ed375b2ab..ecc5112ab6dd 100644
--- a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
+++ b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/MyContentCaptureService.java
@@ -84,18 +84,18 @@ public class MyContentCaptureService extends ContentCaptureService {
@Override
public void onDisconnected() {
- Log.i(TAG, "onDisconnected: sServiceWatcher=" + sServiceWatcher);
-
- if (sServiceWatcher == null) {
+ final ServiceWatcher sw = sServiceWatcher;
+ Log.i(TAG, "onDisconnected: sServiceWatcher=" + sw);
+ if (sw == null) {
Log.e(TAG, "onDisconnected() without a watcher");
return;
}
- if (sServiceWatcher.mService == null) {
- Log.e(TAG, "onDisconnected(): no service on " + sServiceWatcher);
+ if (sw.mService == null) {
+ Log.e(TAG, "onDisconnected(): no service on " + sw);
return;
}
- sServiceWatcher.mDestroyed.countDown();
+ sw.mDestroyed.countDown();
clearServiceWatcher();
}
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index 8e342f3389fc..bec3cc9272c3 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -29,7 +29,7 @@
<option name="push-file" key="trace_config_multi_user.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
<!--Install the content provider automatically when we push some file in sdcard folder.-->
<!--Needed to avoid the installation during the test suite.-->
- <option name="push-file" key="trace_config_detailed.textproto" value="/sdcard/sample.textproto" />
+ <option name="push-file" key="trace_config_multi_user.textproto" value="/sdcard/sample.textproto" />
</target_preparer>
<!-- Needed for pulling the collected trace config on to the host -->
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 0e76488d9642..fc70219d2aeb 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -20,6 +20,7 @@ android_test {
"androidx.annotation_annotation",
"apct-perftests-utils",
"collector-device-lib-platform",
+ "cts-install-lib-java",
],
libs: ["android.test.base"],
diff --git a/apct-tests/perftests/packagemanager/AndroidManifest.xml b/apct-tests/perftests/packagemanager/AndroidManifest.xml
index 4bcd557695a3..3b9431f1b97a 100644
--- a/apct-tests/perftests/packagemanager/AndroidManifest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidManifest.xml
@@ -17,6 +17,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.packagemanager">
+ <!-- prevent test application from being obscured because of package visibility -->
+ <queries>
+ <package android:name="com.android.cts.install.lib.testapp.A" />
+ <package android:name="com.android.cts.install.lib.testapp.B" />
+ <package android:name="com.android.cts.install.lib.testapp.C" />
+ </queries>
<permission android:name="com.android.perftests.packagemanager.TestPermission" />
<uses-permission android:name="com.android.perftests.packagemanager.TestPermission" />
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index 4903510fa502..c9d45a6bda74 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -130,6 +130,10 @@
<option name="instrumentation-arg" key="perfetto_config_file"
value="trace_config.textproto"/>
+ <!--
+ PackageInstallerBenchmark will break for 5 minutes time out so it changes to 10 minutes
+ -->
+ <option name="test-timeout" value="600000" />
</test>
diff --git a/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
new file mode 100644
index 000000000000..3b4f72b2e50a
--- /dev/null
+++ b/apct-tests/perftests/packagemanager/src/android/content/pm/PackageInstallerBenchmark.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.HandlerThread;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.LocalIntentSender;
+import com.android.cts.install.lib.TestApp;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PackageInstallerBenchmark {
+ private static final String TAG = "PackageInstallerBenchmark";
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ /**
+ * This rule adopts the Shell process permissions, needed because INSTALL_PACKAGES
+ * and DELETE_PACKAGES are privileged permission.
+ */
+ @Rule
+ public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES);
+
+ private static class SessionCallback extends PackageInstaller.SessionCallback {
+ private final List<Integer> mExpectedSessions;
+ private final CountDownLatch mCountDownLatch;
+ private final boolean mExpectedSuccess;
+
+ SessionCallback(boolean expectedSuccess, List<Integer> expectedSessions,
+ @NonNull CountDownLatch countDownLatch) {
+ mExpectedSuccess = expectedSuccess;
+ mCountDownLatch = countDownLatch;
+ mExpectedSessions = expectedSessions;
+ }
+
+ @Override
+ public void onCreated(int sessionId) { }
+
+ @Override
+ public void onBadgingChanged(int sessionId) { }
+
+ @Override
+ public void onActiveChanged(int sessionId, boolean active) { }
+
+ @Override
+ public void onProgressChanged(int sessionId, float progress) { }
+
+ @Override
+ public void onFinished(int sessionId, boolean success) {
+ if (success == mExpectedSuccess && mExpectedSessions.contains(sessionId)) {
+ mCountDownLatch.countDown();
+ }
+ }
+ }
+
+ private CountDownLatch mCountDownLatch;
+ private SessionCallback mSessionCallback;
+ private PackageInstaller mPackageInstaller;
+ private Install mInstall;
+ private HandlerThread mHandlerThread;
+ private List<PackageInstaller.Session> mExpectedSessions;
+ private List<Integer> mExpectedSessionIds;
+ final LocalIntentSender mLocalIntentSender = new LocalIntentSender();
+ private IntentSender mIntentSender;
+
+ @Before
+ public void setUp() throws IOException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mPackageInstaller = context.getPackageManager().getPackageInstaller();
+ mHandlerThread = new HandlerThread("PackageInstallerBenchmark");
+ mHandlerThread.start();
+
+ mIntentSender = mLocalIntentSender.getIntentSender();
+ }
+
+ @After
+ public void tearDown() throws InterruptedException {
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ context.unregisterReceiver(mLocalIntentSender);
+
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+ mHandlerThread.quitSafely();
+ }
+
+ private List<PackageInstaller.Session> createSinglePackageSessions(
+ BenchmarkState state, boolean expectedResult, TestApp...testApps)
+ throws IOException, InterruptedException {
+ state.pauseTiming();
+ uninstall(false /* stop at fail */, testApps);
+
+ mExpectedSessions = new ArrayList<>();
+ mExpectedSessionIds = new ArrayList<>();
+ for (TestApp testApp : testApps) {
+ mInstall = Install.single(testApp);
+ final int expectedSessionId = mInstall.createSession();
+ PackageInstaller.Session session =
+ InstallUtils.openPackageInstallerSession(expectedSessionId);
+ Log.d(TAG, "createNewSession: session expectedSessionId = " + expectedSessionId);
+ mExpectedSessions.add(session);
+ mExpectedSessionIds.add(expectedSessionId);
+ }
+
+ mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+ mSessionCallback = new SessionCallback(expectedResult, mExpectedSessionIds,
+ mCountDownLatch);
+ mPackageInstaller.registerSessionCallback(mSessionCallback,
+ mHandlerThread.getThreadHandler());
+ state.resumeTiming();
+ return mExpectedSessions;
+ }
+
+ private List<PackageInstaller.Session> createMultiplePackageSessions(BenchmarkState state,
+ boolean expectedSuccess, List<TestApp[]> testAppsList)
+ throws IOException, InterruptedException {
+ state.pauseTiming();
+ mExpectedSessions = new ArrayList<>();
+ mExpectedSessionIds = new ArrayList<>();
+ for (TestApp[] testApps : testAppsList) {
+ uninstall(false /* stop at fail */, testApps);
+
+ mInstall = Install.multi(testApps);
+ final int expectedSessionId = mInstall.createSession();
+ PackageInstaller.Session session =
+ InstallUtils.openPackageInstallerSession(expectedSessionId);
+ mExpectedSessions.add(session);
+ mExpectedSessionIds.add(expectedSessionId);
+ }
+
+ mCountDownLatch = new CountDownLatch(mExpectedSessions.size());
+ mSessionCallback = new SessionCallback(expectedSuccess, mExpectedSessionIds,
+ mCountDownLatch);
+ mPackageInstaller.registerSessionCallback(mSessionCallback,
+ mHandlerThread.getThreadHandler());
+ state.resumeTiming();
+ return mExpectedSessions;
+ }
+
+ private void uninstall(boolean stopAtFail, TestApp...testApps) throws InterruptedException {
+ String[] packageNames = new String[testApps.length];
+ for (int i = 0; i < testApps.length; i++) {
+ packageNames[i] = testApps[i].getPackageName();
+ }
+ uninstall(stopAtFail, packageNames);
+ }
+
+ private void uninstall(boolean stopAtFail, String...packageNames) throws InterruptedException {
+ LocalIntentSender localIntentSender = new LocalIntentSender();
+ IntentSender intentSender = localIntentSender.getIntentSender();
+ for (String packageName : packageNames) {
+ try {
+ mPackageInstaller.uninstall(packageName, intentSender);
+ } catch (IllegalArgumentException e) {
+ continue;
+ }
+ Intent intent = localIntentSender.getResult();
+ if (stopAtFail) {
+ InstallUtils.assertStatusSuccess(intent);
+ }
+ }
+
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ context.unregisterReceiver(localIntentSender);
+ }
+
+ private void uninstallSession(BenchmarkState state, String...packageNames)
+ throws InterruptedException {
+ state.pauseTiming();
+ uninstall(true /* stop at fail */, packageNames);
+ mPackageInstaller.unregisterSessionCallback(mSessionCallback);
+ state.resumeTiming();
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aSingleApkSession_untilFinishBenchmark() throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions =
+ createSinglePackageSessions(state, true, TestApp.A1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_threeSingleApkSessions_untilFinishBenchmark() throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+ state, true, TestApp.A1, TestApp.B1, TestApp.C1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aMultiplePackagesSession_untilFinishBenchmark()
+ throws IOException, InterruptedException {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final List<TestApp[]> multiPackageApps = new ArrayList<>();
+ multiPackageApps.add(new TestApp[] {TestApp.A1, TestApp.B1, TestApp.C1});
+
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+ state, true, multiPackageApps);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_threeMultiplePackageSessions_untilFinishBenchmark()
+ throws Exception {
+ uninstall(false /* stop at fail */, TestApp.A, TestApp.B, TestApp.C);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final List<TestApp[]> multiPackageApps = new ArrayList<>();
+ multiPackageApps.add(new TestApp[] {TestApp.A1});
+ multiPackageApps.add(new TestApp[] {TestApp.B1});
+ multiPackageApps.add(new TestApp[] {TestApp.C1});
+
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createMultiplePackageSessions(
+ state, true, multiPackageApps);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A, TestApp.B, TestApp.C);
+ }
+ }
+
+ @Test(timeout = 600_000L)
+ public void commit_aMultipleApksSession_untilFinishBenchmark()
+ throws IOException, InterruptedException {
+ uninstall(false /* stop at fail */, TestApp.A);
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ List<PackageInstaller.Session> sessions = createSinglePackageSessions(
+ state, true, TestApp.ASplit1);
+
+ for (PackageInstaller.Session session : sessions) {
+ session.commit(mIntentSender);
+ }
+ mCountDownLatch.await(1, TimeUnit.MINUTES);
+
+ uninstallSession(state, TestApp.A);
+ }
+ }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
index fe2b1f6443b3..ebd8d86b1eed 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
@@ -306,27 +306,28 @@ public final class ManualBenchmarkState {
private void fillStatus(Bundle status, String key, Stats stats) {
if (shouldReport(StatsReport.FLAG_ITERATION)) {
- status.putLong(key + "_iteration", stats.getSize());
+ status.putLong(key + "_iteration (ns)", stats.getSize());
}
if (shouldReport(StatsReport.FLAG_MEDIAN)) {
- status.putLong(key + "_median", stats.getMedian());
+ status.putLong(key + "_median (ns)", stats.getMedian());
}
if (shouldReport(StatsReport.FLAG_MEAN)) {
- status.putLong(key + "_mean", Math.round(stats.getMean()));
+ status.putLong(key + "_mean (ns)", Math.round(stats.getMean()));
}
if (shouldReport(StatsReport.FLAG_MIN)) {
- status.putLong(key + "_min", stats.getMin());
+ status.putLong(key + "_min (ns)", stats.getMin());
}
if (shouldReport(StatsReport.FLAG_MAX)) {
- status.putLong(key + "_max", stats.getMax());
+ status.putLong(key + "_max (ns)", stats.getMax());
}
if (mStatsReportPercentiles != null) {
for (int percentile : mStatsReportPercentiles) {
- status.putLong(key + "_percentile" + percentile, stats.getPercentile(percentile));
+ status.putLong(key + "_percentile" + percentile + " (ns)",
+ stats.getPercentile(percentile));
}
}
if (shouldReport(StatsReport.FLAG_STDDEV)) {
- status.putLong(key + "_stddev", Math.round(stats.getStandardDeviation()));
+ status.putLong(key + "_stddev (ns)", Math.round(stats.getStandardDeviation()));
}
if (shouldReport(StatsReport.FLAG_COEFFICIENT_VAR)) {
status.putLong(key + "_cv",
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index db23a6dc3047..c33d5ecc5d16 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -332,17 +332,20 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
for (int i = 0; i < schemaBundles.size(); i++) {
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
@@ -359,7 +362,7 @@ public class AppSearchManagerService extends SystemService {
}
schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
}
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
packageName,
databaseName,
@@ -418,15 +421,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
GetSchemaResponse response =
instance.getAppSearchImpl().getSchema(packageName, databaseName);
invokeCallbackOnResult(
@@ -450,15 +456,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
List<String> namespaces =
instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
invokeCallbackOnResult(
@@ -485,20 +494,23 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
for (int i = 0; i < documentBundles.size(); i++) {
GenericDocument document = new GenericDocument(documentBundles.get(i));
try {
@@ -571,20 +583,23 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
new AppSearchBatchResult.Builder<>();
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
@@ -652,18 +667,21 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
packageName,
databaseName,
@@ -718,18 +736,21 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
boolean callerHasSystemAccess =
instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
@@ -783,17 +804,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
- // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
- // opened it
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
SearchResultPage searchResultPage =
instance.getAppSearchImpl().getNextPage(packageName, nextPageToken);
invokeCallbackOnResult(
@@ -812,15 +834,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(userHandle);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
} catch (Throwable t) {
Log.e(TAG, "Unable to invalidate the query page token", t);
@@ -846,15 +871,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
// we don't need to append the file. The file is always brand new.
try (DataOutputStream outputStream = new DataOutputStream(
new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
@@ -895,15 +923,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
GenericDocument document;
ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
@@ -957,15 +988,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
if (systemUsage
&& !instance.getVisibilityStore()
@@ -1004,20 +1038,23 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
@@ -1090,18 +1127,21 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
instance.getAppSearchImpl().removeByQuery(
packageName,
databaseName,
@@ -1154,15 +1194,18 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
AppSearchUserInstance instance =
- mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ mAppSearchUserInstanceManager.getUserInstance(targetUser);
StorageInfo storageInfo = instance.getAppSearchImpl()
.getStorageInfoForDatabase(packageName, databaseName);
Bundle storageInfoBundle = storageInfo.getBundle();
@@ -1184,18 +1227,21 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
AppSearchUserInstance instance = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
- instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
+ instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
++operationSuccessCount;
} catch (Throwable t) {
@@ -1236,7 +1282,6 @@ public class AppSearchManagerService extends SystemService {
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
- UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
@@ -1244,12 +1289,18 @@ public class AppSearchManagerService extends SystemService {
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
- Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
- verifyUserUnlocked(callingUser);
- verifyCallingPackage(userContext, callingUser, callingUid, packageName);
- verifyNotInstantApp(userContext, packageName);
+ verifyCaller(callingUid, packageName);
+
+ // Obtain the user where the client wants to run the operations in. This should
+ // end up being the same as userHandle, assuming it is not a special user and
+ // the client is allowed to run operations in that user.
+ UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
+ verifyUserUnlocked(targetUser);
+
+ Context targetUserContext = mContext.createContextAsUser(targetUser,
+ /*flags=*/ 0);
instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
- userContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
+ targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -1278,29 +1329,6 @@ public class AppSearchManagerService extends SystemService {
});
}
- private void verifyCallingPackage(
- @NonNull Context userContext,
- @NonNull UserHandle actualCallingUser,
- int actualCallingUid,
- @NonNull String claimedCallingPackage) {
- Objects.requireNonNull(actualCallingUser);
- Objects.requireNonNull(claimedCallingPackage);
-
- int claimedCallingUid = PackageUtil.getPackageUid(
- userContext, claimedCallingPackage);
- if (claimedCallingUid == INVALID_UID) {
- throw new SecurityException(
- "Specified calling package [" + claimedCallingPackage + "] not found");
- }
- if (claimedCallingUid != actualCallingUid) {
- throw new SecurityException(
- "Specified calling package ["
- + claimedCallingPackage
- + "] does not match the calling uid "
- + actualCallingUid);
- }
- }
-
/** Invokes the {@link IAppSearchResultCallback} with the result. */
private void invokeCallbackOnResult(
IAppSearchResultCallback callback, AppSearchResult<?> result) {
@@ -1354,33 +1382,72 @@ public class AppSearchManagerService extends SystemService {
/**
* Helper for dealing with incoming user arguments to system service calls.
*
- * @param requestedUser The user which the caller is requesting to execute as.
+ * @param targetUserHandle The user which the caller is requesting to execute as.
* @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
*/
@NonNull
- private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
- UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
- if (callingUser.equals(requestedUser)) {
- return requestedUser;
+ private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingUid) {
+ UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
+ if (callingUserHandle.equals(targetUserHandle)) {
+ return targetUserHandle;
}
// Duplicates UserController#ensureNotSpecialUser
- if (requestedUser.getIdentifier() < 0) {
+ if (targetUserHandle.getIdentifier() < 0) {
throw new IllegalArgumentException(
- "Call does not support special user " + requestedUser);
+ "Call does not support special user " + targetUserHandle);
}
throw new SecurityException(
- "Requested user, " + requestedUser + ", is not the same as the calling user, "
- + callingUser + ".");
+ "Requested user, " + targetUserHandle + ", is not the same as the calling user, "
+ + callingUserHandle + ".");
+ }
+
+ /**
+ * Verify various aspects of the calling user.
+ *
+ * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
+ * @param claimedCallingPackage Package name the caller claims to be.
+ */
+ private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
+ // Obtain the user where the client is running in. Note that this could be different from
+ // the userHandle where the client wants to run the AppSearch operation in.
+ UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
+ Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
+ /*flags=*/ 0);
+
+ verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
+ verifyNotInstantApp(callingUserContext, claimedCallingPackage);
+ }
+
+ /**
+ * Check that the caller's supposed package name matches the uid making the call.
+ *
+ * @throws SecurityException if the package name and uid don't match.
+ */
+ private void verifyCallingPackage(
+ @NonNull Context actualCallingUserContext,
+ int actualCallingUid,
+ @NonNull String claimedCallingPackage) {
+ int claimedCallingUid = PackageUtil.getPackageUid(
+ actualCallingUserContext, claimedCallingPackage);
+ if (claimedCallingUid == INVALID_UID) {
+ throw new SecurityException(
+ "Specified calling package [" + claimedCallingPackage + "] not found");
+ }
+ if (claimedCallingUid != actualCallingUid) {
+ throw new SecurityException(
+ "Specified calling package ["
+ + claimedCallingPackage
+ + "] does not match the calling uid "
+ + actualCallingUid);
+ }
}
/**
- * Helper for ensuring instant apps can't make calls to AppSearch.
+ * Ensure instant apps can't make calls to AppSearch.
*
- * @param userContext Context of the user making the call.
- * @param packageName Package name of the caller.
* @throws SecurityException if the caller is an instant app.
*/
private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index 6e4a5a0c5784..7b287d5f9d15 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -19,6 +19,7 @@ package android.app.job;
import android.annotation.SystemApi;
import android.app.JobSchedulerImpl;
import android.app.SystemServiceRegistry;
+import android.app.tare.EconomyManager;
import android.content.Context;
import android.os.DeviceIdleManager;
import android.os.IDeviceIdleController;
@@ -56,5 +57,7 @@ public class JobSchedulerFrameworkInitializer {
SystemServiceRegistry.registerContextAwareService(
Context.POWER_EXEMPTION_SERVICE, PowerExemptionManager.class,
PowerExemptionManager::new);
+ SystemServiceRegistry.registerStaticService(
+ Context.RESOURCE_ECONOMY_SERVICE, EconomyManager.class, EconomyManager::new);
}
}
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
new file mode 100644
index 000000000000..4053bddd7883
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.tare;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * Provides access to the resource economy service.
+ *
+ * @hide
+ */
+@SystemService(Context.RESOURCE_ECONOMY_SERVICE)
+public class EconomyManager {
+ // Keys for AlarmManager TARE factors
+ /** @hide */
+ public static final String KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED =
+ "am_min_satiated_balance_exempted";
+ /** @hide */
+ public static final String KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP =
+ "am_min_satiated_balance_headless_system_app";
+ /** @hide */
+ public static final String KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP =
+ "am_min_satiated_balance_other_app";
+ /** @hide */
+ public static final String KEY_AM_MAX_SATIATED_BALANCE = "am_max_satiated_balance";
+ /** @hide */
+ public static final String KEY_AM_MAX_CIRCULATION = "am_max_circulation";
+ // TODO: Add AlarmManager modifier keys
+ /** @hide */
+ public static final String KEY_AM_REWARD_TOP_ACTIVITY_INSTANT =
+ "am_reward_top_activity_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_TOP_ACTIVITY_ONGOING =
+ "am_reward_top_activity_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_TOP_ACTIVITY_MAX = "am_reward_top_activity_max";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT =
+ "am_reward_notification_seen_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING =
+ "am_reward_notification_seen_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_MAX =
+ "am_reward_notification_seen_max";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT =
+ "am_reward_notification_seen_within_15_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING =
+ "am_reward_notification_seen_within_15_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX =
+ "am_reward_notification_seen_within_15_max";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT =
+ "am_reward_notification_interaction_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING =
+ "am_reward_notification_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX =
+ "am_reward_notification_interaction_max";
+ /** @hide */
+ public static final String KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT =
+ "am_reward_widget_interaction_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING =
+ "am_reward_widget_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_WIDGET_INTERACTION_MAX =
+ "am_reward_widget_interaction_max";
+ /** @hide */
+ public static final String KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT =
+ "am_reward_other_user_interaction_instant";
+ /** @hide */
+ public static final String KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING =
+ "am_reward_other_user_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX =
+ "am_reward_other_user_interaction_max";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP =
+ "am_action_alarm_allow_while_idle_exact_wakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP =
+ "am_action_alarm_allow_while_idle_inexact_wakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP =
+ "am_action_alarm_exact_wakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP =
+ "am_action_alarm_inexact_wakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP =
+ "am_action_alarm_allow_while_idle_exact_nonwakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP =
+ "am_action_alarm_exact_nonwakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP =
+ "am_action_alarm_allow_while_idle_inexact_nonwakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP =
+ "am_action_alarm_inexact_nonwakeup_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP =
+ "am_action_alarm_alarmclock_ctp";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE =
+ "am_action_alarm_allow_while_idle_exact_wakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE =
+ "am_action_alarm_allow_while_idle_inexact_wakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE =
+ "am_action_alarm_exact_wakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE =
+ "am_action_alarm_inexact_wakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE =
+ "am_action_alarm_allow_while_idle_exact_nonwakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE =
+ "am_action_alarm_exact_nonwakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE =
+ "am_action_alarm_allow_while_idle_inexact_nonwakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE =
+ "am_action_alarm_inexact_nonwakeup_base_price";
+ /** @hide */
+ public static final String KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE =
+ "am_action_alarm_alarmclock_base_price";
+
+// Keys for JobScheduler TARE factors
+ /** @hide */
+ public static final String KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED =
+ "js_min_satiated_balance_exempted";
+ /** @hide */
+ public static final String KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP =
+ "js_min_satiated_balance_headless_system_app";
+ /** @hide */
+ public static final String KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP =
+ "js_min_satiated_balance_other_app";
+ /** @hide */
+ public static final String KEY_JS_MAX_SATIATED_BALANCE =
+ "js_max_satiated_balance";
+ /** @hide */
+ public static final String KEY_JS_MAX_CIRCULATION = "js_max_circulation";
+ // TODO: Add JobScheduler modifier keys
+ /** @hide */
+ public static final String KEY_JS_REWARD_TOP_ACTIVITY_INSTANT =
+ "js_reward_top_activity_instant";
+ /** @hide */
+ public static final String KEY_JS_REWARD_TOP_ACTIVITY_ONGOING =
+ "js_reward_top_activity_ongoing";
+ /** @hide */
+ public static final String KEY_JS_REWARD_TOP_ACTIVITY_MAX =
+ "js_reward_top_activity_max";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT =
+ "js_reward_notification_seen_instant";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING =
+ "js_reward_notification_seen_ongoing";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_SEEN_MAX =
+ "js_reward_notification_seen_max";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT =
+ "js_reward_notification_interaction_instant";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING =
+ "js_reward_notification_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX =
+ "js_reward_notification_interaction_max";
+ /** @hide */
+ public static final String KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT =
+ "js_reward_widget_interaction_instant";
+ /** @hide */
+ public static final String KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING =
+ "js_reward_widget_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_JS_REWARD_WIDGET_INTERACTION_MAX =
+ "js_reward_widget_interaction_max";
+ /** @hide */
+ public static final String KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT =
+ "js_reward_other_user_interaction_instant";
+ /** @hide */
+ public static final String KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING =
+ "js_reward_other_user_interaction_ongoing";
+ /** @hide */
+ public static final String KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX =
+ "js_reward_other_user_interaction_max";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MAX_START_CTP = "js_action_job_max_start_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MAX_RUNNING_CTP = "js_action_job_max_running_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_HIGH_START_CTP = "js_action_job_high_start_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP =
+ "js_action_job_high_running_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_DEFAULT_START_CTP =
+ "js_action_job_default_start_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP =
+ "js_action_job_default_running_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_LOW_START_CTP = "js_action_job_low_start_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_LOW_RUNNING_CTP = "js_action_job_low_running_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MIN_START_CTP = "js_action_job_min_start_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MIN_RUNNING_CTP = "js_action_job_min_running_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP =
+ "js_action_job_timeout_penalty_ctp";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE =
+ "js_action_job_max_start_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE =
+ "js_action_job_max_running_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE =
+ "js_action_job_high_start_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE =
+ "js_action_job_high_running_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE =
+ "js_action_job_default_start_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE =
+ "js_action_job_default_running_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE =
+ "js_action_job_low_start_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE =
+ "js_action_job_low_running_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE =
+ "js_action_job_min_start_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE =
+ "js_action_job_min_running_base_price";
+ /** @hide */
+ public static final String KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE =
+ "js_action_job_timeout_penalty_base_price";
+
+ // Default values AlarmManager factors
+ /** @hide */
+ public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP = 200;
+ /** @hide */
+ public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP = 160;
+ /** @hide */
+ public static final int DEFAULT_AM_MAX_SATIATED_BALANCE = 1440;
+ /** @hide */
+ public static final int DEFAULT_AM_MAX_CIRCULATION = 52000;
+ // TODO: add AlarmManager modifier default values
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT = 0;
+ /** @hide */
+ public static final double DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING = 0.01;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX = 60;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT = 5;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT = 5;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT = 10;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT = 10;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX = 500;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP = 1;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP = 1;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP = 1;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP = 1;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP = 5;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE = 5;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE = 4;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE = 4;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE = 3;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE = 2;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE =
+ 2;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE = 1;
+ /** @hide */
+ public static final int DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE = 10;
+
+ // Default values JobScheduler factors
+ // TODO: add time_since_usage variable to min satiated balance factors
+ /** @hide */
+ public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED = 50000;
+ /** @hide */
+ public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP = 10000;
+ /** @hide */
+ public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP = 2000;
+ /** @hide */
+ public static final int DEFAULT_JS_MAX_SATIATED_BALANCE = 60000;
+ /** @hide */
+ public static final int DEFAULT_JS_MAX_CIRCULATION = 691200;
+ // TODO: add JobScheduler modifier default values
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT = 0;
+ /** @hide */
+ public static final double DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING = 0.5;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX = 15000;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT = 1;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX = 10;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT = 5;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX = 5000;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT = 10;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX = 5000;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT = 10;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING = 0;
+ /** @hide */
+ public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX = 5000;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MAX_START_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_HIGH_START_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_LOW_START_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MIN_START_CTP = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP = 30;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE = 10;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE = 5;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE = 8;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE = 4;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE = 6;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE = 3;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE = 4;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE = 2;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE = 1;
+ /** @hide */
+ public static final int DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE = 60;
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index f485211732f5..5bdee5e636a9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -560,6 +560,42 @@ public final class JobServiceContext implements ServiceConnection {
}
}
+ @Override
+ public void onBindingDied(ComponentName name) {
+ synchronized (mLock) {
+ if (mRunningJob == null) {
+ Slog.e(TAG, "Binding died for " + name.getPackageName()
+ + " but no running job on this context");
+ } else if (mRunningJob.getServiceComponent().equals(name)) {
+ Slog.e(TAG, "Binding died for "
+ + mRunningJob.getSourceUserId() + ":" + name.getPackageName());
+ } else {
+ Slog.e(TAG, "Binding died for " + name.getPackageName()
+ + " but context is running a different job");
+ }
+ closeAndCleanupJobLocked(true /* needsReschedule */, "binding died");
+ }
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ synchronized (mLock) {
+ if (mRunningJob == null) {
+ Slog.wtf(TAG, "Got null binding for " + name.getPackageName()
+ + " but no running job on this context");
+ } else if (mRunningJob.getServiceComponent().equals(name)) {
+ Slog.wtf(TAG, "Got null binding for "
+ + mRunningJob.getSourceUserId() + ":" + name.getPackageName());
+ } else {
+ Slog.wtf(TAG, "Got null binding for " + name.getPackageName()
+ + " but context is running a different job");
+ }
+ // Don't reschedule the job since returning a null binding is an explicit choice by the
+ // app which breaks things.
+ closeAndCleanupJobLocked(false /* needsReschedule */, "null binding");
+ }
+ }
+
/**
* This class is reused across different clients, and passes itself in as a callback. Check
* whether the client exercising the callback is the client we expect.
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 74ed334df897..d7c3a86d1d60 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -26,6 +26,8 @@ import static com.android.server.tare.EconomicPolicy.TYPE_ACTION;
import static com.android.server.tare.EconomicPolicy.TYPE_REWARD;
import static com.android.server.tare.EconomicPolicy.eventToString;
import static com.android.server.tare.EconomicPolicy.getEventType;
+import static com.android.server.tare.TareUtils.appToString;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import static com.android.server.tare.TareUtils.narcToString;
import android.annotation.NonNull;
@@ -183,7 +185,7 @@ class Agent {
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents != null) {
final long nowElapsed = SystemClock.elapsedRealtime();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
mTotalDeltaCalculator.reset(ledger, nowElapsed, now);
ongoingEvents.forEach(mTotalDeltaCalculator);
balance += mTotalDeltaCalculator.mTotal;
@@ -194,7 +196,12 @@ class Agent {
@GuardedBy("mLock")
void noteInstantaneousEventLocked(final int userId, @NonNull final String pkgName,
final int eventId, @Nullable String tag) {
- final long now = System.currentTimeMillis();
+ if (mIrs.isSystem(userId, pkgName)) {
+ // Events are free for the system. Don't bother recording them.
+ return;
+ }
+
+ final long now = getCurrentTimeMillis();
final Ledger ledger = getLedgerLocked(userId, pkgName);
final int eventType = getEventType(eventId);
@@ -231,8 +238,9 @@ class Agent {
}
@GuardedBy("mLock")
- void noteOngoingEventLocked(final int userId, @NonNull final String pkgName, final int eventId,
- @Nullable String tag, final long startElapsed, final boolean updateBalanceCheck) {
+ private void noteOngoingEventLocked(final int userId, @NonNull final String pkgName,
+ final int eventId, @Nullable String tag, final long startElapsed,
+ final boolean updateBalanceCheck) {
SparseArrayMap<String, OngoingEvent> ongoingEvents =
mCurrentOngoingEvents.get(userId, pkgName);
if (ongoingEvents == null) {
@@ -278,7 +286,7 @@ class Agent {
@GuardedBy("mLock")
void onDeviceStateChangedLocked() {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
mCurrentOngoingEvents.forEach((userId, pkgName, ongoingEvents) -> {
@@ -326,7 +334,7 @@ class Agent {
@GuardedBy("mLock")
void onAppStatesChangedLocked(final int userId, @NonNull ArraySet<String> pkgNames) {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
for (int i = 0; i < pkgNames.size(); ++i) {
@@ -391,8 +399,8 @@ class Agent {
* registered bills and notify listeners about any changes.
*/
@GuardedBy("mLock")
- void stopOngoingActionLocked(final int userId, @NonNull final String pkgName, final int eventId,
- @Nullable String tag, final long nowElapsed, final long now,
+ private void stopOngoingActionLocked(final int userId, @NonNull final String pkgName,
+ final int eventId, @Nullable String tag, final long nowElapsed, final long now,
final boolean updateBalanceCheck, final boolean notifyOnAffordabilityChange) {
final Ledger ledger = getLedgerLocked(userId, pkgName);
@@ -401,7 +409,7 @@ class Agent {
if (ongoingEvents == null) {
// This may occur if TARE goes from disabled to enabled while an event is already
// occurring.
- Slog.w(TAG, "No ongoing transactions for <" + userId + ">" + pkgName);
+ Slog.w(TAG, "No ongoing transactions for " + appToString(userId, pkgName));
return;
}
final OngoingEvent ongoingEvent = ongoingEvents.get(eventId, tag);
@@ -410,17 +418,20 @@ class Agent {
// occurring.
Slog.w(TAG, "Nonexistent ongoing transaction "
+ eventToString(eventId) + (tag == null ? "" : ":" + tag)
- + " for <" + userId + ">" + pkgName + " ended");
+ + " for " + appToString(userId, pkgName) + " ended");
return;
}
ongoingEvent.refCount--;
if (ongoingEvent.refCount <= 0) {
- final long startElapsed = ongoingEvent.startTimeElapsed;
- final long startTime = now - (nowElapsed - startElapsed);
- final long actualDelta = getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
- recordTransactionLocked(userId, pkgName, ledger,
- new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
- notifyOnAffordabilityChange);
+ if (!mIrs.isSystem(userId, pkgName)) {
+ final long startElapsed = ongoingEvent.startTimeElapsed;
+ final long startTime = now - (nowElapsed - startElapsed);
+ final long actualDelta =
+ getActualDeltaLocked(ongoingEvent, ledger, nowElapsed, now);
+ recordTransactionLocked(userId, pkgName, ledger,
+ new Ledger.Transaction(startTime, now, eventId, tag, actualDelta),
+ notifyOnAffordabilityChange);
+ }
ongoingEvents.delete(eventId, tag);
}
if (updateBalanceCheck) {
@@ -446,6 +457,15 @@ class Agent {
private void recordTransactionLocked(final int userId, @NonNull final String pkgName,
@NonNull Ledger ledger, @NonNull Ledger.Transaction transaction,
final boolean notifyOnAffordabilityChange) {
+ if (transaction.delta == 0) {
+ // Skip recording transactions with a delta of 0 to save on space.
+ return;
+ }
+ if (mIrs.isSystem(userId, pkgName)) {
+ Slog.wtfStack(TAG,
+ "Tried to adjust system balance for " + appToString(userId, pkgName));
+ return;
+ }
final long maxCirculationAllowed = mIrs.getMaxCirculationLocked();
final long newArcsInCirculation = mCurrentNarcsInCirculation + transaction.delta;
if (transaction.delta > 0 && newArcsInCirculation > maxCirculationAllowed) {
@@ -453,7 +473,8 @@ class Agent {
Slog.i(TAG, "Would result in too many credits in circulation. Decreasing transaction "
+ eventToString(transaction.eventId)
+ (transaction.tag == null ? "" : ":" + transaction.tag)
- + " for <" + userId + ">" + pkgName + " by " + (transaction.delta - newDelta));
+ + " for " + appToString(userId, pkgName)
+ + " by " + (transaction.delta - newDelta));
transaction = new Ledger.Transaction(
transaction.startTimeMs, transaction.endTimeMs,
transaction.eventId, transaction.tag, newDelta);
@@ -466,7 +487,8 @@ class Agent {
Slog.i(TAG, "Would result in becoming too rich. Decreasing transaction "
+ eventToString(transaction.eventId)
+ (transaction.tag == null ? "" : ":" + transaction.tag)
- + " for <" + userId + ">" + pkgName + " by " + (transaction.delta - newDelta));
+ + " for " + appToString(userId, pkgName)
+ + " by " + (transaction.delta - newDelta));
transaction = new Ledger.Transaction(
transaction.startTimeMs, transaction.endTimeMs,
transaction.eventId, transaction.tag, newDelta);
@@ -477,7 +499,7 @@ class Agent {
// The earliest transaction won't change until we clean up the ledger, so no point
// continuing to reschedule an existing cleanup.
final long cleanupAlarmElapsed = SystemClock.elapsedRealtime() + MAX_TRANSACTION_AGE_MS
- - (System.currentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
+ - (getCurrentTimeMillis() - ledger.getEarliestTransaction().endTimeMs);
mLedgerCleanupAlarmListener.addAlarmLocked(userId, pkgName, cleanupAlarmElapsed);
}
// TODO: save changes to disk in a background thread
@@ -509,7 +531,7 @@ class Agent {
@GuardedBy("mLock")
void reclaimUnusedAssetsLocked(double percentage) {
final List<PackageInfo> pkgs = mIrs.getInstalledPackages();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final int userId = UserHandle.getUserId(pkgs.get(i).applicationInfo.uid);
final String pkgName = pkgs.get(i).packageName;
@@ -529,7 +551,7 @@ class Agent {
}
if (toReclaim > 0) {
Slog.i(TAG, "Reclaiming unused wealth! Taking " + toReclaim
- + " from <" + userId + ">" + pkgName);
+ + " from " + appToString(userId, pkgName));
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(
@@ -543,11 +565,15 @@ class Agent {
@GuardedBy("mLock")
void distributeBasicIncomeLocked(int batteryLevel) {
List<PackageInfo> pkgs = mIrs.getInstalledPackages();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final PackageInfo pkgInfo = pkgs.get(i);
final int userId = UserHandle.getUserId(pkgInfo.applicationInfo.uid);
final String pkgName = pkgInfo.packageName;
+ if (mIrs.isSystem(userId, pkgName)) {
+ // No point allocating ARCs to the system. It can do whatever it wants.
+ continue;
+ }
Ledger ledger = getLedgerLocked(userId, pkgName);
final long minBalance = mIrs.getMinBalanceLocked(userId, pkgName);
final double perc = batteryLevel / 100d;
@@ -578,12 +604,16 @@ class Agent {
List<PackageInfo> pkgs = packageManager.getInstalledPackagesAsUser(0, userId);
final long maxBirthright =
mIrs.getMaxCirculationLocked() / mIrs.getInstalledPackages().size();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
for (int i = 0; i < pkgs.size(); ++i) {
final PackageInfo packageInfo = pkgs.get(i);
final String pkgName = packageInfo.packageName;
final Ledger ledger = getLedgerLocked(userId, pkgName);
+ if (mIrs.isSystem(userId, pkgName)) {
+ // No point allocating ARCs to the system. It can do whatever it wants.
+ continue;
+ }
if (ledger.getCurrentBalance() > 0) {
// App already got credits somehow. Move along.
Slog.wtf(TAG, "App " + pkgName + " had credits before economy was set up");
@@ -609,7 +639,7 @@ class Agent {
List<PackageInfo> pkgs = mIrs.getInstalledPackages();
final int numPackages = pkgs.size();
final long maxBirthright = mIrs.getMaxCirculationLocked() / numPackages;
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
recordTransactionLocked(userId, pkgName, ledger,
new Ledger.Transaction(now, now, REGULATION_BIRTHRIGHT, null,
@@ -818,7 +848,7 @@ class Agent {
@Override
public String toString() {
- return "<" + userId + ">" + packageName;
+ return appToString(userId, packageName);
}
@Override
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 831c05ff5701..29aa94631d68 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -124,6 +124,11 @@ public interface EconomyManagerInternal {
*/
boolean canPayFor(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
+ /**
+ * Returns the maximum duration (in milliseconds) that the specified app can afford the bill,
+ * based on current prices.
+ */
+ long getMaxDurationMs(int userId, @NonNull String pkgName, @NonNull ActionBill bill);
/**
* Register an {@link AffordabilityChangeListener} to track when an app's ability to afford the
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 67d7a95edbb8..b435c9e1a66d 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -19,10 +19,15 @@ package com.android.server.tare;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.tare.TareUtils.appToString;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.tare.IEconomyManager;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,6 +35,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManagerInternal;
@@ -45,6 +51,7 @@ import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArrayMap;
import android.util.SparseSetArray;
import com.android.internal.annotations.GuardedBy;
@@ -81,6 +88,7 @@ public class InternalResourceService extends SystemService {
private final Handler mHandler;
private final BatteryManagerInternal mBatteryManagerInternal;
private final PackageManager mPackageManager;
+ private final PackageManagerInternal mPackageManagerInternal;
private final Agent mAgent;
private final CompleteEconomicPolicy mCompleteEconomicPolicy;
@@ -95,6 +103,10 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
+ /** Cached mapping of userId+package to their UIDs (for all users) */
+ @GuardedBy("mPackageToUidCache")
+ private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
+
private volatile boolean mIsEnabled;
private volatile int mBootPhase;
// In the range [0,100] to represent 0% to 100% battery.
@@ -104,7 +116,6 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private long mLastUnusedReclamationTime;
- @SuppressWarnings("FieldCanBeLocal")
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Nullable
private String getPackageName(Intent intent) {
@@ -153,13 +164,25 @@ public class InternalResourceService extends SystemService {
}
};
+ private final UsageStatsManagerInternal.UsageEventListener mSurveillanceAgent =
+ new UsageStatsManagerInternal.UsageEventListener() {
+ /**
+ * Callback to inform listeners of a new event.
+ */
+ @Override
+ public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) {
+ mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event)
+ .sendToTarget();
+ }
+ };
+
private final AlarmManager.OnAlarmListener mUnusedWealthReclamationListener =
new AlarmManager.OnAlarmListener() {
@Override
public void onAlarm() {
synchronized (mLock) {
mAgent.reclaimUnusedAssetsLocked(DEFAULT_UNUSED_RECLAMATION_PERCENTAGE);
- mLastUnusedReclamationTime = System.currentTimeMillis();
+ mLastUnusedReclamationTime = getCurrentTimeMillis();
scheduleUnusedWealthReclamationLocked();
}
}
@@ -167,6 +190,7 @@ public class InternalResourceService extends SystemService {
private static final int MSG_NOTIFY_AFFORDABILITY_CHANGE_LISTENER = 0;
private static final int MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT = 1;
+ private static final int MSG_PROCESS_USAGE_EVENT = 2;
private static final String ALARM_TAG_WEALTH_RECLAMATION = "*tare.reclamation*";
private static final String KEY_PKG = "pkg";
@@ -185,6 +209,7 @@ public class InternalResourceService extends SystemService {
mHandler = new IrsHandler(TareHandlerThread.get().getLooper());
mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
mPackageManager = context.getPackageManager();
+ mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mEconomyManagerStub = new EconomyManagerStub();
mCompleteEconomicPolicy = new CompleteEconomicPolicy(this);
mAgent = new Agent(this, mCompleteEconomicPolicy);
@@ -232,10 +257,28 @@ public class InternalResourceService extends SystemService {
/ 100;
}
+ int getUid(final int userId, @NonNull final String pkgName) {
+ synchronized (mPackageToUidCache) {
+ Integer uid = mPackageToUidCache.get(userId, pkgName);
+ if (uid == null) {
+ uid = mPackageManagerInternal.getPackageUid(pkgName, 0, userId);
+ mPackageToUidCache.add(userId, pkgName, uid);
+ }
+ return uid;
+ }
+ }
+
boolean isEnabled() {
return mIsEnabled;
}
+ boolean isSystem(final int userId, @NonNull String pkgName) {
+ if ("android".equals(pkgName)) {
+ return true;
+ }
+ return UserHandle.isCore(getUid(userId, pkgName));
+ }
+
void onBatteryLevelChanged() {
synchronized (mLock) {
final int newBatteryLevel = getCurrentBatteryLevel();
@@ -261,6 +304,9 @@ public class InternalResourceService extends SystemService {
Slog.wtf(TAG, "PM couldn't find newly added package: " + pkgName);
return;
}
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.add(userId, pkgName, uid);
+ }
synchronized (mLock) {
mPkgCache.add(packageInfo);
mUidToPackageCache.add(uid, pkgName);
@@ -277,6 +323,9 @@ public class InternalResourceService extends SystemService {
void onPackageRemoved(final int uid, @NonNull final String pkgName) {
final int userId = UserHandle.getUserId(uid);
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.delete(userId, pkgName);
+ }
synchronized (mLock) {
mUidToPackageCache.remove(uid, pkgName);
for (int i = 0; i < mPkgCache.size(); ++i) {
@@ -341,8 +390,44 @@ public class InternalResourceService extends SystemService {
}
@GuardedBy("mLock")
+ private void processUsageEventLocked(final int userId, @NonNull UsageEvents.Event event) {
+ if (!mIsEnabled) {
+ return;
+ }
+ final String pkgName = event.getPackageName();
+ if (DEBUG) {
+ Slog.d(TAG, "Processing event " + event.getEventType()
+ + " for " + appToString(userId, pkgName));
+ }
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ switch (event.getEventType()) {
+ case UsageEvents.Event.ACTIVITY_RESUMED:
+ mAgent.noteOngoingEventLocked(userId, pkgName,
+ EconomicPolicy.REWARD_TOP_ACTIVITY, null, nowElapsed);
+ break;
+ case UsageEvents.Event.ACTIVITY_PAUSED:
+ case UsageEvents.Event.ACTIVITY_STOPPED:
+ case UsageEvents.Event.ACTIVITY_DESTROYED:
+ final long now = getCurrentTimeMillis();
+ mAgent.stopOngoingActionLocked(userId, pkgName,
+ EconomicPolicy.REWARD_TOP_ACTIVITY, null, nowElapsed, now);
+ break;
+ case UsageEvents.Event.USER_INTERACTION:
+ case UsageEvents.Event.CHOOSER_ACTION:
+ mAgent.noteInstantaneousEventLocked(userId, pkgName,
+ EconomicPolicy.REWARD_OTHER_USER_INTERACTION, null);
+ break;
+ case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+ case UsageEvents.Event.NOTIFICATION_SEEN:
+ mAgent.noteInstantaneousEventLocked(userId, pkgName,
+ EconomicPolicy.REWARD_NOTIFICATION_SEEN, null);
+ break;
+ }
+ }
+
+ @GuardedBy("mLock")
private void scheduleUnusedWealthReclamationLocked() {
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
final long nextReclamationTime =
Math.max(mLastUnusedReclamationTime + UNUSED_RECLAMATION_PERIOD_MS, now + 30_000);
mHandler.post(() -> {
@@ -385,7 +470,7 @@ public class InternalResourceService extends SystemService {
mPkgCache = mPackageManager.getInstalledPackages(0);
}
- private void registerReceivers() {
+ private void registerListeners() {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
@@ -402,6 +487,9 @@ public class InternalResourceService extends SystemService {
userFilter.addAction(Intent.ACTION_USER_ADDED);
getContext()
.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+
+ UsageStatsManagerInternal usmi = LocalServices.getService(UsageStatsManagerInternal.class);
+ usmi.registerListener(mSurveillanceAgent);
}
/** Perform long-running and/or heavy setup work. This should be called off the main thread. */
@@ -421,7 +509,7 @@ public class InternalResourceService extends SystemService {
return;
}
synchronized (mLock) {
- registerReceivers();
+ registerListeners();
mCurrentBatteryLevel = getCurrentBatteryLevel();
mHandler.post(this::setupHeavyWork);
scheduleUnusedWealthReclamationLocked();
@@ -446,6 +534,12 @@ public class InternalResourceService extends SystemService {
mPkgCache.clear();
mUidToPackageCache.clear();
getContext().unregisterReceiver(mBroadcastReceiver);
+ UsageStatsManagerInternal usmi =
+ LocalServices.getService(UsageStatsManagerInternal.class);
+ usmi.unregisterListener(mSurveillanceAgent);
+ }
+ synchronized (mPackageToUidCache) {
+ mPackageToUidCache.clear();
}
}
@@ -471,6 +565,15 @@ public class InternalResourceService extends SystemService {
}
break;
+ case MSG_PROCESS_USAGE_EVENT: {
+ final int userId = msg.arg1;
+ final UsageEvents.Event event = (UsageEvents.Event) msg.obj;
+ synchronized (mLock) {
+ processUsageEventLocked(userId, event);
+ }
+ }
+ break;
+
case MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT: {
removeMessages(MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT);
synchronized (mLock) {
@@ -514,9 +617,22 @@ public class InternalResourceService extends SystemService {
}
private final class LocalService implements EconomyManagerInternal {
+ /**
+ * Use an extremely large value to indicate that an app can pay for a bill indefinitely.
+ * The value set here should be large/long enough that there's no reasonable expectation
+ * of a device operating uninterrupted (or in the exact same state) for that period of time.
+ * We intentionally don't use Long.MAX_VALUE to avoid potential overflow if a client
+ * doesn't check the value and just immediately adds it to the current time.
+ */
+ private static final long FOREVER_MS = 27 * 365 * 24 * HOUR_IN_MILLIS;
+
@Override
public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName,
@NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+ if (isSystem(userId, pkgName)) {
+ // The system's affordability never changes.
+ return;
+ }
synchronized (mLock) {
mAgent.registerAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
}
@@ -525,6 +641,10 @@ public class InternalResourceService extends SystemService {
@Override
public void unregisterAffordabilityChangeListener(int userId, @NonNull String pkgName,
@NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
+ if (isSystem(userId, pkgName)) {
+ // The system's affordability never changes.
+ return;
+ }
synchronized (mLock) {
mAgent.unregisterAffordabilityChangeListenerLocked(userId, pkgName, listener, bill);
}
@@ -535,6 +655,11 @@ public class InternalResourceService extends SystemService {
if (!mIsEnabled) {
return true;
}
+ if (isSystem(userId, pkgName)) {
+ // The government, I mean the system, can create ARCs as it needs to in order to
+ // operate.
+ return true;
+ }
// TODO: take temp-allowlist into consideration
long requiredBalance = 0;
final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
@@ -552,6 +677,32 @@ public class InternalResourceService extends SystemService {
}
@Override
+ public long getMaxDurationMs(int userId, @NonNull String pkgName,
+ @NonNull ActionBill bill) {
+ if (!mIsEnabled) {
+ return FOREVER_MS;
+ }
+ if (isSystem(userId, pkgName)) {
+ return FOREVER_MS;
+ }
+ long totalCostPerSecond = 0;
+ final List<EconomyManagerInternal.AnticipatedAction> projectedActions =
+ bill.getAnticipatedActions();
+ for (int i = 0; i < projectedActions.size(); ++i) {
+ AnticipatedAction action = projectedActions.get(i);
+ final long cost =
+ mCompleteEconomicPolicy.getCostOfAction(action.actionId, userId, pkgName);
+ totalCostPerSecond += cost;
+ }
+ if (totalCostPerSecond == 0) {
+ return FOREVER_MS;
+ }
+ synchronized (mLock) {
+ return mAgent.getBalanceLocked(userId, pkgName) * 1000 / totalCostPerSecond;
+ }
+ }
+
+ @Override
public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
@@ -581,7 +732,7 @@ public class InternalResourceService extends SystemService {
return;
}
final long nowElapsed = SystemClock.elapsedRealtime();
- final long now = System.currentTimeMillis();
+ final long now = getCurrentTimeMillis();
synchronized (mLock) {
mAgent.stopOngoingActionLocked(userId, pkgName, eventId, tag, nowElapsed, now);
}
@@ -630,6 +781,9 @@ public class InternalResourceService extends SystemService {
private void dumpInternal(final IndentingPrintWriter pw) {
synchronized (mLock) {
+ pw.print("Is enabled: ");
+ pw.println(mIsEnabled);
+
pw.print("Current battery level: ");
pw.println(mCurrentBatteryLevel);
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
index ae1bf26f36f2..76543d74f15e 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Ledger.java
@@ -19,6 +19,7 @@ package com.android.server.tare;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static com.android.server.tare.TareUtils.dumpTime;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import static com.android.server.tare.TareUtils.narcToString;
import android.annotation.NonNull;
@@ -109,8 +110,8 @@ class Ledger {
/** Deletes transactions that are older than {@code minAgeMs}. */
void removeOldTransactions(long minAgeMs) {
- final long cutoff = System.currentTimeMillis() - minAgeMs;
- while (mTransactions.get(0).endTimeMs <= cutoff) {
+ final long cutoff = getCurrentTimeMillis() - minAgeMs;
+ while (mTransactions.size() > 0 && mTransactions.get(0).endTimeMs <= cutoff) {
mTransactions.remove(0);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
index 92a2014a6600..67a3dc67e569 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ProcessStateModifier.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.IUidObserver;
-import android.content.pm.PackageManagerInternal;
import android.os.RemoteException;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -28,7 +27,6 @@ import android.util.SparseArrayMap;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.LocalServices;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -56,7 +54,6 @@ class ProcessStateModifier extends Modifier {
private final Object mLock = new Object();
private final InternalResourceService mIrs;
- private final PackageManagerInternal mPackageManagerInternal;
/** Cached mapping of userId+package to their UIDs (for all users) */
private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
@@ -105,7 +102,6 @@ class ProcessStateModifier extends Modifier {
ProcessStateModifier(@NonNull InternalResourceService irs) {
super();
mIrs = irs;
- mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
}
@Override
@@ -143,7 +139,7 @@ class ProcessStateModifier extends Modifier {
final int procState;
synchronized (mLock) {
procState = mUidProcStateBucketCache.get(
- getUidLocked(userId, pkgName), PROC_STATE_BUCKET_NONE);
+ mIrs.getUid(userId, pkgName), PROC_STATE_BUCKET_NONE);
}
switch (procState) {
case PROC_STATE_BUCKET_TOP:
@@ -166,15 +162,6 @@ class ProcessStateModifier extends Modifier {
pw.println(mUidProcStateBucketCache);
}
- @GuardedBy("mLock")
- private int getUidLocked(final int userId, @NonNull final String pkgName) {
- if (!mPackageToUidCache.contains(userId, pkgName)) {
- mPackageToUidCache.add(userId, pkgName,
- mPackageManagerInternal.getPackageUid(pkgName, 0, userId));
- }
- return mPackageToUidCache.get(userId, pkgName);
- }
-
@ProcStateBucket
private int getProcStateBucket(int procState) {
if (procState <= ActivityManager.PROCESS_STATE_TOP) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
index 2d72f5688688..1e047aa60cf8 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
@@ -20,7 +20,10 @@ import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.util.IndentingPrintWriter;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.text.SimpleDateFormat;
+import java.time.Clock;
class TareUtils {
private static final long NARC_IN_ARC = 1_000_000_000L;
@@ -29,6 +32,9 @@ class TareUtils {
private static final SimpleDateFormat sDumpDateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ @VisibleForTesting
+ static Clock sSystemClock = Clock.systemUTC();
+
static long arcToNarc(int arcs) {
return arcs * NARC_IN_ARC;
}
@@ -37,6 +43,10 @@ class TareUtils {
pw.print(sDumpDateFormat.format(time));
}
+ static long getCurrentTimeMillis() {
+ return sSystemClock.millis();
+ }
+
static int narcToArc(long narcs) {
return (int) (narcs / NARC_IN_ARC);
}
@@ -59,4 +69,10 @@ class TareUtils {
sb.append(" ARCs");
return sb.toString();
}
+
+ /** Returns a standardized format for printing userId+pkgName combinations. */
+ @NonNull
+ static String appToString(int userId, String pkgName) {
+ return "<" + userId + ">" + pkgName;
+ }
}
diff --git a/api/Android.bp b/api/Android.bp
index 2ea180ebf598..66b6dbafcc85 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -90,6 +90,7 @@ genrule {
":framework-sdkextensions{.public.api.txt}",
":framework-statsd{.public.api.txt}",
":framework-tethering{.public.api.txt}",
+ ":framework-uwb{.public.api.txt}",
":framework-wifi{.public.api.txt}",
":i18n.module.public.api{.public.api.txt}",
":non-updatable-current.txt",
@@ -149,6 +150,7 @@ genrule {
":framework-sdkextensions{.public.stubs.source}",
":framework-statsd{.public.stubs.source}",
":framework-tethering{.public.stubs.source}",
+ ":framework-uwb{.public.stubs.source}",
":framework-wifi{.public.stubs.source}",
":i18n.module.public.api{.public.stubs.source}",
],
@@ -175,6 +177,7 @@ genrule {
":framework-sdkextensions{.public.removed-api.txt}",
":framework-statsd{.public.removed-api.txt}",
":framework-tethering{.public.removed-api.txt}",
+ ":framework-uwb{.public.removed-api.txt}",
":framework-wifi{.public.removed-api.txt}",
":i18n.module.public.api{.public.removed-api.txt}",
":non-updatable-removed.txt",
@@ -215,6 +218,7 @@ genrule {
":framework-sdkextensions{.system.api.txt}",
":framework-statsd{.system.api.txt}",
":framework-tethering{.system.api.txt}",
+ ":framework-uwb{.system.api.txt}",
":framework-wifi{.system.api.txt}",
":non-updatable-system-current.txt",
],
@@ -273,6 +277,7 @@ genrule {
":framework-sdkextensions{.system.removed-api.txt}",
":framework-statsd{.system.removed-api.txt}",
":framework-tethering{.system.removed-api.txt}",
+ ":framework-uwb{.system.removed-api.txt}",
":framework-wifi{.system.removed-api.txt}",
":non-updatable-system-removed.txt",
],
@@ -313,6 +318,7 @@ genrule {
":framework-sdkextensions{.module-lib.api.txt}",
":framework-statsd{.module-lib.api.txt}",
":framework-tethering{.module-lib.api.txt}",
+ ":framework-uwb{.module-lib.api.txt}",
":framework-wifi{.module-lib.api.txt}",
":non-updatable-module-lib-current.txt",
],
@@ -373,6 +379,7 @@ genrule {
":framework-sdkextensions{.module-lib.removed-api.txt}",
":framework-statsd{.module-lib.removed-api.txt}",
":framework-tethering{.module-lib.removed-api.txt}",
+ ":framework-uwb{.module-lib.removed-api.txt}",
":framework-wifi{.module-lib.removed-api.txt}",
":non-updatable-module-lib-removed.txt",
],
@@ -491,6 +498,7 @@ genrule {
":framework-sdkextensions.stubs{.jar}",
":framework-statsd.stubs{.jar}",
":framework-tethering.stubs{.jar}",
+ ":framework-uwb.stubs{.jar}",
":framework-wifi.stubs{.jar}",
":i18n.module.public.api.stubs{.jar}",
],
diff --git a/boot/Android.bp b/boot/Android.bp
index b71f9bf519cb..049c8026faa9 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -100,6 +100,10 @@ platform_bootclasspath {
module: "com.android.tethering-bootclasspath-fragment",
},
{
+ apex: "com.android.uwb",
+ module: "com.android.uwb-bootclasspath-fragment",
+ },
+ {
apex: "com.android.wifi",
module: "com.android.wifi-bootclasspath-fragment",
},
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index b2b66c27f795..3534624a58a2 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -71,7 +71,7 @@ cc_library_shared {
"libui",
"libjnigraphics",
"libEGL",
- "libGLESv1_CM",
+ "libGLESv2",
"libgui",
],
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 3109c5c1e075..6e27aff5ae7b 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -52,9 +52,8 @@
#include <gui/DisplayEventReceiver.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
#include <EGL/eglext.h>
#include "BootAnimation.h"
@@ -108,6 +107,56 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress";
static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
static constexpr size_t TEXT_POS_LEN_MAX = 16;
+static const char U_TEXTURE[] = "uTexture";
+static const char U_FADE[] = "uFade";
+static const char U_CROP_AREA[] = "uCropArea";
+static const char A_UV[] = "aUv";
+static const char A_POSITION[] = "aPosition";
+static const char VERTEX_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ attribute vec4 aPosition;
+ attribute highp vec2 aUv;
+ varying highp vec2 vUv;
+ void main() {
+ gl_Position = aPosition;
+ vUv = aUv;
+ })";
+static const char IMAGE_FRAG_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ uniform sampler2D uTexture;
+ uniform float uFade;
+ varying highp vec2 vUv;
+ void main() {
+ vec4 color = texture2D(uTexture, vUv);
+ gl_FragColor = vec4(color.x, color.y, color.z, 1.0 - uFade);
+ })";
+static const char TEXT_FRAG_SHADER_SOURCE[] = R"(
+ precision mediump float;
+ uniform sampler2D uTexture;
+ uniform vec4 uCropArea;
+ varying highp vec2 vUv;
+ void main() {
+ vec2 uv = vec2(mix(uCropArea.x, uCropArea.z, vUv.x),
+ mix(uCropArea.y, uCropArea.w, vUv.y));
+ gl_FragColor = texture2D(uTexture, uv);
+ })";
+
+static GLfloat quadPositions[] = {
+ -0.5f, -0.5f,
+ +0.5f, -0.5f,
+ +0.5f, +0.5f,
+ +0.5f, +0.5f,
+ -0.5f, +0.5f,
+ -0.5f, -0.5f
+};
+static GLfloat quadUVs[] = {
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f
+};
// ---------------------------------------------------------------------------
@@ -209,7 +258,6 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
const int w = bitmapInfo.width;
const int h = bitmapInfo.height;
- GLint crop[4] = { 0, h, w, -h };
texture->w = w;
texture->h = h;
@@ -237,11 +285,10 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
break;
}
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return NO_ERROR;
}
@@ -263,7 +310,6 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
const int w = bitmapInfo.width;
const int h = bitmapInfo.height;
- GLint crop[4] = { 0, h, w, -h };
int tw = 1 << (31 - __builtin_clz(w));
int th = 1 << (31 - __builtin_clz(h));
if (tw < w) tw <<= 1;
@@ -297,7 +343,10 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) {
break;
}
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
*width = w;
*height = h;
@@ -470,7 +519,9 @@ status_t BootAnimation::readyToRun() {
eglInitialize(display, nullptr, nullptr);
EGLConfig config = getEglConfig(display);
EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
- EGLContext context = eglCreateContext(display, config, nullptr, nullptr);
+ // Initialize egl context with client version number 2.0.
+ EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes);
EGLint w, h;
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
@@ -503,11 +554,6 @@ status_t BootAnimation::readyToRun() {
void BootAnimation::projectSceneToWindow() {
glViewport(0, 0, mWidth, mHeight);
glScissor(0, 0, mWidth, mHeight);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, static_cast<float>(mWidth), 0, static_cast<float>(mHeight), -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
}
void BootAnimation::resizeSurface(int newWidth, int newHeight) {
@@ -600,8 +646,68 @@ void BootAnimation::findBootAnimationFile() {
}
}
+GLuint compileShader(GLenum shaderType, const GLchar *source) {
+ GLuint shader = glCreateShader(shaderType);
+ glShaderSource(shader, 1, &source, 0);
+ glCompileShader(shader);
+ GLint isCompiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
+ if (isCompiled == GL_FALSE) {
+ SLOGE("Compile shader failed. Shader type: %d", shaderType);
+ return 0;
+ }
+ return shader;
+}
+
+GLuint linkShader(GLuint vertexShader, GLuint fragmentShader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, fragmentShader);
+ glLinkProgram(program);
+ GLint isLinked = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
+ if (isLinked == GL_FALSE) {
+ SLOGE("Linking shader failed. Shader handles: vert %d, frag %d",
+ vertexShader, fragmentShader);
+ return 0;
+ }
+ return program;
+}
+
+void BootAnimation::initShaders() {
+ GLuint vertexShader = compileShader(GL_VERTEX_SHADER, (const GLchar *)VERTEX_SHADER_SOURCE);
+ GLuint imageFragmentShader =
+ compileShader(GL_FRAGMENT_SHADER, (const GLchar *)IMAGE_FRAG_SHADER_SOURCE);
+ GLuint textFragmentShader =
+ compileShader(GL_FRAGMENT_SHADER, (const GLchar *)TEXT_FRAG_SHADER_SOURCE);
+
+ // Initialize image shader.
+ mImageShader = linkShader(vertexShader, imageFragmentShader);
+ GLint positionLocation = glGetAttribLocation(mImageShader, A_POSITION);
+ GLint uvLocation = glGetAttribLocation(mImageShader, A_UV);
+ mImageTextureLocation = glGetUniformLocation(mImageShader, U_TEXTURE);
+ mImageFadeLocation = glGetUniformLocation(mImageShader, U_FADE);
+ glEnableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions);
+ glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+ glEnableVertexAttribArray(uvLocation);
+
+ // Initialize text shader.
+ mTextShader = linkShader(vertexShader, textFragmentShader);
+ positionLocation = glGetAttribLocation(mTextShader, A_POSITION);
+ uvLocation = glGetAttribLocation(mTextShader, A_UV);
+ mTextTextureLocation = glGetUniformLocation(mTextShader, U_TEXTURE);
+ mTextCropAreaLocation = glGetUniformLocation(mTextShader, U_CROP_AREA);
+ glEnableVertexAttribArray(positionLocation);
+ glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, quadPositions);
+ glVertexAttribPointer(uvLocation, 2, GL_FLOAT, GL_FALSE, 0, quadUVs);
+ glEnableVertexAttribArray(uvLocation);
+}
+
bool BootAnimation::threadLoop() {
bool result;
+ initShaders();
+
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {
@@ -623,6 +729,8 @@ bool BootAnimation::threadLoop() {
}
bool BootAnimation::android() {
+ glActiveTexture(GL_TEXTURE0);
+
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
@@ -631,19 +739,14 @@ bool BootAnimation::android() {
mCallbacks->init({});
// clear screen
- glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(mDisplay, mSurface);
- glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
// Blend state
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
const nsecs_t startTime = systemTime();
do {
@@ -666,12 +769,12 @@ bool BootAnimation::android() {
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
- glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h);
- glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
+ drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
+ drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
- glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
+ drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
if (res == EGL_FALSE)
@@ -798,10 +901,10 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) {
status = initTexture(font->map, &font->texture.w, &font->texture.h);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else if (fallback != nullptr) {
status = initTexture(&font->texture, mAssets, fallback);
} else {
@@ -816,40 +919,11 @@ status_t BootAnimation::initFont(Font* font, const char* fallback) {
return status;
}
-void BootAnimation::fadeFrame(const int frameLeft, const int frameBottom, const int frameWidth,
- const int frameHeight, const Animation::Part& part,
- const int fadedFramesCount) {
- glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_TEXTURE_2D);
- // avoid creating a hole due to mixing result alpha with GL_REPLACE texture
- glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
-
- const float alpha = static_cast<float>(fadedFramesCount) / part.framesToFadeCount;
- glColor4f(part.backgroundColor[0], part.backgroundColor[1], part.backgroundColor[2], alpha);
-
- const float frameStartX = static_cast<float>(frameLeft);
- const float frameStartY = static_cast<float>(frameBottom);
- const float frameEndX = frameStartX + frameWidth;
- const float frameEndY = frameStartY + frameHeight;
- const GLfloat frameRect[] = {
- frameStartX, frameStartY,
- frameEndX, frameStartY,
- frameEndX, frameEndY,
- frameStartX, frameEndY
- };
- glVertexPointer(2, GL_FLOAT, 0, frameRect);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_TEXTURE_2D);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_BLEND);
-}
-
void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) {
glEnable(GL_BLEND); // Allow us to draw on top of the animation
glBindTexture(GL_TEXTURE_2D, font.texture.name);
+ glUseProgram(mTextShader);
+ glUniform1i(mTextTextureLocation, 0);
const int len = strlen(str);
const int strWidth = font.char_width * len;
@@ -865,8 +939,6 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int*
*y = mHeight + *y - font.char_height;
}
- int cropRect[4] = { 0, 0, font.char_width, -font.char_height };
-
for (int i = 0; i < len; i++) {
char c = str[i];
@@ -878,13 +950,13 @@ void BootAnimation::drawText(const char* str, const Font& font, bool bold, int*
const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters
const int row = charPos / FONT_NUM_COLS;
const int col = charPos % FONT_NUM_COLS;
- cropRect[0] = col * font.char_width; // Left of column
- cropRect[1] = row * font.char_height * 2; // Top of row
- // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line
- cropRect[1] += bold ? 2 * font.char_height : font.char_height;
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
-
- glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height);
+ // Bold fonts are expected in the second half of each row.
+ float v0 = (row + (bold ? 0.5f : 0.0f)) / FONT_NUM_ROWS;
+ float u0 = ((float)col) / FONT_NUM_COLS;
+ float v1 = v0 + 1.0f / FONT_NUM_ROWS / 2;
+ float u1 = u0 + 1.0f / FONT_NUM_COLS;
+ glUniform4f(mTextCropAreaLocation, u0, v0, u1, v1);
+ drawTexturedQuad(*x, *y, font.char_width, font.char_height);
*x += font.char_width;
}
@@ -1166,19 +1238,16 @@ bool BootAnimation::movie() {
// Blend required to draw time on top of animation frames.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
- glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
bool clockFontInitialized = false;
if (mClockEnabled) {
clockFontInitialized =
@@ -1218,6 +1287,34 @@ bool BootAnimation::shouldStopPlayingPart(const Animation::Part& part,
(lastDisplayedProgress == 0 || lastDisplayedProgress == 100);
}
+// Linear mapping from range <a1, a2> to range <b1, b2>
+float mapLinear(float x, float a1, float a2, float b1, float b2) {
+ return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
+}
+
+void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, float height) {
+ // Map coordinates from screen space to world space.
+ float x0 = mapLinear(xStart, 0, mWidth, -1, 1);
+ float y0 = mapLinear(yStart, 0, mHeight, -1, 1);
+ float x1 = mapLinear(xStart + width, 0, mWidth, -1, 1);
+ float y1 = mapLinear(yStart + height, 0, mHeight, -1, 1);
+ // Update quad vertex positions.
+ quadPositions[0] = x0;
+ quadPositions[1] = y0;
+ quadPositions[2] = x1;
+ quadPositions[3] = y0;
+ quadPositions[4] = x1;
+ quadPositions[5] = y1;
+ quadPositions[6] = x1;
+ quadPositions[7] = y1;
+ quadPositions[8] = x0;
+ quadPositions[9] = y1;
+ quadPositions[10] = x0;
+ quadPositions[11] = y0;
+ glDrawArrays(GL_TRIANGLES, 0,
+ sizeof(quadPositions) / sizeof(quadPositions[0]) / 2);
+}
+
bool BootAnimation::playAnimation(const Animation& animation) {
const size_t pcount = animation.parts.size();
nsecs_t frameDuration = s2ns(1) / animation.fps;
@@ -1230,7 +1327,6 @@ bool BootAnimation::playAnimation(const Animation& animation) {
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
- glBindTexture(GL_TEXTURE_2D, 0);
// Handle animation package
if (part.animation != nullptr) {
@@ -1272,12 +1368,8 @@ bool BootAnimation::playAnimation(const Animation& animation) {
if (r > 0) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
- if (part.count != 1) {
- glGenTextures(1, &frame.tid);
- glBindTexture(GL_TEXTURE_2D, frame.tid);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
+ glGenTextures(1, &frame.tid);
+ glBindTexture(GL_TEXTURE_2D, frame.tid);
int w, h;
initTexture(frame.map, &w, &h);
}
@@ -1300,16 +1392,21 @@ bool BootAnimation::playAnimation(const Animation& animation) {
// specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
// which is equivalent to mHeight - (yc + frame.trimHeight)
const int frameDrawY = mHeight - (yc + frame.trimHeight);
- glDrawTexiOES(xc, frameDrawY, 0, frame.trimWidth, frame.trimHeight);
+ float fade = 0;
// if the part hasn't been stopped yet then continue fading if necessary
if (exitPending() && part.hasFadingPhase()) {
- fadeFrame(xc, frameDrawY, frame.trimWidth, frame.trimHeight, part,
- ++fadedFramesCount);
+ fade = static_cast<float>(++fadedFramesCount) / part.framesToFadeCount;
if (fadedFramesCount >= part.framesToFadeCount) {
fadedFramesCount = MAX_FADED_FRAMES_COUNT; // no more fading
}
}
+ glUseProgram(mImageShader);
+ glUniform1i(mImageTextureLocation, 0);
+ glUniform1f(mImageFadeLocation, fade);
+ glEnable(GL_BLEND);
+ drawTexturedQuad(xc, frameDrawY, frame.trimWidth, frame.trimHeight);
+ glDisable(GL_BLEND);
if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f8a31c6d8790..7b616d91c58b 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -31,7 +31,7 @@
#include <binder/IBinder.h>
#include <EGL/egl.h>
-#include <GLES/gl.h>
+#include <GLES2/gl2.h>
namespace android {
@@ -166,6 +166,7 @@ private:
status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
status_t initTexture(FileMap* map, int* width, int* height);
status_t initFont(Font* font, const char* fallback);
+ void initShaders();
bool android();
bool movie();
void drawText(const char* str, const Font& font, bool bold, int* x, int* y);
@@ -173,6 +174,7 @@ private:
void drawProgress(int percent, const Font& font, const int xPos, const int yPos);
void fadeFrame(int frameLeft, int frameBottom, int frameWidth, int frameHeight,
const Animation::Part& part, int fadedFramesCount);
+ void drawTexturedQuad(float xStart, float yStart, float width, float height);
bool validClock(const Animation::Part& part);
Animation* loadAnimation(const String8&);
bool playAnimation(const Animation&);
@@ -218,6 +220,12 @@ private:
sp<TimeCheckThread> mTimeCheckThread = nullptr;
sp<Callbacks> mCallbacks;
Animation* mAnimation = nullptr;
+ GLuint mImageShader;
+ GLuint mTextShader;
+ GLuint mImageFadeLocation;
+ GLuint mImageTextureLocation;
+ GLuint mTextCropAreaLocation;
+ GLuint mTextTextureLocation;
};
// ---------------------------------------------------------------------------
diff --git a/core/api/current.txt b/core/api/current.txt
index 4c1476cc3b33..8e8a9e6b658a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6652,7 +6652,7 @@ package android.app {
method public boolean onUnbind(android.content.Intent);
method public final void startForeground(int, android.app.Notification);
method public final void startForeground(int, @NonNull android.app.Notification, int);
- method public final void stopForeground(boolean);
+ method @Deprecated public final void stopForeground(boolean);
method public final void stopForeground(int);
method public final void stopSelf();
method public final void stopSelf(int);
@@ -9124,6 +9124,7 @@ package android.bluetooth {
field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
field public static final int GATT_FAILURE = 257; // 0x101
field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
+ field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8
field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
field public static final int GATT_INVALID_OFFSET = 7; // 0x7
@@ -25266,13 +25267,17 @@ package android.media.session {
public final class MediaSessionManager {
method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName);
method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @Nullable android.os.Handler);
+ method public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
method public void addOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener, @NonNull android.os.Handler);
method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessions(@Nullable android.content.ComponentName);
+ method @Nullable public android.media.session.MediaSession.Token getMediaKeyEventSession();
+ method @NonNull public String getMediaKeyEventSessionPackageName();
method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
method public boolean isTrustedForMediaControl(@NonNull android.media.session.MediaSessionManager.RemoteUserInfo);
method @Deprecated public void notifySession2Created(@NonNull android.media.Session2Token);
method public void removeOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
+ method public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method public void removeOnSession2TokensChangedListener(@NonNull android.media.session.MediaSessionManager.OnSession2TokensChangedListener);
}
@@ -25280,6 +25285,10 @@ package android.media.session {
method public void onActiveSessionsChanged(@Nullable java.util.List<android.media.session.MediaController>);
}
+ public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
+ method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
+ }
+
public static interface MediaSessionManager.OnSession2TokensChangedListener {
method public void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
}
@@ -31676,6 +31685,7 @@ package android.os {
method public boolean isDeviceIdleMode();
method public boolean isIgnoringBatteryOptimizations(String);
method public boolean isInteractive();
+ method public boolean isLightDeviceIdleMode();
method public boolean isPowerSaveMode();
method public boolean isRebootingUserspaceSupported();
method @Deprecated public boolean isScreenOn();
@@ -31686,6 +31696,7 @@ package android.os {
method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
+ field public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
field @Deprecated public static final int FULL_WAKE_LOCK = 26; // 0x1a
field public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; // 0x2
@@ -34824,6 +34835,7 @@ package android.provider {
}
public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
+ field public static final String ACTION_SET_DEFAULT_ACCOUNT = "android.provider.action.SET_DEFAULT_ACCOUNT";
field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
field public static final android.net.Uri CONTENT_URI;
@@ -39684,6 +39696,7 @@ package android.telecom {
method public final void cancelCall();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onPlaceCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
+ method public void onRedirectionTimeout();
method public final boolean onUnbind(@NonNull android.content.Intent);
method public final void placeCallUnmodified();
method public final void redirectCall(@NonNull android.net.Uri, @NonNull android.telecom.PhoneAccountHandle, boolean);
@@ -51933,7 +51946,7 @@ package android.view.inputmethod {
method public boolean finishComposingText();
method public int getCursorCapsMode(int);
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
- method public android.os.Handler getHandler();
+ method @Nullable public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 96c990d51696..86d67b04085f 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2107,6 +2107,7 @@ package android.bluetooth {
field @NonNull public static final android.os.ParcelUuid BASE_UUID;
field @NonNull public static final android.os.ParcelUuid BNEP;
field @NonNull public static final android.os.ParcelUuid DIP;
+ field @NonNull public static final android.os.ParcelUuid GENERIC_MEDIA_CONTROL;
field @NonNull public static final android.os.ParcelUuid HEARING_AID;
field @NonNull public static final android.os.ParcelUuid HFP;
field @NonNull public static final android.os.ParcelUuid HFP_AG;
@@ -2117,6 +2118,7 @@ package android.bluetooth {
field @NonNull public static final android.os.ParcelUuid LE_AUDIO;
field @NonNull public static final android.os.ParcelUuid MAP;
field @NonNull public static final android.os.ParcelUuid MAS;
+ field @NonNull public static final android.os.ParcelUuid MEDIA_CONTROL;
field @NonNull public static final android.os.ParcelUuid MNS;
field @NonNull public static final android.os.ParcelUuid NAP;
field @NonNull public static final android.os.ParcelUuid OBEX_OBJECT_PUSH;
@@ -2352,6 +2354,7 @@ package android.content {
field public static final String TETHERING_SERVICE = "tethering";
field public static final String TRANSLATION_MANAGER_SERVICE = "translation";
field public static final String UI_TRANSLATION_SERVICE = "ui_translation";
+ field public static final String UWB_SERVICE = "uwb";
field public static final String VR_SERVICE = "vrmanager";
field public static final String WIFI_NL80211_SERVICE = "wifinl80211";
field @Deprecated public static final String WIFI_RTT_SERVICE = "rttmanager";
@@ -2831,6 +2834,9 @@ package android.content.pm {
field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
field public static final int RESTRICTION_NONE = 0; // 0x0
+ field public static final int ROLLBACK_DATA_POLICY_RESTORE = 0; // 0x0
+ field public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; // 0x2
+ field public static final int ROLLBACK_DATA_POLICY_WIPE = 1; // 0x1
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0
field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1
field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2
@@ -5583,11 +5589,7 @@ package android.media.session {
public final class MediaSessionManager {
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventDispatchedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void addOnMediaKeyEventSessionChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
- method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.media.session.MediaSession.Token getMediaKeyEventSession();
- method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public String getMediaKeyEventSessionPackageName();
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventDispatchedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventDispatchedListener);
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void removeOnMediaKeyEventSessionChangedListener(@NonNull android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener);
method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
}
@@ -5596,10 +5598,6 @@ package android.media.session {
method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token);
}
- public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener {
- method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token);
- }
-
public static interface MediaSessionManager.OnMediaKeyListener {
method public boolean onMediaKey(android.view.KeyEvent);
}
@@ -6020,6 +6018,7 @@ package android.media.tv.tuner {
method public static int getTunerVersion();
field public static final int TUNER_VERSION_1_0 = 65536; // 0x10000
field public static final int TUNER_VERSION_1_1 = 65537; // 0x10001
+ field public static final int TUNER_VERSION_2_0 = 131072; // 0x20000
field public static final int TUNER_VERSION_UNKNOWN = 0; // 0x0
}
@@ -7028,13 +7027,13 @@ package android.media.tv.tuner.frontend {
field public static final long FEC_23_36 = 268435456L; // 0x10000000L
field public static final long FEC_25_36 = 536870912L; // 0x20000000L
field public static final long FEC_26_45 = 1073741824L; // 0x40000000L
- field public static final long FEC_28_45 = -2147483648L; // 0xffffffff80000000L
- field public static final long FEC_29_45 = 1L; // 0x1L
+ field public static final long FEC_28_45 = 2147483648L; // 0x80000000L
+ field public static final long FEC_29_45 = 4294967296L; // 0x100000000L
field public static final long FEC_2_3 = 32L; // 0x20L
field public static final long FEC_2_5 = 64L; // 0x40L
field public static final long FEC_2_9 = 128L; // 0x80L
- field public static final long FEC_31_45 = 2L; // 0x2L
- field public static final long FEC_32_45 = 4L; // 0x4L
+ field public static final long FEC_31_45 = 8589934592L; // 0x200000000L
+ field public static final long FEC_32_45 = 17179869184L; // 0x400000000L
field public static final long FEC_3_4 = 256L; // 0x100L
field public static final long FEC_3_5 = 512L; // 0x200L
field public static final long FEC_4_15 = 2048L; // 0x800L
@@ -7042,7 +7041,7 @@ package android.media.tv.tuner.frontend {
field public static final long FEC_5_6 = 4096L; // 0x1000L
field public static final long FEC_5_9 = 8192L; // 0x2000L
field public static final long FEC_6_7 = 16384L; // 0x4000L
- field public static final long FEC_77_90 = 8L; // 0x8L
+ field public static final long FEC_77_90 = 34359738368L; // 0x800000000L
field public static final long FEC_7_15 = 131072L; // 0x20000L
field public static final long FEC_7_8 = 32768L; // 0x8000L
field public static final long FEC_7_9 = 65536L; // 0x10000L
@@ -9126,6 +9125,7 @@ package android.provider {
field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
+ field public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native";
field public static final String NAMESPACE_LOCATION = "location";
field public static final String NAMESPACE_MEDIA = "media";
field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
@@ -14265,148 +14265,6 @@ package android.util {
}
-package android.uwb {
-
- public final class AngleMeasurement implements android.os.Parcelable {
- ctor public AngleMeasurement(@FloatRange(from=-3.141592653589793, to=3.141592653589793) double, @FloatRange(from=0.0, to=3.141592653589793) double, @FloatRange(from=0.0, to=1.0) double);
- method public int describeContents();
- method @FloatRange(from=0.0, to=1.0) public double getConfidenceLevel();
- method @FloatRange(from=0.0, to=3.141592653589793) public double getErrorRadians();
- method @FloatRange(from=-3.141592653589793, to=3.141592653589793) public double getRadians();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.AngleMeasurement> CREATOR;
- }
-
- public final class AngleOfArrivalMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.uwb.AngleMeasurement getAltitude();
- method @NonNull public android.uwb.AngleMeasurement getAzimuth();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.AngleOfArrivalMeasurement> CREATOR;
- }
-
- public static final class AngleOfArrivalMeasurement.Builder {
- ctor public AngleOfArrivalMeasurement.Builder(@NonNull android.uwb.AngleMeasurement);
- method @NonNull public android.uwb.AngleOfArrivalMeasurement build();
- method @NonNull public android.uwb.AngleOfArrivalMeasurement.Builder setAltitude(@NonNull android.uwb.AngleMeasurement);
- }
-
- public final class DistanceMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0, to=1.0) public double getConfidenceLevel();
- method @FloatRange(from=0.0) public double getErrorMeters();
- method public double getMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.DistanceMeasurement> CREATOR;
- }
-
- public static final class DistanceMeasurement.Builder {
- ctor public DistanceMeasurement.Builder();
- method @NonNull public android.uwb.DistanceMeasurement build();
- method @NonNull public android.uwb.DistanceMeasurement.Builder setConfidenceLevel(@FloatRange(from=0.0, to=1.0) double);
- method @NonNull public android.uwb.DistanceMeasurement.Builder setErrorMeters(@FloatRange(from=0.0) double);
- method @NonNull public android.uwb.DistanceMeasurement.Builder setMeters(double);
- }
-
- public final class RangingMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.uwb.AngleOfArrivalMeasurement getAngleOfArrivalMeasurement();
- method @Nullable public android.uwb.DistanceMeasurement getDistanceMeasurement();
- method public long getElapsedRealtimeNanos();
- method @NonNull public android.uwb.UwbAddress getRemoteDeviceAddress();
- method public int getStatus();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.RangingMeasurement> CREATOR;
- field public static final int RANGING_STATUS_FAILURE_OUT_OF_RANGE = 1; // 0x1
- field public static final int RANGING_STATUS_FAILURE_UNKNOWN_ERROR = -1; // 0xffffffff
- field public static final int RANGING_STATUS_SUCCESS = 0; // 0x0
- }
-
- public static final class RangingMeasurement.Builder {
- ctor public RangingMeasurement.Builder();
- method @NonNull public android.uwb.RangingMeasurement build();
- method @NonNull public android.uwb.RangingMeasurement.Builder setAngleOfArrivalMeasurement(@NonNull android.uwb.AngleOfArrivalMeasurement);
- method @NonNull public android.uwb.RangingMeasurement.Builder setDistanceMeasurement(@NonNull android.uwb.DistanceMeasurement);
- method @NonNull public android.uwb.RangingMeasurement.Builder setElapsedRealtimeNanos(long);
- method @NonNull public android.uwb.RangingMeasurement.Builder setRemoteDeviceAddress(@NonNull android.uwb.UwbAddress);
- method @NonNull public android.uwb.RangingMeasurement.Builder setStatus(int);
- }
-
- public final class RangingReport implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.uwb.RangingMeasurement> getMeasurements();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.RangingReport> CREATOR;
- }
-
- public static final class RangingReport.Builder {
- ctor public RangingReport.Builder();
- method @NonNull public android.uwb.RangingReport.Builder addMeasurement(@NonNull android.uwb.RangingMeasurement);
- method @NonNull public android.uwb.RangingReport.Builder addMeasurements(@NonNull java.util.List<android.uwb.RangingMeasurement>);
- method @NonNull public android.uwb.RangingReport build();
- }
-
- public final class RangingSession implements java.lang.AutoCloseable {
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void close();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void reconfigure(@NonNull android.os.PersistableBundle);
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void start(@NonNull android.os.PersistableBundle);
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void stop();
- }
-
- public static interface RangingSession.Callback {
- method public void onClosed(int, @NonNull android.os.PersistableBundle);
- method public void onOpenFailed(int, @NonNull android.os.PersistableBundle);
- method public void onOpened(@NonNull android.uwb.RangingSession);
- method public void onReconfigureFailed(int, @NonNull android.os.PersistableBundle);
- method public void onReconfigured(@NonNull android.os.PersistableBundle);
- method public void onReportReceived(@NonNull android.uwb.RangingReport);
- method public void onStartFailed(int, @NonNull android.os.PersistableBundle);
- method public void onStarted(@NonNull android.os.PersistableBundle);
- method public void onStopFailed(int, @NonNull android.os.PersistableBundle);
- method public void onStopped(int, @NonNull android.os.PersistableBundle);
- field public static final int REASON_BAD_PARAMETERS = 3; // 0x3
- field public static final int REASON_GENERIC_ERROR = 4; // 0x4
- field public static final int REASON_LOCAL_REQUEST = 1; // 0x1
- field public static final int REASON_MAX_SESSIONS_REACHED = 5; // 0x5
- field public static final int REASON_PROTOCOL_SPECIFIC_ERROR = 7; // 0x7
- field public static final int REASON_REMOTE_REQUEST = 2; // 0x2
- field public static final int REASON_SYSTEM_POLICY = 6; // 0x6
- field public static final int REASON_UNKNOWN = 0; // 0x0
- }
-
- public final class UwbAddress implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public static android.uwb.UwbAddress fromBytes(@NonNull byte[]);
- method public int size();
- method @NonNull public byte[] toBytes();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.uwb.UwbAddress> CREATOR;
- field public static final int EXTENDED_ADDRESS_BYTE_LENGTH = 8; // 0x8
- field public static final int SHORT_ADDRESS_BYTE_LENGTH = 2; // 0x2
- }
-
- public final class UwbManager {
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos();
- method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo();
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.UWB_PRIVILEGED, android.Manifest.permission.UWB_RANGING}) public android.os.CancellationSignal openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback);
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback);
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback);
- }
-
- public static interface UwbManager.AdapterStateCallback {
- method public void onStateChanged(int, int);
- field public static final int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1; // 0x1
- field public static final int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4; // 0x4
- field public static final int STATE_CHANGED_REASON_SESSION_STARTED = 0; // 0x0
- field public static final int STATE_CHANGED_REASON_SYSTEM_BOOT = 3; // 0x3
- field public static final int STATE_CHANGED_REASON_SYSTEM_POLICY = 2; // 0x2
- field public static final int STATE_DISABLED = 0; // 0x0
- field public static final int STATE_ENABLED_ACTIVE = 2; // 0x2
- field public static final int STATE_ENABLED_INACTIVE = 1; // 0x1
- }
-
-}
-
package android.view {
public abstract class Window {
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 3a883d8ebfc1..427bbd82f561 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -323,6 +323,23 @@ aidl_interface {
},
}
+aidl_interface {
+ name: "android.debug_aidl",
+ unstable: true,
+ srcs: [
+ "android/debug/AdbTransportType.aidl",
+ "android/debug/FingerprintAndPairDevice.aidl",
+ "android/debug/IAdbCallback.aidl",
+ "android/debug/IAdbManager.aidl",
+ "android/debug/PairDevice.aidl",
+ ],
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ },
+}
+
// Avoid including Parcelable classes as we don't want to have two copies of
// Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
// and TeleService app (packages/services/Telephony).
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 7145c0fe35bf..b80c4b4d7f88 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -36,6 +36,7 @@ import android.os.PowerExemptionManager.TempAllowListType;
import android.os.TransactionTooLargeException;
import android.os.WorkSource;
import android.util.ArraySet;
+import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
@@ -84,6 +85,18 @@ public abstract class ActivityManagerInternal {
public static final int ALLOW_ALL_PROFILE_PERMISSIONS_IN_PROFILE = 3;
/**
+ * Returns profile information in free form string in two separate strings.
+ * See AppProfiler for the output format.
+ * The output can only be used for human consumption. The format may change
+ * in the future.
+ * Do not call it frequently.
+ * @param time uptime for the cpu state
+ * @param lines lines of the cpu state should be returned
+ * @return a pair of Strings. The first is the current cpu load, the second is the cpu state.
+ */
+ public abstract Pair<String, String> getAppProfileStatsForDebugging(long time, int lines);
+
+ /**
* Verify that calling app has access to the given provider.
*/
public abstract String checkContentProviderAccess(String authority, @UserIdInt int userId);
@@ -412,6 +425,13 @@ public abstract class ActivityManagerInternal {
public abstract void inputDispatchingResumed(int pid);
/**
+ * User tapped "wait" in the ANR dialog - reschedule the dialog to be shown again at a later
+ * time.
+ * @param data AppNotRespondingDialog.Data object
+ */
+ public abstract void rescheduleAnrDialog(Object data);
+
+ /**
* Sends {@link android.content.Intent#ACTION_CONFIGURATION_CHANGED} with all the appropriate
* flags.
*/
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 8e1f263ebf03..76f873185267 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -215,6 +215,14 @@ public class ActivityOptions {
"android.activity.launchRootTaskToken";
/**
+ * The {@link com.android.server.wm.TaskFragment} token the activity should be launched into.
+ * @see #setLaunchTaskFragmentToken(IBinder)
+ * @hide
+ */
+ public static final String KEY_LAUNCH_TASK_FRAGMENT_TOKEN =
+ "android.activity.launchTaskFragmentToken";
+
+ /**
* The windowing mode the activity should be launched into.
* @hide
*/
@@ -396,6 +404,7 @@ public class ActivityOptions {
private int mCallerDisplayId = INVALID_DISPLAY;
private WindowContainerToken mLaunchTaskDisplayArea;
private WindowContainerToken mLaunchRootTask;
+ private IBinder mLaunchTaskFragmentToken;
@WindowConfiguration.WindowingMode
private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
@WindowConfiguration.ActivityType
@@ -1138,6 +1147,7 @@ public class ActivityOptions {
mCallerDisplayId = opts.getInt(KEY_CALLER_DISPLAY_ID, INVALID_DISPLAY);
mLaunchTaskDisplayArea = opts.getParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN);
mLaunchRootTask = opts.getParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN);
+ mLaunchTaskFragmentToken = opts.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN);
mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
@@ -1473,6 +1483,17 @@ public class ActivityOptions {
}
/** @hide */
+ public IBinder getLaunchTaskFragmentToken() {
+ return mLaunchTaskFragmentToken;
+ }
+
+ /** @hide */
+ public ActivityOptions setLaunchTaskFragmentToken(IBinder taskFragmentToken) {
+ mLaunchTaskFragmentToken = taskFragmentToken;
+ return this;
+ }
+
+ /** @hide */
public int getLaunchWindowingMode() {
return mLaunchWindowingMode;
}
@@ -1882,6 +1903,9 @@ public class ActivityOptions {
if (mLaunchRootTask != null) {
b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask);
}
+ if (mLaunchTaskFragmentToken != null) {
+ b.putBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN, mLaunchTaskFragmentToken);
+ }
if (mLaunchWindowingMode != WINDOWING_MODE_UNDEFINED) {
b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7d70441c1cd2..ae812ece4c98 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -530,8 +530,9 @@ public final class ActivityThread extends ClientTransactionHandler
// A reusable token for other purposes, e.g. content capture, translation. It shouldn't be
// used without security checks
public IBinder shareableActivityToken;
- // The token of the TaskFragment that embedded this activity.
- @Nullable public IBinder mTaskFragmentToken;
+ // The token of the initial TaskFragment that embedded this activity. Do not rely on it
+ // after creation because the activity could be reparented.
+ @Nullable public IBinder mInitialTaskFragmentToken;
int ident;
@UnsupportedAppUsage
Intent intent;
@@ -626,7 +627,7 @@ public final class ActivityThread extends ClientTransactionHandler
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
IBinder shareableActivityToken, boolean launchedFromBubble,
- IBinder taskFragmentToken) {
+ IBinder initialTaskFragmentToken) {
this.token = token;
this.assistToken = assistToken;
this.shareableActivityToken = shareableActivityToken;
@@ -648,7 +649,7 @@ public final class ActivityThread extends ClientTransactionHandler
mActivityOptions = activityOptions;
mPendingFixedRotationAdjustments = fixedRotationAdjustments;
mLaunchedFromBubble = launchedFromBubble;
- mTaskFragmentToken = taskFragmentToken;
+ mInitialTaskFragmentToken = initialTaskFragmentToken;
init();
}
@@ -5666,8 +5667,8 @@ public final class ActivityThread extends ClientTransactionHandler
*/
private void scheduleRelaunchActivityIfPossible(@NonNull ActivityClientRecord r,
boolean preserveWindow) {
- if (r.activity.mFinished || r.token instanceof Binder) {
- // Do not schedule relaunch if the activity is finishing or not a local object (e.g.
+ if ((r.activity != null && r.activity.mFinished) || r.token instanceof Binder) {
+ // Do not schedule relaunch if the activity is finishing or is a local object (e.g.
// created by ActivtiyGroup that server side doesn't recognize it).
return;
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index bb7cdfa1a1ea..d932a29beca6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7205,6 +7205,34 @@ public class AppOpsManager {
* @hide
*/
public interface OnOpStartedListener {
+
+ /**
+ * Represents a start operation that was unsuccessful
+ * @hide
+ */
+ public int START_TYPE_FAILED = 0;
+
+ /**
+ * Represents a successful start operation
+ * @hide
+ */
+ public int START_TYPE_STARTED = 1;
+
+ /**
+ * Represents an operation where a restricted operation became unrestricted, and resumed.
+ * @hide
+ */
+ public int START_TYPE_RESUMED = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ START_TYPE_FAILED,
+ START_TYPE_STARTED,
+ START_TYPE_RESUMED
+ })
+ public @interface StartedType {}
+
/**
* Called when an op was started.
*
@@ -7213,11 +7241,35 @@ public class AppOpsManager {
* @param uid The UID performing the operation.
* @param packageName The package performing the operation.
* @param attributionTag The attribution tag performing the operation.
- * @param flags The flags of this op
+ * @param flags The flags of this op.
* @param result The result of the start.
*/
void onOpStarted(int op, int uid, String packageName, String attributionTag,
@OpFlags int flags, @Mode int result);
+
+ /**
+ * Called when an op was started.
+ *
+ * Note: This is only for op starts. It is not called when an op is noted or stopped.
+ * By default, unless this method is overridden, no code will be executed for resume
+ * events.
+ * @param op The op code.
+ * @param uid The UID performing the operation.
+ * @param packageName The package performing the operation.
+ * @param attributionTag The attribution tag performing the operation.
+ * @param flags The flags of this op.
+ * @param result The result of the start.
+ * @param startType The start type of this start event. Either failed, resumed, or started.
+ * @param attributionFlags The location of this started op in an attribution chain.
+ * @param attributionChainId The ID of the attribution chain of this op, if it is in one.
+ */
+ default void onOpStarted(int op, int uid, String packageName, String attributionTag,
+ @OpFlags int flags, @Mode int result, @StartedType int startType,
+ @AttributionFlags int attributionFlags, int attributionChainId) {
+ if (startType != START_TYPE_RESUMED) {
+ onOpStarted(op, uid, packageName, attributionTag, flags, result);
+ }
+ }
}
AppOpsManager(Context context, IAppOpsService service) {
@@ -7858,8 +7910,10 @@ public class AppOpsManager {
cb = new IAppOpsStartedCallback.Stub() {
@Override
public void opStarted(int op, int uid, String packageName, String attributionTag,
- int flags, int mode) {
- callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode);
+ int flags, int mode, int startType, int attributionFlags,
+ int attributionChainId) {
+ callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode,
+ startType, attributionFlags, attributionChainId);
}
};
mStartedWatchers.put(callback, cb);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index b81a8d3a41f0..7e4f9b406375 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1014,17 +1014,13 @@ public class ApplicationPackageManager extends PackageManager {
}
}
@Override
- protected boolean bypass(Integer uid) {
- return uid < 0;
- }
- @Override
public String queryToString(Integer uid) {
return String.format("uid=%d", uid.intValue());
}
};
@Override
- public String[] getPackagesForUid(@UserIdInt int uid) {
+ public String[] getPackagesForUid(int uid) {
return mGetPackagesForUidCache.query(uid).value();
}
@@ -1039,7 +1035,7 @@ public class ApplicationPackageManager extends PackageManager {
}
@Override
- public String getNameForUid(@UserIdInt int uid) {
+ public String getNameForUid(int uid) {
try {
return mPM.getNameForUid(uid);
} catch (RemoteException e) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7114d73ae168..d0acacf20a89 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2260,7 +2260,7 @@ class ContextImpl extends Context {
int modeFlags) {
try {
return ActivityManager.getService().checkUriPermissions(uris, pid, uid, modeFlags,
- null);
+ getUserId(), null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index b90b9a11611e..6b738fff1eee 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -221,7 +221,7 @@ interface IActivityManager {
int getProcessLimit();
int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId,
in IBinder callerToken);
- int[] checkUriPermissions(in List<Uri> uris, int pid, int uid, int mode,
+ int[] checkUriPermissions(in List<Uri> uris, int pid, int uid, int mode, int userId,
in IBinder callerToken);
void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
int mode, int userId);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index b2184fe65887..fd6589ceadaa 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -743,6 +743,17 @@ public class Instrumentation {
}
/**
+ * This overload is used for notifying the {@link android.window.TaskFragmentOrganizer}
+ * implementation internally about started activities.
+ *
+ * @see #onStartActivity(Intent)
+ * @hide
+ */
+ public ActivityResult onStartActivity(Context who, Intent intent, Bundle options) {
+ return onStartActivity(intent);
+ }
+
+ /**
* Used for intercepting any started activity.
*
* <p> A non-null return value here will be considered a hit for this monitor.
@@ -1722,7 +1733,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intent, options);
}
if (result != null) {
am.mHits++;
@@ -1790,7 +1804,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intents[0]);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intents[0], options);
}
if (result != null) {
am.mHits++;
@@ -1861,7 +1878,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intent, options);
}
if (result != null) {
am.mHits++;
@@ -1928,7 +1948,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intent, options);
}
if (result != null) {
am.mHits++;
@@ -1974,7 +1997,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intent, options);
}
if (result != null) {
am.mHits++;
@@ -2021,7 +2047,10 @@ public class Instrumentation {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
- result = am.onStartActivity(intent);
+ if (options == null) {
+ options = ActivityOptions.makeBasic().toBundle();
+ }
+ result = am.onStartActivity(who, intent, options);
}
if (result != null) {
am.mHits++;
@@ -2083,7 +2112,8 @@ public class Instrumentation {
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
- + "; have you declared this activity in your AndroidManifest.xml?");
+ + "; have you declared this activity in your AndroidManifest.xml"
+ + ", or does your intent not match its declared <intent-filter>?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 7cb1d89aa954..0145747e0c65 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -312,29 +312,25 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
private static final String TAG = "Service";
/**
- * Flag for {@link #stopForeground(int)}: if set, the notification previously provided
- * to {@link #startForeground} will be removed. Otherwise it will remain
- * until a later call (to {@link #startForeground(int, Notification)} or
- * {@link #stopForeground(int)} removes it, or the service is destroyed.
+ * Selector for {@link #stopForeground(int)}: if supplied, the notification previously
+ * supplied to {@link #startForeground} will be cancelled and removed from display.
*/
public static final int STOP_FOREGROUND_REMOVE = 1<<0;
/**
- * Flag for {@link #stopForeground(int)}: if set, the notification previously provided
- * to {@link #startForeground} will be detached from the service. Only makes sense
- * when {@link #STOP_FOREGROUND_REMOVE} is <b>not</b> set -- in this case, the notification
- * will remain shown, but be completely detached from the service and so no longer changed
- * except through direct calls to the notification manager.
+ * Selector for {@link #stopForeground(int)}: if set, the notification previously supplied
+ * to {@link #startForeground} will be detached from the service's lifecycle. The notification
+ * will remain shown even after the service is stopped and destroyed.
*/
public static final int STOP_FOREGROUND_DETACH = 1<<1;
/** @hide */
- @IntDef(flag = true, prefix = { "STOP_FOREGROUND_" }, value = {
+ @IntDef(flag = false, prefix = { "STOP_FOREGROUND_" }, value = {
STOP_FOREGROUND_REMOVE,
STOP_FOREGROUND_DETACH
})
@Retention(RetentionPolicy.SOURCE)
- public @interface StopForegroundFlags {}
+ public @interface StopForegroundSelector {}
public Service() {
super(null);
@@ -387,6 +383,13 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
* <p>This mode makes sense for things that will be explicitly started
* and stopped to run for arbitrary periods of time, such as a service
* performing background music playback.
+ *
+ * <p>Since Android version {@link Build.VERSION_CODES#S}, apps
+ * targeting {@link Build.VERSION_CODES#S} or above are disallowed
+ * to start a foreground service from the background, but the restriction
+ * doesn't impact <em>restarts</em> of a sticky foreground service. However,
+ * when apps start a sticky foreground service from the background,
+ * the same restriction still applies.
*/
public static final int START_STICKY = 1;
@@ -784,12 +787,16 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
}
/**
- * Synonym for {@link #stopForeground(int)}.
- * @param removeNotification If true, the {@link #STOP_FOREGROUND_REMOVE} flag
- * will be supplied.
+ * Legacy version of {@link #stopForeground(int)}.
+ * @param removeNotification If true, the {@link #STOP_FOREGROUND_REMOVE}
+ * selector will be passed to {@link #stopForeground(int)}; otherwise
+ * {@code zero} will be passed.
* @see #stopForeground(int)
* @see #startForeground(int, Notification)
+ *
+ * @deprecated use {@link #stopForeground(int)} instead.
*/
+ @Deprecated
public final void stopForeground(boolean removeNotification) {
stopForeground(removeNotification ? STOP_FOREGROUND_REMOVE : 0);
}
@@ -800,14 +807,29 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
* you use {@link #stopSelf()} or related methods), just takes it out of the
* foreground state.
*
- * @param flags additional behavior options.
+ * <p>If {@link #STOP_FOREGROUND_REMOVE} is supplied, the service's associated
+ * notification will be cancelled immediately.</p>
+ * <p>If {@link #STOP_FOREGROUND_DETACH} is supplied, the service's association
+ * with the notification will be severed. If the notification had not yet been
+ * shown, due to foreground-service notification deferral policy, it is
+ * immediately posted when {@code stopForeground(STOP_FOREGROUND_DETACH)}
+ * is called. In all cases, the notification remains shown
+ * even after this service is stopped fully and destroyed.</p>
+ * <p>If {@code zero} is passed as the argument, the result will be the legacy
+ * behavior as defined prior to Android L: the notification will remain posted until
+ * the service is fully stopped, at which time it will automatically be cancelled.</p>
+ *
+ * @param notificationBehavior the intended behavior for the service's associated
+ * notification
* @see #startForeground(int, Notification)
+ * @see #STOP_FOREGROUND_DETACH
+ * @see #STOP_FOREGROUND_REMOVE
*/
- public final void stopForeground(@StopForegroundFlags int flags) {
+ public final void stopForeground(@StopForegroundSelector int notificationBehavior) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, 0, null,
- flags, 0);
+ notificationBehavior, 0);
} catch (RemoteException ex) {
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 32ea41b2c75f..8ac8229042ad 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -205,7 +205,7 @@ import android.telephony.TelephonyRegistryManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
-import android.uwb.UwbManager;
+import android.uwb.UwbFrameworkInitializer;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.WindowManager;
@@ -728,14 +728,6 @@ public final class SystemServiceRegistry {
return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));
}});
- registerService(Context.UWB_SERVICE, UwbManager.class,
- new CachedServiceFetcher<UwbManager>() {
- @Override
- public UwbManager createService(ContextImpl ctx) {
- return UwbManager.getInstance(ctx);
- }
- });
-
registerService(Context.VIBRATOR_MANAGER_SERVICE, VibratorManager.class,
new CachedServiceFetcher<VibratorManager>() {
@Override
@@ -1486,6 +1478,7 @@ public final class SystemServiceRegistry {
MediaFrameworkInitializer.registerServiceWrappers();
RoleFrameworkInitializer.registerServiceWrappers();
SchedulingFrameworkInitializer.registerServiceWrappers();
+ UwbFrameworkInitializer.registerServiceWrappers();
} finally {
// If any of the above code throws, we're in a pretty bad shape and the process
// will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 27db25de7173..4b401a5150de 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10596,11 +10596,16 @@ public class DevicePolicyManager {
* behavior of this API is changed such that passing {@code null} as the {@code admin} parameter
* will return if any admin has blocked the uninstallation. Before L MR1, passing {@code null}
* will cause a NullPointerException to be raised.
+ * <p>
+ * <strong>Note:</strong> If your app targets Android 11 (API level 30) or higher,
+ * this method returns a filtered result. Learn more about how to
+ * <a href="/training/basics/intents/package-visibility">manage package visibility</a>.
*
* @param admin The name of the admin component whose blocking policy will be checked, or
* {@code null} to check whether any admin has blocked the uninstallation.
* @param packageName package to check.
- * @return true if uninstallation is blocked.
+ * @return true if uninstallation is blocked and the given package is visible to you, false
+ * otherwise if uninstallation isn't blocked or the given package isn't visible to you.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
@@ -13736,8 +13741,6 @@ public class DevicePolicyManager {
*
* It is recommended that the Enterprise ID is at least 6 characters long, and no more than
* 64 characters.
- * This API is supposed to be called only after the boot phase is complete,
- * throws {@link IllegalStateException} if called before boot phase is complete.
*
* @param enterpriseId An identifier of the organization this work profile or device is
* enrolled into.
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 1b03f2f328e5..bf9a9b060b6b 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -116,7 +116,7 @@ public class FullBackup {
ConfigSection.CLOUD_BACKUP,
ConfigSection.DEVICE_TRANSFER
})
- private @interface ConfigSection {
+ @interface ConfigSection {
String CLOUD_BACKUP = "cloud-backup";
String DEVICE_TRANSFER = "device-transfer";
}
@@ -528,7 +528,8 @@ public class FullBackup {
return mExcludes;
}
- private synchronized int getRequiredTransportFlags()
+ @VisibleForTesting
+ public synchronized int getRequiredTransportFlags()
throws IOException, XmlPullParserException {
if (mRequiredTransportFlags == null) {
maybeParseBackupSchemeLocked();
@@ -587,11 +588,13 @@ public class FullBackup {
if (mDataExtractionRules != 0) {
// New config is present. Use it if it has configuration for this operation
// type.
+ boolean isSectionPresent;
try (XmlResourceParser parser = getParserForResource(mDataExtractionRules)) {
- parseNewBackupSchemeFromXmlLocked(parser, configSection, mExcludes, mIncludes);
+ isSectionPresent = parseNewBackupSchemeFromXmlLocked(parser, configSection,
+ mExcludes, mIncludes);
}
- if (!mExcludes.isEmpty() || !mIncludes.isEmpty()) {
- // Found configuration in the new config, we will use it.
+ if (isSectionPresent) {
+ // Found the relevant section in the new config, we will use it.
mIsUsingNewScheme = true;
return;
}
@@ -630,24 +633,31 @@ public class FullBackup {
.getXml(resourceId);
}
- private void parseNewBackupSchemeFromXmlLocked(XmlPullParser parser,
+ @VisibleForTesting
+ public boolean parseNewBackupSchemeFromXmlLocked(XmlPullParser parser,
@ConfigSection String configSection,
Set<PathWithRequiredFlags> excludes,
Map<String, Set<PathWithRequiredFlags>> includes)
throws IOException, XmlPullParserException {
verifyTopLevelTag(parser, "data-extraction-rules");
+ boolean isSectionPresent = false;
+
int event;
while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event != XmlPullParser.START_TAG || !configSection.equals(parser.getName())) {
continue;
}
+ isSectionPresent = true;
+
parseRequiredTransportFlags(parser, configSection);
parseRules(parser, excludes, includes, Optional.of(0), configSection);
}
logParsingResults(excludes, includes);
+
+ return isSectionPresent;
}
private void parseRequiredTransportFlags(XmlPullParser parser,
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 17a3e48e5d91..65cdc83a9e8f 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -108,6 +108,9 @@ public final class BluetoothGatt implements BluetoothProfile {
/** A read or write operation was requested with an invalid offset */
public static final int GATT_INVALID_OFFSET = 0x7;
+ /** Insufficient authorization for a given operation */
+ public static final int GATT_INSUFFICIENT_AUTHORIZATION = 0x8;
+
/** A write operation exceeds the maximum length of the attribute */
public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 0xd;
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 83a272fce311..5b67a75a2b43 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -220,12 +220,19 @@ public interface BluetoothProfile {
int VOLUME_CONTROL = 23;
/**
+ * @hide
+ * Media Control Profile server
+ *
+ */
+ int MCP_SERVER = 24;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- int MAX_PROFILE_ID = 23;
+ int MAX_PROFILE_ID = 24;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index bc3754a2fc56..ff250e63cc85 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -174,6 +174,16 @@ public final class BluetoothUuid {
/** @hide */
@NonNull
@SystemApi
+ public static final ParcelUuid GENERIC_MEDIA_CONTROL =
+ ParcelUuid.fromString("00001849-0000-1000-8000-00805F9B34FB");
+ /** @hide */
+ @NonNull
+ @SystemApi
+ public static final ParcelUuid MEDIA_CONTROL =
+ ParcelUuid.fromString("00001848-0000-1000-8000-00805F9B34FB");
+ /** @hide */
+ @NonNull
+ @SystemApi
public static final ParcelUuid BASE_UUID =
ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a741f9649b4c..c714f507242e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -745,9 +745,6 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
if (Binder.getCallingPid() == Process.myPid()) {
return PermissionChecker.PERMISSION_GRANTED;
}
- if (!attributionSource.checkCallingUid()) {
- return PermissionChecker.PERMISSION_HARD_DENIED;
- }
return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(getContext(),
permission, -1, new AttributionSource(getContext().getAttributionSource(),
attributionSource), /*message*/ null);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ac88c7bdcb18..31a84ed72ecd 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3301,6 +3301,12 @@ public abstract class Context {
* to startService() are not counted -- this stops the service no matter
* how many times it was started.
*
+ * <p>If the service is running as a foreground service when it is
+ * stopped, its associated notification will be removed. To avoid this,
+ * apps can use {@link android.app.Service#stopForeground(int)
+ * stopForeground(STOP_FOREGROUND_DETACH)} to decouple the notification
+ * from the service's lifecycle before stopping it.</p>
+ *
* <p>Note that if a stopped service still has {@link ServiceConnection}
* objects bound to it with the {@link #BIND_AUTO_CREATE} set, it will
* not be destroyed until all of these bindings are removed. See
@@ -5606,6 +5612,7 @@ public abstract class Context {
* @see #getSystemService(String)
* @hide
*/
+ @SystemApi
public static final String UWB_SERVICE = "uwb";
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e109ae558ea2..846349d8be77 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1866,7 +1866,7 @@ public class Intent implements Parcelable, Cloneable {
* that should be managed by the launched UI.
* </p>
* <p>
- * <li> {@link #EXTRA_USER} specifies the UserHandle of the user that owns the app.
+ * <li> {@link #EXTRA_USER} specifies the {@link UserHandle} of the user that owns the app.
* </p>
* <p>
* Output: Nothing.
@@ -2850,8 +2850,8 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
/**
- * Broadcast Action: A user ID has been removed from the system. The user
- * ID number is stored in the extra data under {@link #EXTRA_UID}.
+ * Broadcast Action: A uid has been removed from the system. The uid
+ * number is stored in the extra data under {@link #EXTRA_UID}.
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
@@ -3726,10 +3726,12 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.USER_BACKGROUND";
/**
- * Broadcast sent to the system when a user is added. Carries an extra
- * EXTRA_USER_HANDLE that has the userHandle of the new user. It is sent to
- * all running users. You must hold
- * {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
+ * Broadcast sent to the system when a user is added.
+ * Carries an extra {@link #EXTRA_USER} that specifies the {@link UserHandle} of the new user
+ * (and for legacy reasons, also carries an int extra {@link #EXTRA_USER_HANDLE} specifying that
+ * user's user ID).
+ * It is sent to all running users.
+ * You must hold {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
* @hide
*/
@SystemApi
@@ -3738,7 +3740,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent by the system when a user is started. Carries an extra
- * {@link EXTRA_USER_HANDLE} that has the userHandle of the user. This is only sent to
+ * {@link #EXTRA_USER_HANDLE} that has the user ID of the user. This is only sent to
* registered receivers, not manifest receivers. It is sent to the user
* that has been started. This is sent as a foreground
* broadcast, since it is part of a visible user interaction; be as quick
@@ -3750,7 +3752,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent when a user is in the process of starting. Carries an extra
- * {@link EXTRA_USER_HANDLE} that has the userHandle of the user. This is only
+ * {@link #EXTRA_USER_HANDLE} that has the user ID of the user. This is only
* sent to registered receivers, not manifest receivers. It is sent to all
* users (including the one that is being started). You must hold
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS} to receive
@@ -3767,7 +3769,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent when a user is going to be stopped. Carries an extra
- * {@link EXTRA_USER_HANDLE} that has the userHandle of the user. This is only
+ * {@link #EXTRA_USER_HANDLE} that has the user ID of the user. This is only
* sent to registered receivers, not manifest receivers. It is sent to all
* users (including the one that is being stopped). You must hold
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS} to receive
@@ -3785,7 +3787,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent to the system when a user is stopped. Carries an extra
- * {@link EXTRA_USER_HANDLE} that has the userHandle of the user. This is similar to
+ * {@link #EXTRA_USER_HANDLE} that has the user ID of the user. This is similar to
* {@link #ACTION_PACKAGE_RESTARTED}, but for an entire user instead of a
* specific package. This is only sent to registered receivers, not manifest
* receivers. It is sent to all running users <em>except</em> the one that
@@ -3797,8 +3799,12 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.USER_STOPPED";
/**
- * Broadcast sent to the system when a user is removed. Carries an extra EXTRA_USER_HANDLE that has
- * the userHandle of the user. It is sent to all running users except the
+ * Broadcast sent to the system when a user is removed.
+ * Carries an extra {@link #EXTRA_USER} that specifies the {@link UserHandle} of the user that
+ * was removed
+ * (and for legacy reasons, also carries an int extra {@link #EXTRA_USER_HANDLE} specifying that
+ * user's user ID).
+ * It is sent to all running users except the
* one that has been removed. The user will not be completely removed until all receivers have
* handled the broadcast. You must hold
* {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
@@ -3809,9 +3815,13 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.USER_REMOVED";
/**
- * Broadcast sent to the system when the user switches. Carries an extra EXTRA_USER_HANDLE that has
- * the userHandle of the user to become the current one. This is only sent to
- * registered receivers, not manifest receivers. It is sent to all running users.
+ * Broadcast sent to the system when the user switches.
+ * Carries an extra {@link #EXTRA_USER} that specifies the {@link UserHandle}
+ * of the user to become the current one
+ * (and for legacy reasons, also carries an int extra {@link #EXTRA_USER_HANDLE} specifying that
+ * user's user ID).
+ * This is only sent to registered receivers, not manifest receivers.
+ * It is sent to all running users.
* You must hold
* {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
* @hide
@@ -3840,17 +3850,18 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent to the primary user when an associated managed profile is added (the profile
* was created and is ready to be used). Carries an extra {@link #EXTRA_USER} that specifies
- * the UserHandle of the profile that was added. Only applications (for example Launchers)
- * that need to display merged content across both primary and managed profiles need to
- * worry about this broadcast. This is only sent to registered receivers,
+ * the {@link UserHandle} of the profile that was added. Only applications (for example
+ * Launchers) that need to display merged content across both primary and managed profiles need
+ * to worry about this broadcast. This is only sent to registered receivers,
* not manifest receivers.
*/
public static final String ACTION_MANAGED_PROFILE_ADDED =
"android.intent.action.MANAGED_PROFILE_ADDED";
/**
- * Broadcast sent to the primary user when an associated managed profile is removed. Carries an
- * extra {@link #EXTRA_USER} that specifies the UserHandle of the profile that was removed.
+ * Broadcast sent to the primary user when an associated managed profile is removed.
+ * Carries an extra {@link #EXTRA_USER} that specifies the {@link UserHandle} of the profile
+ * that was removed.
* Only applications (for example Launchers) that need to display merged content across both
* primary and managed profiles need to worry about this broadcast. This is only sent to
* registered receivers, not manifest receivers.
@@ -3861,9 +3872,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent to the primary user when the credential-encrypted private storage for
* an associated managed profile is unlocked. Carries an extra {@link #EXTRA_USER} that
- * specifies the UserHandle of the profile that was unlocked. Only applications (for example
- * Launchers) that need to display merged content across both primary and managed profiles
- * need to worry about this broadcast. This is only sent to registered receivers,
+ * specifies the {@link UserHandle} of the profile that was unlocked. Only applications (for
+ * example Launchers) that need to display merged content across both primary and managed
+ * profiles need to worry about this broadcast. This is only sent to registered receivers,
* not manifest receivers.
*/
public static final String ACTION_MANAGED_PROFILE_UNLOCKED =
@@ -3872,9 +3883,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent to the primary user when an associated managed profile has become available.
* Currently this includes when the user disables quiet mode for the profile. Carries an extra
- * {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
- * this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
- * of quiet mode. This is only sent to registered receivers, not manifest receivers.
+ * {@link #EXTRA_USER} that specifies the {@link UserHandle} of the profile. When quiet mode is
+ * changed, this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the
+ * new state of quiet mode. This is only sent to registered receivers, not manifest receivers.
*/
public static final String ACTION_MANAGED_PROFILE_AVAILABLE =
"android.intent.action.MANAGED_PROFILE_AVAILABLE";
@@ -3882,9 +3893,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast sent to the primary user when an associated managed profile has become unavailable.
* Currently this includes when the user enables quiet mode for the profile. Carries an extra
- * {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
- * this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
- * of quiet mode. This is only sent to registered receivers, not manifest receivers.
+ * {@link #EXTRA_USER} that specifies the {@link UserHandle} of the profile. When quiet mode is
+ * changed, this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the
+ * new state of quiet mode. This is only sent to registered receivers, not manifest receivers.
*/
public static final String ACTION_MANAGED_PROFILE_UNAVAILABLE =
"android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
@@ -5339,7 +5350,7 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
/**
- * An int representing the user id to be used.
+ * An int representing the user ID to be used.
*
* @hide
*/
@@ -5933,7 +5944,7 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.ALLOW_MULTIPLE";
/**
- * The integer userHandle (i.e. userId) carried with broadcast intents related to addition,
+ * The user ID integer carried with broadcast intents related to addition,
* removal and switching of users and managed profiles - {@link #ACTION_USER_ADDED},
* {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}.
*
@@ -5943,7 +5954,7 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.user_handle";
/**
- * The UserHandle carried with intents.
+ * The {@link UserHandle} carried with intents.
*/
public static final String EXTRA_USER =
"android.intent.extra.USER";
@@ -9418,7 +9429,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* This is NOT a secure mechanism to identify the user who sent the intent.
- * When the intent is sent to a different user, it is used to fix uris by adding the userId
+ * When the intent is sent to a different user, it is used to fix uris by adding the user ID
* who sent the intent.
* @hide
*/
@@ -11371,8 +11382,17 @@ public class Intent implements Parcelable, Cloneable {
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void prepareToLeaveProcess(Context context) {
- final boolean leavingPackage = (mComponent == null)
- || !Objects.equals(mComponent.getPackageName(), context.getPackageName());
+ final boolean leavingPackage;
+ if (mComponent != null) {
+ leavingPackage = !Objects.equals(mComponent.getPackageName(), context.getPackageName());
+ } else if (mPackage != null) {
+ leavingPackage = !Objects.equals(mPackage, context.getPackageName());
+ } else {
+ // When no specific component or package has been defined, we have
+ // to assume that we might be routed through an intent
+ // disambiguation dialog which might leave our package
+ leavingPackage = true;
+ }
prepareToLeaveProcess(leavingPackage);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3f8aedb31ea9..c2a65d5bf85d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1616,7 +1616,7 @@ public class PackageInstaller {
/** {@hide} */
public DataLoaderParams dataLoaderParams;
/** {@hide} */
- public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
+ public int rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
/** {@hide} */
public boolean forceQueryableOverride;
/** {@hide} */
@@ -1887,7 +1887,7 @@ public class PackageInstaller {
} else {
installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
}
- rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
+ rollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cd02aed67084..a5cd331de4ff 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1053,26 +1053,37 @@ public abstract class PackageManager {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- RollbackDataPolicy.RESTORE,
- RollbackDataPolicy.WIPE,
- RollbackDataPolicy.RETAIN
+ @IntDef(prefix = { "ROLLBACK_DATA_POLICY_" }, value = {
+ ROLLBACK_DATA_POLICY_RESTORE,
+ ROLLBACK_DATA_POLICY_WIPE,
+ ROLLBACK_DATA_POLICY_RETAIN
})
- public @interface RollbackDataPolicy {
- /**
- * User data will be backed up during install and restored during rollback.
- */
- int RESTORE = 0;
- /**
- * User data won't be backed up during install but will be wiped out during rollback.
- */
- int WIPE = 1;
- /**
- * User data won't be backed up during install and won't be restored during rollback.
- * TODO: Not implemented yet.
- */
- int RETAIN = 2;
- }
+ public @interface RollbackDataPolicy {}
+
+ /**
+ * User data will be backed up during install and restored during rollback.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ROLLBACK_DATA_POLICY_RESTORE = 0;
+
+ /**
+ * User data won't be backed up during install but will be wiped out during rollback.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ROLLBACK_DATA_POLICY_WIPE = 1;
+
+ /**
+ * User data won't be backed up during install and won't be restored during rollback.
+ * TODO: Not implemented yet.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ROLLBACK_DATA_POLICY_RETAIN = 2;
/** @hide */
@IntDef(flag = true, prefix = { "INSTALL_" }, value = {
@@ -9096,7 +9107,6 @@ public abstract class PackageManager {
private static final class ApplicationInfoQuery {
final String packageName;
final int flags;
- @UserIdInt
final int userId;
ApplicationInfoQuery(@Nullable String packageName, int flags, int userId) {
@@ -9158,10 +9168,6 @@ public abstract class PackageManager {
query.packageName, query.flags, query.userId);
}
@Override
- protected boolean bypass(ApplicationInfoQuery query) {
- return query.userId < 0;
- }
- @Override
protected ApplicationInfo maybeCheckConsistency(
ApplicationInfoQuery query, ApplicationInfo proposedResult) {
// Implementing this debug check for ApplicationInfo would require a
@@ -9172,7 +9178,7 @@ public abstract class PackageManager {
/** @hide */
public static ApplicationInfo getApplicationInfoAsUserCached(
- String packageName, int flags, @UserIdInt int userId) {
+ String packageName, int flags, int userId) {
return sApplicationInfoCache.query(
new ApplicationInfoQuery(packageName, flags, userId));
}
@@ -9204,7 +9210,6 @@ public abstract class PackageManager {
private static final class PackageInfoQuery {
final String packageName;
final int flags;
- @UserIdInt
final int userId;
PackageInfoQuery(@Nullable String packageName, int flags, int userId) {
@@ -9265,10 +9270,6 @@ public abstract class PackageManager {
query.packageName, query.flags, query.userId);
}
@Override
- protected boolean bypass(PackageInfoQuery query) {
- return query.userId < 0;
- }
- @Override
protected PackageInfo maybeCheckConsistency(
PackageInfoQuery query, PackageInfo proposedResult) {
// Implementing this debug check for PackageInfo would require a
@@ -9279,7 +9280,7 @@ public abstract class PackageManager {
/** @hide */
public static PackageInfo getPackageInfoAsUserCached(
- String packageName, int flags, @UserIdInt int userId) {
+ String packageName, int flags, int userId) {
return sPackageInfoCache.query(new PackageInfoQuery(packageName, flags, userId));
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bed03835707f..29ce3971e83a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -55,6 +55,8 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.overlay.OverlayPaths;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.split.SplitAssetLoader;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.res.ApkAssets;
@@ -7425,7 +7427,7 @@ public class PackageParser {
mCompileSdkVersionCodename = dest.readString();
mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
- mKeySetMapping = readKeySetMapping(dest);
+ mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest);
cpuAbiOverride = dest.readString();
use32bitAbi = (dest.readInt() == 1);
@@ -7551,73 +7553,13 @@ public class PackageParser {
dest.writeInt(mCompileSdkVersion);
dest.writeString(mCompileSdkVersionCodename);
dest.writeArraySet(mUpgradeKeySets);
- writeKeySetMapping(dest, mKeySetMapping);
+ ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping);
dest.writeString(cpuAbiOverride);
dest.writeInt(use32bitAbi ? 1 : 0);
dest.writeByteArray(restrictUpdateHash);
dest.writeInt(visibleToInstantApps ? 1 : 0);
}
- /**
- * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
- */
- private static void writeKeySetMapping(
- Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
- if (keySetMapping == null) {
- dest.writeInt(-1);
- return;
- }
-
- final int N = keySetMapping.size();
- dest.writeInt(N);
-
- for (int i = 0; i < N; i++) {
- dest.writeString(keySetMapping.keyAt(i));
- ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
- if (keys == null) {
- dest.writeInt(-1);
- continue;
- }
-
- final int M = keys.size();
- dest.writeInt(M);
- for (int j = 0; j < M; j++) {
- dest.writeSerializable(keys.valueAt(j));
- }
- }
- }
-
- /**
- * Reads a keyset mapping from the given parcel at the given data position. May return
- * {@code null} if the serialized mapping was {@code null}.
- */
- private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
- final int N = in.readInt();
- if (N == -1) {
- return null;
- }
-
- ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
- for (int i = 0; i < N; ++i) {
- String key = in.readString();
- final int M = in.readInt();
- if (M == -1) {
- keySetMapping.put(key, null);
- continue;
- }
-
- ArraySet<PublicKey> keys = new ArraySet<>(M);
- for (int j = 0; j < M; ++j) {
- PublicKey pk = (PublicKey) in.readSerializable();
- keys.add(pk);
- }
-
- keySetMapping.put(key, keys);
- }
-
- return keySetMapping;
- }
-
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
public Package createFromParcel(Parcel in) {
return new Package(in);
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index 9fee7bb92490..f2a6a5c9382f 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -535,7 +535,7 @@ public class PackageInfoWithoutStateUtils {
ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
Float minAspectRatio = a.getMinAspectRatio();
ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
- ai.supportsSizeChanges = a.getSupportsSizeChanges();
+ ai.supportsSizeChanges = a.isSupportsSizeChanges();
ai.requestedVrComponent = a.getRequestedVrComponent();
ai.rotationAnimation = a.getRotationAnimation();
ai.colorMode = a.getColorMode();
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 72cc9299376a..d6e1ac903c42 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -360,7 +360,7 @@ public interface ParsingPackage extends ParsingPackageRead {
ParsingPackage setCompileSdkVersion(int compileSdkVersion);
- ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
+ ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName);
ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 0db65467c686..f0d95d97263a 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -553,7 +553,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
setCompileSdkVersion(manifestArray.getInteger(
R.styleable.AndroidManifest_compileSdkVersion, 0));
- setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
+ setCompileSdkVersionCodeName(manifestArray.getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
setIsolatedSplitLoading(manifestArray.getBoolean(
@@ -2686,8 +2686,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
}
@Override
- public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
- this.compileSdkVersionCodeName = compileSdkVersionCodename;
+ public ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName) {
+ this.compileSdkVersionCodeName = compileSdkVersionCodeName;
return this;
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
index 73ee13212e90..adb6b76473eb 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivity.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
@@ -423,6 +424,7 @@ public class ParsedActivity extends ParsedMainComponent {
}
}
+ @NonNull
public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
@Override
public ParsedActivity createFromParcel(Parcel source) {
@@ -513,10 +515,6 @@ public class ParsedActivity extends ParsedMainComponent {
return minAspectRatio;
}
- public boolean getSupportsSizeChanges() {
- return supportsSizeChanges;
- }
-
@Nullable
public String getRequestedVrComponent() {
return requestedVrComponent;
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
index 3c0f097285ca..838adfd3215e 100644
--- a/core/java/android/content/pm/parsing/component/ParsedComponent.java
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -43,8 +43,8 @@ import java.util.Map;
/** @hide */
public abstract class ParsedComponent implements Parcelable {
- private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
- ParsedIntentInfo.ListParceler.class);
+ private static final ParsedIntentInfo.ListParceler sForIntentInfos =
+ Parcelling.Cache.getOrCreate(ParsedIntentInfo.ListParceler.class);
@NonNull
@DataClass.ParcelWith(ForInternedString.class)
diff --git a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
index 65ff4720063b..41789204a76d 100644
--- a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
+++ b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -94,6 +95,7 @@ public class ParsedInstrumentation extends ParsedComponent {
this.functionalTest = in.readByte() != 0;
}
+ @NonNull
public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
new Parcelable.Creator<ParsedInstrumentation>() {
@Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
index 01ee0f4828f9..59d4a95edb0a 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.IntentFilter;
import android.os.Parcel;
@@ -58,6 +59,7 @@ public final class ParsedIntentInfo extends IntentFilter {
item.writeIntentInfoToParcel(dest, parcelFlags);
}
+ @NonNull
@Override
public ParsedIntentInfo unparcel(Parcel source) {
return new ParsedIntentInfo(source);
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermission.java b/core/java/android/content/pm/parsing/component/ParsedPermission.java
index 50bc3d98fb2a..0f82941f92b1 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermission.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermission.java
@@ -16,6 +16,7 @@
package android.content.pm.parsing.component;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PermissionInfo;
import android.os.Parcel;
@@ -167,6 +168,7 @@ public class ParsedPermission extends ParsedComponent {
this.knownCerts = sForStringSet.unparcel(in);
}
+ @NonNull
public static final Parcelable.Creator<ParsedPermission> CREATOR =
new Parcelable.Creator<ParsedPermission>() {
@Override
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcess.java b/core/java/android/content/pm/parsing/component/ParsedProcess.java
index c39d6b1d3250..fe102252931e 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcess.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcess.java
@@ -19,7 +19,6 @@ package android.content.pm.parsing.component;
import static java.util.Collections.emptySet;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/content/pm/parsing/component/ParsedProvider.java b/core/java/android/content/pm/parsing/component/ParsedProvider.java
index ebf85f71d282..9a12b48cffb0 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProvider.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProvider.java
@@ -169,6 +169,7 @@ public class ParsedProvider extends ParsedMainComponent {
this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
}
+ @NonNull
public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
@Override
public ParsedProvider createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/parsing/component/ParsedService.java b/core/java/android/content/pm/parsing/component/ParsedService.java
index 471d3468a084..5499a130a4ad 100644
--- a/core/java/android/content/pm/parsing/component/ParsedService.java
+++ b/core/java/android/content/pm/parsing/component/ParsedService.java
@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Parcel;
@@ -83,6 +84,7 @@ public class ParsedService extends ParsedMainComponent {
this.permission = sForInternedString.unparcel(in);
}
+ @NonNull
public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
@Override
public ParsedService createFromParcel(Parcel source) {
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 0140280cd3d5..8df7c37f313b 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -180,7 +180,7 @@ public final class PackageRollbackInfo implements Parcelable {
@NonNull List<Integer> pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
boolean isApex, boolean isApkInApex, @NonNull List<Integer> snapshottedUsers) {
this(packageRolledBackFrom, packageRolledBackTo, pendingBackups, pendingRestores, isApex,
- isApkInApex, snapshottedUsers, PackageManager.RollbackDataPolicy.RESTORE);
+ isApkInApex, snapshottedUsers, PackageManager.ROLLBACK_DATA_POLICY_RESTORE);
}
/** @hide */
@@ -207,7 +207,7 @@ public final class PackageRollbackInfo implements Parcelable {
this.mPendingRestores = null;
this.mPendingBackups = null;
this.mSnapshottedUsers = null;
- this.mRollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
+ this.mRollbackDataPolicy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;
}
@Override
diff --git a/core/java/android/uwb/UwbAddress.aidl b/core/java/android/debug/FingerprintAndPairDevice.aidl
index a202b1a1f51d..b439e14282e7 100644
--- a/core/java/android/uwb/UwbAddress.aidl
+++ b/core/java/android/debug/FingerprintAndPairDevice.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 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,6 +14,15 @@
* limitations under the License.
*/
-package android.uwb;
+package android.debug;
-parcelable UwbAddress;
+import android.debug.PairDevice;
+
+/**
+ * @see {@link android.debug.IAdbManager#getPairedDevices()}
+ * @hide
+ */
+parcelable FingerprintAndPairDevice {
+ String keyFingerprint;
+ PairDevice device;
+} \ No newline at end of file
diff --git a/core/java/android/uwb/MeasurementStatus.aidl b/core/java/android/debug/IAdbCallback.aidl
index 5fa15549e84d..9c8f1cfac527 100644
--- a/core/java/android/uwb/MeasurementStatus.aidl
+++ b/core/java/android/debug/IAdbCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 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,26 +14,18 @@
* limitations under the License.
*/
-package android.uwb;
+package android.debug;
+
+import android.debug.AdbTransportType;
/**
+ * Callback interface of {@link android.debug.IAdbCallbackManager}.
+ *
* @hide
*/
-@Backing(type="int")
-enum MeasurementStatus {
- /**
- * Ranging was successful
- */
- SUCCESS,
-
- /**
- * The remote device is out of range
- */
- FAILURE_OUT_OF_RANGE,
-
- /**
- * An unknown failure has occurred.
- */
- FAILURE_UNKNOWN,
+oneway interface IAdbCallback {
+ /**
+ * On debugging enabled, service providing IAdbManager calls this function.
+ */
+ void onDebuggingChanged(boolean enabled, AdbTransportType type);
}
-
diff --git a/core/java/android/debug/IAdbManager.aidl b/core/java/android/debug/IAdbManager.aidl
index aea7633d91dc..314c4058dd06 100644
--- a/core/java/android/debug/IAdbManager.aidl
+++ b/core/java/android/debug/IAdbManager.aidl
@@ -16,6 +16,9 @@
package android.debug;
+import android.debug.FingerprintAndPairDevice;
+import android.debug.IAdbCallback;
+
/**
* Interface to communicate remotely with the {@code AdbService} in the system server.
*
@@ -58,9 +61,10 @@ interface IAdbManager {
void denyWirelessDebugging();
/**
- * Returns a Map<String, PairDevice> with the key fingerprint mapped to the device information.
+ * Returns an array of NamedPairDevice with the key fingerprint mapped to the device
+ * information.
*/
- Map getPairedDevices();
+ FingerprintAndPairDevice[] getPairedDevices();
/**
* Unpair the device identified by the key fingerprint it uses.
@@ -108,4 +112,14 @@ interface IAdbManager {
* QR code.
*/
boolean isAdbWifiQrSupported();
+
+ /**
+ * Register callback for ADB debugging changed notification.
+ */
+ void registerCallback(IAdbCallback callback);
+
+ /**
+ * Unregister callback for ADB debugging changed notification.
+ */
+ void unregisterCallback(IAdbCallback callback);
}
diff --git a/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl b/core/java/android/debug/PairDevice.aidl
index d3b34c632bcc..c72a5ede3bd4 100644
--- a/core/java/android/uwb/IUwbAdapterStateCallbacks.aidl
+++ b/core/java/android/debug/PairDevice.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 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,26 @@
* limitations under the License.
*/
-package android.uwb;
-
-import android.uwb.StateChangeReason;
-import android.uwb.AdapterState;
+package android.debug;
/**
+ * Contains information about the client in an ADB connection.
+ * @see {@link android.debug.IAdbManager#getPairedDevices()}
* @hide
*/
-interface IUwbAdapterStateCallbacks {
- /**
- * Called whenever the adapter state changes
- *
- * @param state UWB state; enabled_active, enabled_inactive, or disabled.
- * @param reason the reason that the state has changed
+parcelable PairDevice {
+ /**
+ * The human-readable name of the device.
+ */
+ String name;
+
+ /**
+ * The device's guid.
+ */
+ String guid;
+
+ /**
+ * Indicates whether the device is currently connected to adbd.
*/
- void onAdapterStateChanged(AdapterState state, StateChangeReason reason);
+ boolean connected;
} \ No newline at end of file
diff --git a/core/java/android/debug/PairDevice.java b/core/java/android/debug/PairDevice.java
deleted file mode 100644
index 2d5b446b4f8f..000000000000
--- a/core/java/android/debug/PairDevice.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.debug;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.Immutable;
-import com.android.internal.util.Preconditions;
-
-/**
- * Contains information about the client in an ADB connection.
- * @hide
- */
-@Immutable
-public class PairDevice implements Parcelable {
- /**
- * The human-readable name of the device.
- */
- @NonNull private final String mName;
-
- /**
- * The device's guid.
- */
- @NonNull private final String mGuid;
-
- /**
- * Indicates whether the device is currently connected to adbd.
- */
- private final boolean mConnected;
-
- public PairDevice(@NonNull String name, @NonNull String guid, boolean connected) {
- Preconditions.checkStringNotEmpty(name);
- Preconditions.checkStringNotEmpty(guid);
- mName = name;
- mGuid = guid;
- mConnected = connected;
- }
-
- /**
- * @return the device name.
- */
- @NonNull
- public String getDeviceName() {
- return mName;
- }
-
- /**
- * @return the device GUID.
- */
- @NonNull
- public String getGuid() {
- return mGuid;
- }
-
- /**
- * @return the adb connection state of the device.
- */
- public boolean isConnected() {
- return mConnected;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mName);
- dest.writeString(mGuid);
- dest.writeBoolean(mConnected);
- }
-
- /**
- * @return Human-readable info about the object.
- */
- @Override
- public String toString() {
- return "\n" + mName + "\n" + mGuid + "\n" + mConnected;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<PairDevice> CREATOR =
- new Creator<PairDevice>() {
- @Override
- public PairDevice createFromParcel(Parcel source) {
- return new PairDevice(source.readString(), source.readString(),
- source.readBoolean());
- }
-
- @Override
- public PairDevice[] newArray(int size) {
- return new PairDevice[size];
- }
- };
-}
diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl
index d69a9e14b4bf..55711654231e 100644
--- a/core/java/android/hardware/ISensorPrivacyManager.aidl
+++ b/core/java/android/hardware/ISensorPrivacyManager.aidl
@@ -52,4 +52,6 @@ interface ISensorPrivacyManager {
void addUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener);
void removeUserGlobalIndividualSensorPrivacyListener(int sensor, in ISensorPrivacyListener listener);
+
+ void showSensorUseDialog(int sensor);
} \ No newline at end of file
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index fa7ce11c5414..3c524b2052f7 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -33,6 +33,7 @@ import android.os.UserHandle;
import android.service.SensorPrivacyIndividualEnabledSensorProto;
import android.service.SensorPrivacyToggleSourceProto;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -48,6 +49,8 @@ import java.util.concurrent.Executor;
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {
+ private static final String LOG_TAG = SensorPrivacyManager.class.getSimpleName();
+
/**
* Unique Id of this manager to identify to the service
* @hide
@@ -505,6 +508,25 @@ public final class SensorPrivacyManager {
}
/**
+ * If sensor privacy for the provided sensor is enabled then this call will show the user the
+ * dialog which is shown when an application attempts to use that sensor. If privacy isn't
+ * enabled then this does nothing.
+ *
+ * This call can only be made by the system uid.
+ *
+ * @throws SecurityException when called by someone other than system uid.
+ *
+ * @hide
+ */
+ public void showSensorUseDialog(int sensor) {
+ try {
+ mService.showSensorUseDialog(sensor);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Received exception while trying to show sensor use dialog", e);
+ }
+ }
+
+ /**
* A class implementing this interface can register with the {@link
* android.hardware.SensorPrivacyManager} to receive notification when the all-sensor privacy
* state changes.
diff --git a/core/java/android/hardware/camera2/MultiResolutionImageReader.java b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
index 3af1b5b03d35..0dbf29de5253 100644
--- a/core/java/android/hardware/camera2/MultiResolutionImageReader.java
+++ b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
@@ -91,7 +91,7 @@ public class MultiResolutionImageReader implements AutoCloseable {
* </p>
* <p>
* The {@code maxImages} parameter determines the maximum number of
- * {@link Image} objects that can be be acquired from each of the {@code ImageReader}
+ * {@link Image} objects that can be acquired from each of the {@code ImageReader}
* within the {@code MultiResolutionImageReader}. However, requesting more buffers will
* use up more memory, so it is important to use only the minimum number necessary. The
* application is strongly recommended to acquire no more than {@code maxImages} images
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index d5a35bc31e68..02245e49e611 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -446,16 +446,12 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
}
- @Override
- protected void finalize() throws Throwable {
- if (mHandlerThread != null) {
- mHandlerThread.quitSafely();
- }
- super.finalize();
- }
+ public void release(boolean skipCloseNotification) {
+ boolean notifyClose = false;
- public void release() {
synchronized (mInterfaceLock) {
+ mHandlerThread.quitSafely();
+
if (mSessionProcessor != null) {
try {
mSessionProcessor.deInitSession();
@@ -469,6 +465,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
if (mExtensionClientId >= 0) {
CameraExtensionCharacteristics.unregisterClient(mExtensionClientId);
if (mInitialized) {
+ notifyClose = true;
CameraExtensionCharacteristics.releaseSession();
}
}
@@ -482,6 +479,16 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
mClientRepeatingRequestSurface = null;
mClientCaptureSurface = null;
}
+
+ if (notifyClose && !skipCloseNotification) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallbacks.onClosed(
+ CameraAdvancedExtensionSessionImpl.this));
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
private void notifyConfigurationFailure() {
@@ -491,7 +498,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
}
- release();
+ release(true /*skipCloseNotification*/);
final long ident = Binder.clearCallingIdentity();
try {
@@ -507,15 +514,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
android.hardware.camera2.CameraCaptureSession.StateCallback {
@Override
public void onClosed(@NonNull CameraCaptureSession session) {
- release();
-
- final long ident = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallbacks.onClosed(
- CameraAdvancedExtensionSessionImpl.this));
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ release(false /*skipCloseNotification*/);
}
@Override
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 0bf812e03984..fc728a22ed5a 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -697,12 +697,12 @@ public class CameraDeviceImpl extends CameraDevice
}
if (mCurrentExtensionSession != null) {
- mCurrentExtensionSession.release();
+ mCurrentExtensionSession.release(false /*skipCloseNotification*/);
mCurrentExtensionSession = null;
}
if (mCurrentAdvancedExtensionSession != null) {
- mCurrentAdvancedExtensionSession.release();
+ mCurrentAdvancedExtensionSession.release(false /*skipCloseNotification*/);
mCurrentAdvancedExtensionSession = null;
}
@@ -1352,12 +1352,12 @@ public class CameraDeviceImpl extends CameraDevice
}
if (mCurrentExtensionSession != null) {
- mCurrentExtensionSession.release();
+ mCurrentExtensionSession.release(true /*skipCloseNotification*/);
mCurrentExtensionSession = null;
}
if (mCurrentAdvancedExtensionSession != null) {
- mCurrentAdvancedExtensionSession.release();
+ mCurrentAdvancedExtensionSession.release(true /*skipCloseNotification*/);
mCurrentAdvancedExtensionSession = null;
}
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 7d29a7d275cf..ecd24914c566 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -630,18 +630,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
new CameraExtensionUtils.HandlerExecutor(mHandler), requestHandler);
}
- @Override
- protected void finalize() throws Throwable {
- if (mHandlerThread != null) {
- mHandlerThread.quitSafely();
- }
- super.finalize();
- }
-
/** @hide */
- public void release() {
+ public void release(boolean skipCloseNotification) {
+ boolean notifyClose = false;
+
synchronized (mInterfaceLock) {
mInternalRepeatingRequestEnabled = false;
+ mHandlerThread.quitSafely();
try {
mPreviewExtender.onDeInit();
@@ -654,6 +649,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
if (mExtensionClientId >= 0) {
CameraExtensionCharacteristics.unregisterClient(mExtensionClientId);
if (mInitialized) {
+ notifyClose = true;
CameraExtensionCharacteristics.releaseSession();
}
}
@@ -704,6 +700,15 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
mCameraRepeatingSurface = mClientRepeatingRequestSurface = null;
mCameraBurstSurface = mClientCaptureSurface = null;
}
+
+ if (notifyClose && !skipCloseNotification) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallbacks.onClosed(CameraExtensionSessionImpl.this));
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
}
private void notifyConfigurationFailure() {
@@ -713,7 +718,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
}
}
- release();
+ release(true /*skipCloseNotification*/);
final long ident = Binder.clearCallingIdentity();
try {
@@ -745,14 +750,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
android.hardware.camera2.CameraCaptureSession.StateCallback {
@Override
public void onClosed(@NonNull CameraCaptureSession session) {
- release();
-
- final long ident = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(() -> mCallbacks.onClosed(CameraExtensionSessionImpl.this));
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ release(false /*skipCloseNotification*/);
}
@Override
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
index 9acf9bf0c803..afefcbe80bf1 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
@@ -75,7 +75,7 @@ public final class CameraExtensionUtils {
ImageWriter writer = null;
Image img = null;
SurfaceInfo surfaceInfo = new SurfaceInfo();
- int nativeFormat = SurfaceUtils.getSurfaceFormat(s);
+ int nativeFormat = SurfaceUtils.detectSurfaceFormat(s);
int dataspace = SurfaceUtils.getSurfaceDataspace(s);
Size surfaceSize = SurfaceUtils.getSurfaceSize(s);
surfaceInfo.mFormat = nativeFormat;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 8fd9a6abf7b6..196134b397cb 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1720,21 +1720,21 @@ public class CameraMetadataNative implements Parcelable {
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAWBRegions((MeteringRectangle[]) value);
+ metadata.setAWBRegions(value);
}
});
sSetCommandMap.put(CaptureRequest.CONTROL_AF_REGIONS.getNativeKey(),
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAFRegions((MeteringRectangle[]) value);
+ metadata.setAFRegions(value);
}
});
sSetCommandMap.put(CaptureRequest.CONTROL_AE_REGIONS.getNativeKey(),
new SetCommand() {
@Override
public <T> void setValue(CameraMetadataNative metadata, T value) {
- metadata.setAERegions((MeteringRectangle[]) value);
+ metadata.setAERegions(value);
}
});
}
@@ -1815,30 +1815,33 @@ public class CameraMetadataNative implements Parcelable {
return true;
}
- private <T> boolean setAFRegions(MeteringRectangle[] afRegions) {
+ private <T> boolean setAFRegions(T afRegions) {
if (afRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AF_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
+ // The cast to CaptureRequest.Key is needed since java does not support template
+ // specialization and we need to route this method to
+ // setBase(CaptureRequest.Key<T> key, T value)
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AF_REGIONS, afRegions);
return true;
}
- private <T> boolean setAERegions(MeteringRectangle[] aeRegions) {
+ private <T> boolean setAERegions(T aeRegions) {
if (aeRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AE_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
return true;
}
- private <T> boolean setAWBRegions(MeteringRectangle[] awbRegions) {
+ private <T> boolean setAWBRegions(T awbRegions) {
if (awbRegions == null) {
return false;
}
setBase(CaptureRequest.CONTROL_AWB_REGIONS_SET, true);
- setBase(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
+ setBase((CaptureRequest.Key)CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
return true;
}
diff --git a/core/java/android/hardware/camera2/params/InputConfiguration.java b/core/java/android/hardware/camera2/params/InputConfiguration.java
index 8dfc0a7b41ca..70c85a1fb26c 100644
--- a/core/java/android/hardware/camera2/params/InputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/InputConfiguration.java
@@ -42,7 +42,7 @@ public final class InputConfiguration {
private final boolean mIsMultiResolution;
/**
- * Create an input configration with the width, height, and user-defined format.
+ * Create an input configuration with the width, height, and user-defined format.
*
* <p>Images of a user-defined format are accessible by applications. Use
* {@link android.hardware.camera2.CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP}
@@ -64,7 +64,7 @@ public final class InputConfiguration {
}
/**
- * Create an input configration with the format and a list of multi-resolution input stream
+ * Create an input configuration with the format and a list of multi-resolution input stream
* info.
*
* <p>Use {@link
@@ -108,7 +108,7 @@ public final class InputConfiguration {
}
/**
- * Get the width of this input configration.
+ * Get the width of this input configuration.
*
* @return width of this input configuration.
*/
@@ -117,7 +117,7 @@ public final class InputConfiguration {
}
/**
- * Get the height of this input configration.
+ * Get the height of this input configuration.
*
* @return height of this input configuration.
*/
@@ -126,7 +126,7 @@ public final class InputConfiguration {
}
/**
- * Get the format of this input configration.
+ * Get the format of this input configuration.
*
* @return format of this input configuration.
*/
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 57d8ded79e8e..fd1a33161740 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -160,6 +160,23 @@ public class SurfaceUtils {
}
/**
+ * Detect and retrieve the Surface format without any
+ * additional overrides.
+ *
+ * @param surface The surface to be queried for format.
+ * @return format of the surface.
+ *
+ * @throws IllegalArgumentException if the surface is already abandoned.
+ */
+ public static int detectSurfaceFormat(Surface surface) {
+ checkNotNull(surface);
+ int surfaceType = nativeDetectSurfaceType(surface);
+ if (surfaceType == BAD_VALUE) throw new IllegalArgumentException("Surface was abandoned");
+
+ return surfaceType;
+ }
+
+ /**
* Get the Surface dataspace.
*
* @param surface The surface to be queried for dataspace.
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index abcc33c43c74..4f205530ef0d 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.graphics.Point;
import android.hardware.SensorManager;
import android.os.Handler;
+import android.os.IBinder;
import android.os.PowerManager;
import android.util.IntArray;
import android.util.Slog;
@@ -340,6 +341,28 @@ public abstract class DisplayManagerInternal {
public abstract List<RefreshRateLimitation> getRefreshRateLimitations(int displayId);
/**
+ * Returns the window token of the level of the WindowManager hierarchy to mirror. Returns null
+ * if layer mirroring by SurfaceFlinger should not be performed for the given displayId.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ public abstract IBinder getWindowTokenClientToMirror(int displayId);
+
+ /**
+ * For the given displayId, updates the window token of the level of the WindowManager hierarchy
+ * to mirror. If windowToken is null, then SurfaceFlinger performs no layer mirroring to the
+ * given display.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ public abstract void setWindowTokenClientToMirror(int displayId, IBinder windowToken);
+
+ /**
+ * Returns the default size of the surface associated with the display, or null if the surface
+ * is not provided for layer mirroring by SurfaceFlinger.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ public abstract Point getDisplaySurfaceDefaultSize(int displayId);
+
+ /**
* 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/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index 71688c7cc7e8..0e86f43207aa 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.media.projection.MediaProjection;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.Surface;
@@ -91,9 +92,16 @@ public final class VirtualDisplayConfig implements Parcelable {
*/
private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+ /**
+ * The window token of the level of the WindowManager hierarchy to mirror, or null if mirroring
+ * should not be performed.
+ */
+ @Nullable
+ private IBinder mWindowTokenClientToMirror = null;
- // Code below generated by codegen v1.0.20.
+
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -115,7 +123,8 @@ public final class VirtualDisplayConfig implements Parcelable {
int flags,
@Nullable Surface surface,
@Nullable String uniqueId,
- int displayIdToMirror) {
+ int displayIdToMirror,
+ @Nullable IBinder windowTokenClientToMirror) {
this.mName = name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mName);
@@ -135,6 +144,7 @@ public final class VirtualDisplayConfig implements Parcelable {
this.mSurface = surface;
this.mUniqueId = uniqueId;
this.mDisplayIdToMirror = displayIdToMirror;
+ this.mWindowTokenClientToMirror = windowTokenClientToMirror;
// onConstructed(); // You can define this method to get a callback
}
@@ -212,6 +222,15 @@ public final class VirtualDisplayConfig implements Parcelable {
return mDisplayIdToMirror;
}
+ /**
+ * The window token of the level of the WindowManager hierarchy to mirror, or null if mirroring
+ * should not be performed.
+ */
+ @DataClass.Generated.Member
+ public @Nullable IBinder getWindowTokenClientToMirror() {
+ return mWindowTokenClientToMirror;
+ }
+
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -221,6 +240,7 @@ public final class VirtualDisplayConfig implements Parcelable {
int flg = 0;
if (mSurface != null) flg |= 0x20;
if (mUniqueId != null) flg |= 0x40;
+ if (mWindowTokenClientToMirror != null) flg |= 0x100;
dest.writeInt(flg);
dest.writeString(mName);
dest.writeInt(mWidth);
@@ -230,6 +250,7 @@ public final class VirtualDisplayConfig implements Parcelable {
if (mSurface != null) dest.writeTypedObject(mSurface, flags);
if (mUniqueId != null) dest.writeString(mUniqueId);
dest.writeInt(mDisplayIdToMirror);
+ if (mWindowTokenClientToMirror != null) dest.writeStrongBinder(mWindowTokenClientToMirror);
}
@Override
@@ -252,6 +273,7 @@ public final class VirtualDisplayConfig implements Parcelable {
Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
int displayIdToMirror = in.readInt();
+ IBinder windowTokenClientToMirror = (flg & 0x100) == 0 ? null : (IBinder) in.readStrongBinder();
this.mName = name;
com.android.internal.util.AnnotationValidations.validate(
@@ -272,6 +294,7 @@ public final class VirtualDisplayConfig implements Parcelable {
this.mSurface = surface;
this.mUniqueId = uniqueId;
this.mDisplayIdToMirror = displayIdToMirror;
+ this.mWindowTokenClientToMirror = windowTokenClientToMirror;
// onConstructed(); // You can define this method to get a callback
}
@@ -305,6 +328,7 @@ public final class VirtualDisplayConfig implements Parcelable {
private @Nullable Surface mSurface;
private @Nullable String mUniqueId;
private int mDisplayIdToMirror;
+ private @Nullable IBinder mWindowTokenClientToMirror;
private long mBuilderFieldsSet = 0L;
@@ -439,10 +463,22 @@ public final class VirtualDisplayConfig implements Parcelable {
return this;
}
+ /**
+ * The window token of the level of the WindowManager hierarchy to mirror, or null if mirroring
+ * should not be performed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setWindowTokenClientToMirror(@NonNull IBinder value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x100;
+ mWindowTokenClientToMirror = value;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull VirtualDisplayConfig build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x100; // Mark builder used
+ mBuilderFieldsSet |= 0x200; // Mark builder used
if ((mBuilderFieldsSet & 0x10) == 0) {
mFlags = 0;
@@ -456,6 +492,9 @@ public final class VirtualDisplayConfig implements Parcelable {
if ((mBuilderFieldsSet & 0x80) == 0) {
mDisplayIdToMirror = DEFAULT_DISPLAY;
}
+ if ((mBuilderFieldsSet & 0x100) == 0) {
+ mWindowTokenClientToMirror = null;
+ }
VirtualDisplayConfig o = new VirtualDisplayConfig(
mName,
mWidth,
@@ -464,12 +503,13 @@ public final class VirtualDisplayConfig implements Parcelable {
mFlags,
mSurface,
mUniqueId,
- mDisplayIdToMirror);
+ mDisplayIdToMirror,
+ mWindowTokenClientToMirror);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x100) != 0) {
+ if ((mBuilderFieldsSet & 0x200) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -477,10 +517,10 @@ public final class VirtualDisplayConfig implements Parcelable {
}
@DataClass.Generated(
- time = 1604456298440L,
- codegenVersion = "1.0.20",
+ time = 1620657851981L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
- inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
+ inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate @android.annotation.Nullable android.os.IBinder mWindowTokenClientToMirror\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/inputmethodservice/RemoteInputConnection.java b/core/java/android/inputmethodservice/RemoteInputConnection.java
index 5a8687d78fd8..ec5bcf1f1199 100644
--- a/core/java/android/inputmethodservice/RemoteInputConnection.java
+++ b/core/java/android/inputmethodservice/RemoteInputConnection.java
@@ -43,6 +43,16 @@ import com.android.internal.view.IInputMethod;
import java.lang.ref.WeakReference;
+/**
+ * Takes care of remote method invocations of {@link InputConnection} in the IME side.
+ *
+ * <p>This class works as a proxy to forward API calls on {@link InputConnection} to
+ * {@link com.android.internal.inputmethod.RemoteInputConnectionImpl} running on the IME client
+ * (editor app) process then waits replies as needed.</p>
+ *
+ * <p>See also {@link IInputContext} for the actual {@link android.os.Binder} IPC protocols under
+ * the hood.</p>
+ */
final class RemoteInputConnection implements InputConnection {
private static final String TAG = "RemoteInputConnection";
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index f38271aad867..403f55ceb94a 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -34,6 +34,7 @@ import android.util.Log;
import com.android.internal.os.IDropBoxManagerService;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
@@ -257,7 +258,8 @@ public class DropBoxManager {
} else {
return null;
}
- return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+ return (mFlags & IS_GZIPPED) != 0
+ ? new GZIPInputStream(new BufferedInputStream(is)) : is;
}
public static final @android.annotation.NonNull Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() {
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1bc64951ad96..edfcb3d6f12a 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1470,7 +1470,7 @@ public final class FileUtils {
try (ParcelFileDescriptor dupFd = ParcelFileDescriptor.dup(fd)) {
return MediaStore.getOriginalMediaFormatFileDescriptor(context, dupFd);
} catch (Exception e) {
- Log.d(TAG, "Failed to convert to modern format file descriptor", e);
+ // Ignore error
return null;
}
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3aa0bcb6abee..2f66a39c1b52 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2092,9 +2092,7 @@ public final class PowerManager {
* when light idle mode restrictions are being actively applied; it will return false if the
* device is in a long-term idle mode but currently running a maintenance window where
* restrictions have been lifted.
- * @hide
*/
- @UnsupportedAppUsage
public boolean isLightDeviceIdleMode() {
try {
return mService.isLightDeviceIdleMode();
@@ -2555,9 +2553,7 @@ public final class PowerManager {
/**
* Intent that is broadcast when the state of {@link #isLightDeviceIdleMode()} changes.
* This broadcast is only sent to registered receivers.
- * @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
= "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index f853e67f87d0..f7d7b21cb598 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -257,7 +257,12 @@ public final class ServiceManager {
*
* @return {@code null} only if there are permission problems or fatal errors.
*/
- public static native IBinder waitForService(@NonNull String name);
+ public static IBinder waitForService(@NonNull String name) {
+ return Binder.allowBlocking(waitForServiceNative(name));
+ }
+
+ private static native IBinder waitForServiceNative(@NonNull String name);
+
/**
* Returns the specified service from the service manager, if declared.
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 03f94c549512..19f204b377c8 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -31,7 +31,9 @@ import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE;
import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.media.AudioSystem.MODE_IN_COMMUNICATION;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
@@ -63,7 +65,8 @@ import java.util.Objects;
*
* @hide
*/
-public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener {
+public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedListener,
+ AppOpsManager.OnOpStartedListener {
/** Whether to show the mic and camera icons. */
private static final String PROPERTY_CAMERA_MIC_ICONS_ENABLED = "camera_mic_icons_enabled";
@@ -160,9 +163,10 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
mUserContexts = new ArrayMap<>();
mUserContexts.put(Process.myUserHandle(), mContext);
// TODO ntmyren: make this listen for flag enable/disable changes
- String[] ops = { OPSTR_CAMERA, OPSTR_RECORD_AUDIO };
- mContext.getSystemService(AppOpsManager.class).startWatchingActive(ops,
- context.getMainExecutor(), this);
+ String[] opStrs = { OPSTR_CAMERA, OPSTR_RECORD_AUDIO };
+ mAppOpsManager.startWatchingActive(opStrs, context.getMainExecutor(), this);
+ int[] ops = { OP_CAMERA, OP_RECORD_AUDIO };
+ mAppOpsManager.startWatchingStarted(ops, this);
}
private Context getUserContext(UserHandle user) {
@@ -182,25 +186,65 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
public void onOpActiveChanged(@NonNull String op, int uid, @NonNull String packageName,
@Nullable String attributionTag, boolean active, @AttributionFlags int attributionFlags,
int attributionChainId) {
- if (attributionChainId == ATTRIBUTION_CHAIN_ID_NONE
- || attributionFlags == ATTRIBUTION_FLAGS_NONE
- || (attributionFlags & ATTRIBUTION_FLAG_TRUSTED) == 0) {
- // If this is not a chain, or it is untrusted, return
+ if (active) {
+ // Started callback handles these
return;
}
- if (!active) {
- // if any link in the chain is finished, remove the chain.
- // TODO ntmyren: be smarter about this
- mAttributionChains.remove(attributionChainId);
+ // if any link in the chain is finished, remove the chain. Then, find any other chains that
+ // contain this op/package/uid/tag combination, and remove them, as well.
+ // TODO ntmyren: be smarter about this
+ mAttributionChains.remove(attributionChainId);
+ int numChains = mAttributionChains.size();
+ ArrayList<Integer> toRemove = new ArrayList<>();
+ for (int i = 0; i < numChains; i++) {
+ int chainId = mAttributionChains.keyAt(i);
+ ArrayList<AccessChainLink> chain = mAttributionChains.valueAt(i);
+ int chainSize = chain.size();
+ for (int j = 0; j < chainSize; j++) {
+ AccessChainLink link = chain.get(j);
+ if (link.packageAndOpEquals(op, packageName, attributionTag, uid)) {
+ toRemove.add(chainId);
+ break;
+ }
+ }
+ }
+ mAttributionChains.removeAll(toRemove);
+ }
+
+ @Override
+ public void onOpStarted(int op, int uid, String packageName, String attributionTag,
+ @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+ // not part of an attribution chain. Do nothing
+ }
+
+ @Override
+ public void onOpStarted(int op, int uid, String packageName, String attributionTag,
+ @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result,
+ @StartedType int startedType, @AttributionFlags int attributionFlags,
+ int attributionChainId) {
+ if (startedType == START_TYPE_FAILED || attributionChainId == ATTRIBUTION_CHAIN_ID_NONE
+ || attributionFlags == ATTRIBUTION_FLAGS_NONE
+ || (attributionFlags & ATTRIBUTION_FLAG_TRUSTED) == 0) {
+ // If this is not a successful start, or it is not a chain, or it is untrusted, return
return;
}
+ addLinkToChainIfNotPresent(AppOpsManager.opToPublicName(op), packageName, uid,
+ attributionTag, attributionFlags, attributionChainId);
+ }
+
+ private void addLinkToChainIfNotPresent(String op, String packageName, int uid,
+ String attributionTag, int attributionFlags, int attributionChainId) {
ArrayList<AccessChainLink> currentChain = mAttributionChains.computeIfAbsent(
attributionChainId, k -> new ArrayList<>());
AccessChainLink link = new AccessChainLink(op, packageName, attributionTag, uid,
attributionFlags);
+ if (currentChain.contains(link)) {
+ return;
+ }
+
int currSize = currentChain.size();
if (currSize == 0 || link.isEnd() || !currentChain.get(currSize - 1).isEnd()) {
// if the list is empty, this link is the end, or the last link in the current chain
@@ -613,5 +657,21 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
public boolean isStart() {
return (flags & ATTRIBUTION_FLAG_RECEIVER) != 0;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AccessChainLink)) {
+ return false;
+ }
+ AccessChainLink other = (AccessChainLink) obj;
+ return other.flags == flags && packageAndOpEquals(other.usage.op,
+ other.usage.packageName, other.usage.attributionTag, other.usage.uid);
+ }
+
+ public boolean packageAndOpEquals(String op, String packageName, String attributionTag,
+ int uid) {
+ return Objects.equals(op, usage.op) && Objects.equals(packageName, usage.packageName)
+ && Objects.equals(attributionTag, usage.attributionTag) && uid == usage.uid;
+ }
}
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b3d60a58410f..570d73d4293b 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8588,6 +8588,15 @@ public final class ContactsContract {
* Type: INTEGER
*/
public static final String UNGROUPED_WITH_PHONES = "summ_phones";
+
+ /**
+ * Flag indicating if the account is the default account for new contacts. At most one
+ * account has this flag set at a time. It can only be set to 1 on a row with null data set.
+ * <p>
+ * Type: INTEGER (boolean)
+ * @hide
+ */
+ String IS_DEFAULT = "x_is_default";
}
/**
@@ -8681,6 +8690,13 @@ public final class ContactsContract {
* The MIME-type of {@link #CONTENT_URI} providing a single setting.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
+
+ /**
+ * Action used to launch the UI to set the default account for new contacts.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SET_DEFAULT_ACCOUNT =
+ "android.provider.action.SET_DEFAULT_ACCOUNT";
}
/**
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index ded598ad9e6d..ef486a9e27e2 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -258,6 +258,14 @@ public final class DeviceConfig {
public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
/**
+ * Namespace for all lmkd related features.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_LMKD_NATIVE = "lmkd_native";
+
+ /**
* Namespace for all location related features.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4dfa6c30a5e7..635aa4e2e72a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10221,6 +10221,13 @@ public final class Settings {
"device_state_rotation_lock";
/**
+ * Control whether communal mode is allowed on this device.
+ *
+ * @hide
+ */
+ public static final String COMMUNAL_MODE_ENABLED = "communal_mode_enabled";
+
+ /**
* These entries are considered common between the personal and the managed profile,
* since the managed profile doesn't get to change them.
*/
@@ -13511,6 +13518,54 @@ public final class Settings {
public static final int DEFAULT_ENABLE_TARE = 0;
/**
+ * Whether to enable the TARE AlarmManager economic policy or not.
+ * 1 means enable, 0 means disable.
+ *
+ * @hide
+ */
+ public static final String ENABLE_TARE_ALARM_MANAGER = "enable_tare_alarm_manager";
+
+ /**
+ * Default value for {@link #ENABLE_TARE_ALARM_MANAGER}.
+ *
+ * @hide
+ */
+ public static final int DEFAULT_ENABLE_TARE_ALARM_MANAGER = 0;
+
+ /**
+ * Settings for AlarmManager's TARE EconomicPolicy (list of its economic factors).
+ *
+ * Keys are listed in {@link android.app.tare.EconomyManager}.
+ *
+ * @hide
+ */
+ public static final String TARE_ALARM_MANAGER_CONSTANTS = "tare_alarm_manager_constants";
+
+ /**
+ * Whether to enable the TARE JobScheduler economic policy or not.
+ * 1 means enable, 0 means disable.
+ *
+ * @hide
+ */
+ public static final String ENABLE_TARE_JOB_SCHEDULER = "enable_tare_job_scheduler";
+
+ /**
+ * Default value for {@link #ENABLE_TARE_JOB_SCHEDULER}.
+ *
+ * @hide
+ */
+ public static final int DEFAULT_ENABLE_TARE_JOB_SCHEDULER = 0;
+
+ /**
+ * Settings for JobScheduler's TARE EconomicPolicy (list of its economic factors).
+ *
+ * Keys are listed in {@link android.app.tare.EconomyManager}.
+ *
+ * @hide
+ */
+ public static final String TARE_JOB_SCHEDULER_CONSTANTS = "tare_job_scheduler_constants";
+
+ /**
* Whether or not to enable the User Absent, Radios Off feature on small battery devices.
* Type: int (0 for false, 1 for true)
* Default: 0
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 41374167cc56..face870ca1b4 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -783,6 +783,9 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector {
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
+ // TODO: Remove this RequiresPermission since it isn't actually enforced. Also fix the javadoc
+ // about permissions enforcement (when it throws vs when it just returns false) for other
+ // methods in this class.
@RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
@Override
public boolean stopRecognition() {
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index 02294e5720ae..f7a3415259fd 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -82,6 +82,9 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector {
try {
mManagerService.startListeningFromMic(
mAudioFormat, new BinderCallback(mHandler, mCallback));
+ } catch (SecurityException e) {
+ Slog.e(TAG, "startRecognition failed: " + e);
+ return false;
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 6a0fec790242..f52c9ff210d6 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -520,6 +520,12 @@ public class VoiceInteractionService extends Service {
// Ignore.
}
+ try {
+ mSystemService.shutdownHotwordDetectionService();
+ } catch (Exception ex) {
+ // Ignore.
+ }
+
mSoftwareHotwordDetector = null;
}
diff --git a/core/java/android/uwb/AdapterStateListener.java b/core/java/android/uwb/AdapterStateListener.java
deleted file mode 100644
index 7e82cc6318f7..000000000000
--- a/core/java/android/uwb/AdapterStateListener.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.NonNull;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.uwb.UwbManager.AdapterStateCallback;
-import android.uwb.UwbManager.AdapterStateCallback.State;
-import android.uwb.UwbManager.AdapterStateCallback.StateChangedReason;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * @hide
- */
-public class AdapterStateListener extends IUwbAdapterStateCallbacks.Stub {
- private static final String TAG = "Uwb.StateListener";
-
- private final IUwbAdapter mAdapter;
- private boolean mIsRegistered = false;
-
- private final Map<AdapterStateCallback, Executor> mCallbackMap = new HashMap<>();
-
- @StateChangedReason
- private int mAdapterStateChangeReason = AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN;
- @State
- private int mAdapterState = AdapterStateCallback.STATE_DISABLED;
-
- public AdapterStateListener(@NonNull IUwbAdapter adapter) {
- mAdapter = adapter;
- }
-
- /**
- * Register an {@link AdapterStateCallback} with this {@link AdapterStateListener}
- *
- * @param executor an {@link Executor} to execute given callback
- * @param callback user implementation of the {@link AdapterStateCallback}
- */
- public void register(@NonNull Executor executor, @NonNull AdapterStateCallback callback) {
- synchronized (this) {
- if (mCallbackMap.containsKey(callback)) {
- return;
- }
-
- mCallbackMap.put(callback, executor);
-
- if (!mIsRegistered) {
- try {
- mAdapter.registerAdapterStateCallbacks(this);
- mIsRegistered = true;
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to register adapter state callback");
- throw e.rethrowFromSystemServer();
- }
- } else {
- sendCurrentState(callback);
- }
- }
- }
-
- /**
- * Unregister the specified {@link AdapterStateCallback}
- *
- * @param callback user implementation of the {@link AdapterStateCallback}
- */
- public void unregister(@NonNull AdapterStateCallback callback) {
- synchronized (this) {
- if (!mCallbackMap.containsKey(callback)) {
- return;
- }
-
- mCallbackMap.remove(callback);
-
- if (mCallbackMap.isEmpty() && mIsRegistered) {
- try {
- mAdapter.unregisterAdapterStateCallbacks(this);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to unregister AdapterStateCallback with service");
- throw e.rethrowFromSystemServer();
- }
- mIsRegistered = false;
- }
- }
- }
-
- /**
- * Sets the adapter enabled state
- *
- * @param isEnabled value of new adapter state
- */
- public void setEnabled(boolean isEnabled) {
- synchronized (this) {
- try {
- mAdapter.setEnabled(isEnabled);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set adapter state");
- throw e.rethrowFromSystemServer();
- }
-
- }
- }
-
- /**
- * Gets the adapter enabled state
- *
- * @return integer representing adapter enabled state
- */
- public int getAdapterState() {
- synchronized (this) {
- try {
- return mAdapter.getAdapterState();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to get adapter state");
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- private void sendCurrentState(@NonNull AdapterStateCallback callback) {
- synchronized (this) {
- Executor executor = mCallbackMap.get(callback);
-
- final long identity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> callback.onStateChanged(
- mAdapterState, mAdapterStateChangeReason));
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void onAdapterStateChanged(int state, int reason) {
- synchronized (this) {
- @StateChangedReason int localReason =
- convertToStateChangedReason(reason);
- @State int localState = convertToState(state);
- mAdapterStateChangeReason = localReason;
- mAdapterState = localState;
- for (AdapterStateCallback cb : mCallbackMap.keySet()) {
- sendCurrentState(cb);
- }
- }
- }
-
- private static @StateChangedReason int convertToStateChangedReason(
- @StateChangeReason int reason) {
- switch (reason) {
- case StateChangeReason.ALL_SESSIONS_CLOSED:
- return AdapterStateCallback.STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED;
-
- case StateChangeReason.SESSION_STARTED:
- return AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED;
-
- case StateChangeReason.SYSTEM_POLICY:
- return AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY;
-
- case StateChangeReason.SYSTEM_BOOT:
- return AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT;
-
- case StateChangeReason.UNKNOWN:
- default:
- return AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN;
- }
- }
-
- private static @State int convertToState(@AdapterState int state) {
- switch (state) {
- case AdapterState.STATE_ENABLED_INACTIVE:
- return AdapterStateCallback.STATE_ENABLED_INACTIVE;
-
- case AdapterState.STATE_ENABLED_ACTIVE:
- return AdapterStateCallback.STATE_ENABLED_ACTIVE;
-
- case AdapterState.STATE_DISABLED:
- default:
- return AdapterStateCallback.STATE_DISABLED;
- }
- }
-}
diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java
deleted file mode 100644
index 3d603737c48c..000000000000
--- a/core/java/android/uwb/AngleMeasurement.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.FloatRange;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Angle measurement
- *
- * <p>The actual angle is interpreted as:
- * {@link #getRadians()} +/- {@link #getErrorRadians()} ()} at {@link #getConfidenceLevel()}
- *
- * @hide
- */
-@SystemApi
-public final class AngleMeasurement implements Parcelable {
- private final double mRadians;
- private final double mErrorRadians;
- private final double mConfidenceLevel;
-
- /**
- * Constructs a new {@link AngleMeasurement} object
- *
- * @param radians the angle in radians
- * @param errorRadians the error of the angle measurement in radians
- * @param confidenceLevel confidence level of the angle measurement
- *
- * @throws IllegalArgumentException if the radians, errorRadians, or confidenceLevel is out of
- * allowed range
- */
- public AngleMeasurement(
- @FloatRange(from = -Math.PI, to = +Math.PI) double radians,
- @FloatRange(from = 0.0, to = +Math.PI) double errorRadians,
- @FloatRange(from = 0.0, to = 1.0) double confidenceLevel) {
- if (radians < -Math.PI || radians > Math.PI) {
- throw new IllegalArgumentException("Invalid radians: " + radians);
- }
- mRadians = radians;
-
- if (errorRadians < 0.0 || errorRadians > Math.PI) {
- throw new IllegalArgumentException("Invalid error radians: " + errorRadians);
- }
- mErrorRadians = errorRadians;
-
- if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
- throw new IllegalArgumentException("Invalid confidence level: " + confidenceLevel);
- }
- mConfidenceLevel = confidenceLevel;
- }
-
- /**
- * Angle measurement in radians
- *
- * @return angle in radians
- */
- @FloatRange(from = -Math.PI, to = +Math.PI)
- public double getRadians() {
- return mRadians;
- }
-
- /**
- * Error of angle measurement in radians
- *
- * <p>Must be a positive value
- *
- * @return angle measurement error in radians
- */
- @FloatRange(from = 0.0, to = +Math.PI)
- public double getErrorRadians() {
- return mErrorRadians;
- }
-
- /**
- * Angle measurement confidence level expressed as a value between
- * 0.0 to 1.0.
- *
- * <p>A value of 0.0 indicates there is no confidence in the measurement. A value of 1.0
- * indicates there is maximum confidence in the measurement.
- *
- * @return the confidence level of the angle measurement
- */
- @FloatRange(from = 0.0, to = 1.0)
- public double getConfidenceLevel() {
- return mConfidenceLevel;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof AngleMeasurement) {
- AngleMeasurement other = (AngleMeasurement) obj;
- return mRadians == other.getRadians()
- && mErrorRadians == other.getErrorRadians()
- && mConfidenceLevel == other.getConfidenceLevel();
- }
- return false;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mRadians, mErrorRadians, mConfidenceLevel);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeDouble(mRadians);
- dest.writeDouble(mErrorRadians);
- dest.writeDouble(mConfidenceLevel);
- }
-
- public static final @android.annotation.NonNull Creator<AngleMeasurement> CREATOR =
- new Creator<AngleMeasurement>() {
- @Override
- public AngleMeasurement createFromParcel(Parcel in) {
- return new AngleMeasurement(in.readDouble(), in.readDouble(), in.readDouble());
- }
-
- @Override
- public AngleMeasurement[] newArray(int size) {
- return new AngleMeasurement[size];
- }
- };
-}
diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java
deleted file mode 100644
index db04ad16c191..000000000000
--- a/core/java/android/uwb/AngleOfArrivalMeasurement.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Represents an angle of arrival measurement between two devices using Ultra Wideband
- *
- * @hide
- */
-@SystemApi
-public final class AngleOfArrivalMeasurement implements Parcelable {
- private final AngleMeasurement mAzimuthAngleMeasurement;
- private final AngleMeasurement mAltitudeAngleMeasurement;
-
- private AngleOfArrivalMeasurement(@NonNull AngleMeasurement azimuthAngleMeasurement,
- @Nullable AngleMeasurement altitudeAngleMeasurement) {
- mAzimuthAngleMeasurement = azimuthAngleMeasurement;
- mAltitudeAngleMeasurement = altitudeAngleMeasurement;
- }
-
- /**
- * Azimuth angle measurement
- * <p>Azimuth {@link AngleMeasurement} of remote device in horizontal coordinate system, this is
- * the angle clockwise from the meridian when viewing above the north pole.
- *
- * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
- *
- * <p>On an Android device, azimuth north is defined as the angle perpendicular away from the
- * back of the device when holding it in portrait mode upright.
- *
- * <p>Azimuth angle must be supported when Angle of Arrival is supported
- *
- * @return the azimuth {@link AngleMeasurement}
- */
- @NonNull
- public AngleMeasurement getAzimuth() {
- return mAzimuthAngleMeasurement;
- }
-
- /**
- * Altitude angle measurement
- * <p>Altitude {@link AngleMeasurement} of remote device in horizontal coordinate system, this
- * is the angle above the equator when the north pole is up.
- *
- * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
- *
- * <p>On an Android device, altitude is defined as the angle vertical from ground when holding
- * the device in portrait mode upright.
- *
- * @return altitude {@link AngleMeasurement} or null when this is not available
- */
- @Nullable
- public AngleMeasurement getAltitude() {
- return mAltitudeAngleMeasurement;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof AngleOfArrivalMeasurement) {
- AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj;
- return mAzimuthAngleMeasurement.equals(other.getAzimuth())
- && mAltitudeAngleMeasurement.equals(other.getAltitude());
- }
- return false;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mAzimuthAngleMeasurement, mAltitudeAngleMeasurement);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mAzimuthAngleMeasurement, flags);
- dest.writeParcelable(mAltitudeAngleMeasurement, flags);
- }
-
- public static final @android.annotation.NonNull Creator<AngleOfArrivalMeasurement> CREATOR =
- new Creator<AngleOfArrivalMeasurement>() {
- @Override
- public AngleOfArrivalMeasurement createFromParcel(Parcel in) {
- Builder builder =
- new Builder(in.readParcelable(AngleMeasurement.class.getClassLoader()));
-
- builder.setAltitude(in.readParcelable(AngleMeasurement.class.getClassLoader()));
-
- return builder.build();
- }
-
- @Override
- public AngleOfArrivalMeasurement[] newArray(int size) {
- return new AngleOfArrivalMeasurement[size];
- }
- };
-
- /**
- * Builder class for {@link AngleOfArrivalMeasurement}.
- */
- public static final class Builder {
- private final AngleMeasurement mAzimuthAngleMeasurement;
- private AngleMeasurement mAltitudeAngleMeasurement = null;
-
- /**
- * Constructs an {@link AngleOfArrivalMeasurement} object
- *
- * @param azimuthAngle the azimuth angle of the measurement
- */
- public Builder(@NonNull AngleMeasurement azimuthAngle) {
- mAzimuthAngleMeasurement = azimuthAngle;
- }
-
- /**
- * Set the altitude angle
- *
- * @param altitudeAngle altitude angle
- */
- @NonNull
- public Builder setAltitude(@NonNull AngleMeasurement altitudeAngle) {
- mAltitudeAngleMeasurement = altitudeAngle;
- return this;
- }
-
- /**
- * Build the {@link AngleOfArrivalMeasurement} object
- */
- @NonNull
- public AngleOfArrivalMeasurement build() {
- return new AngleOfArrivalMeasurement(mAzimuthAngleMeasurement,
- mAltitudeAngleMeasurement);
- }
- }
-}
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
deleted file mode 100644
index 98565536e64a..000000000000
--- a/core/java/android/uwb/DistanceMeasurement.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.FloatRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * A data point for the distance measurement
- *
- * <p>The actual distance is interpreted as:
- * {@link #getMeters()} +/- {@link #getErrorMeters()} at {@link #getConfidenceLevel()}
- *
- * @hide
- */
-@SystemApi
-public final class DistanceMeasurement implements Parcelable {
- private final double mMeters;
- private final double mErrorMeters;
- private final double mConfidenceLevel;
-
- private DistanceMeasurement(double meters, double errorMeters, double confidenceLevel) {
- mMeters = meters;
- mErrorMeters = errorMeters;
- mConfidenceLevel = confidenceLevel;
- }
-
- /**
- * Distance measurement in meters
- *
- * @return distance in meters
- */
- public double getMeters() {
- return mMeters;
- }
-
- /**
- * Error of distance measurement in meters
- * <p>Must be positive
- *
- * @return error of distance measurement in meters
- */
- @FloatRange(from = 0.0)
- public double getErrorMeters() {
- return mErrorMeters;
- }
-
- /**
- * Distance measurement confidence level expressed as a value between 0.0 to 1.0.
- *
- * <p>A value of 0.0 indicates no confidence in the measurement. A value of 1.0 represents
- * maximum confidence in the measurement
- *
- * @return confidence level
- */
- @FloatRange(from = 0.0, to = 1.0)
- public double getConfidenceLevel() {
- return mConfidenceLevel;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof DistanceMeasurement) {
- DistanceMeasurement other = (DistanceMeasurement) obj;
- return mMeters == other.getMeters()
- && mErrorMeters == other.getErrorMeters()
- && mConfidenceLevel == other.getConfidenceLevel();
- }
- return false;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mMeters, mErrorMeters, mConfidenceLevel);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeDouble(mMeters);
- dest.writeDouble(mErrorMeters);
- dest.writeDouble(mConfidenceLevel);
- }
-
- public static final @android.annotation.NonNull Creator<DistanceMeasurement> CREATOR =
- new Creator<DistanceMeasurement>() {
- @Override
- public DistanceMeasurement createFromParcel(Parcel in) {
- Builder builder = new Builder();
- builder.setMeters(in.readDouble());
- builder.setErrorMeters(in.readDouble());
- builder.setConfidenceLevel(in.readDouble());
- return builder.build();
- }
-
- @Override
- public DistanceMeasurement[] newArray(int size) {
- return new DistanceMeasurement[size];
- }
- };
-
- /**
- * Builder to get a {@link DistanceMeasurement} object.
- */
- public static final class Builder {
- private double mMeters = Double.NaN;
- private double mErrorMeters = Double.NaN;
- private double mConfidenceLevel = Double.NaN;
-
- /**
- * Set the distance measurement in meters
- *
- * @param meters distance in meters
- * @throws IllegalArgumentException if meters is NaN
- */
- @NonNull
- public Builder setMeters(double meters) {
- if (Double.isNaN(meters)) {
- throw new IllegalArgumentException("meters cannot be NaN");
- }
- mMeters = meters;
- return this;
- }
-
- /**
- * Set the distance error in meters
- *
- * @param errorMeters distance error in meters
- * @throws IllegalArgumentException if error is negative or NaN
- */
- @NonNull
- public Builder setErrorMeters(@FloatRange(from = 0.0) double errorMeters) {
- if (Double.isNaN(errorMeters) || errorMeters < 0.0) {
- throw new IllegalArgumentException(
- "errorMeters must be >= 0.0 and not NaN: " + errorMeters);
- }
- mErrorMeters = errorMeters;
- return this;
- }
-
- /**
- * Set the confidence level
- *
- * @param confidenceLevel the confidence level in the distance measurement
- * @throws IllegalArgumentException if confidence level is not in the range of [0.0, 1.0]
- */
- @NonNull
- public Builder setConfidenceLevel(
- @FloatRange(from = 0.0, to = 1.0) double confidenceLevel) {
- if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
- throw new IllegalArgumentException(
- "confidenceLevel must be in the range [0.0, 1.0]: " + confidenceLevel);
- }
- mConfidenceLevel = confidenceLevel;
- return this;
- }
-
- /**
- * Builds the {@link DistanceMeasurement} object
- *
- * @throws IllegalStateException if meters, error, or confidence are not set
- */
- @NonNull
- public DistanceMeasurement build() {
- if (Double.isNaN(mMeters)) {
- throw new IllegalStateException("Meters cannot be NaN");
- }
-
- if (Double.isNaN(mErrorMeters)) {
- throw new IllegalStateException("Error meters cannot be NaN");
- }
-
- if (Double.isNaN(mConfidenceLevel)) {
- throw new IllegalStateException("Confidence level cannot be NaN");
- }
-
- return new DistanceMeasurement(mMeters, mErrorMeters, mConfidenceLevel);
- }
- }
-}
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
deleted file mode 100644
index d87935003e03..000000000000
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.content.AttributionSource;
-import android.os.PersistableBundle;
-import android.uwb.IUwbAdapterStateCallbacks;
-import android.uwb.IUwbRangingCallbacks;
-import android.uwb.SessionHandle;
-
-/**
- * @hide
- */
-interface IUwbAdapter {
- /*
- * Register the callbacks used to notify the framework of events and data
- *
- * The provided callback's IUwbAdapterStateCallbacks#onAdapterStateChanged
- * function must be called immediately following registration with the current
- * state of the UWB adapter.
- *
- * @param callbacks callback to provide range and status updates to the framework
- */
- void registerAdapterStateCallbacks(in IUwbAdapterStateCallbacks adapterStateCallbacks);
-
- /*
- * Unregister the callbacks used to notify the framework of events and data
- *
- * Calling this function with an unregistered callback is a no-op
- *
- * @param callbacks callback to unregister
- */
- void unregisterAdapterStateCallbacks(in IUwbAdapterStateCallbacks callbacks);
-
- /**
- * Get the accuracy of the ranging timestamps
- *
- * @return accuracy of the ranging timestamps in nanoseconds
- */
- long getTimestampResolutionNanos();
-
- /**
- * Provides the capabilities and features of the device
- *
- * @return specification specific capabilities and features of the device
- */
- PersistableBundle getSpecificationInfo();
-
- /**
- * Request to open a new ranging session
- *
- * This function does not start the ranging session, but all necessary
- * components must be initialized and ready to start a new ranging
- * session prior to calling IUwbAdapterCallback#onRangingOpened.
- *
- * IUwbAdapterCallbacks#onRangingOpened must be called within
- * RANGING_SESSION_OPEN_THRESHOLD_MS milliseconds of #openRanging being
- * called if the ranging session is opened successfully.
- *
- * IUwbAdapterCallbacks#onRangingOpenFailed must be called within
- * RANGING_SESSION_OPEN_THRESHOLD_MS milliseconds of #openRanging being called
- * if the ranging session fails to be opened.
- *
- * If the provided sessionHandle is already open for the calling client, then
- * #onRangingOpenFailed must be called and the new session must not be opened.
- *
- * @param attributionSource AttributionSource to use for permission enforcement.
- * @param sessionHandle the session handle to open ranging for
- * @param rangingCallbacks the callbacks used to deliver ranging information
- * @param parameters the configuration to use for ranging
- */
- void openRanging(in AttributionSource attributionSource,
- in SessionHandle sessionHandle,
- in IUwbRangingCallbacks rangingCallbacks,
- in PersistableBundle parameters);
-
- /**
- * Request to start ranging
- *
- * IUwbAdapterCallbacks#onRangingStarted must be called within
- * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being
- * called if the ranging session starts successfully.
- *
- * IUwbAdapterCallbacks#onRangingStartFailed must be called within
- * RANGING_SESSION_START_THRESHOLD_MS milliseconds of #startRanging being
- * called if the ranging session fails to be started.
- *
- * @param sessionHandle the session handle to start ranging for
- * @param parameters additional configuration required to start ranging
- */
- void startRanging(in SessionHandle sessionHandle,
- in PersistableBundle parameters);
-
- /**
- * Request to reconfigure ranging
- *
- * IUwbAdapterCallbacks#onRangingReconfigured must be called after
- * successfully reconfiguring the session.
- *
- * IUwbAdapterCallbacks#onRangingReconfigureFailed must be called after
- * failing to reconfigure the session.
- *
- * A session must not be modified by a failed call to #reconfigureRanging.
- *
- * @param sessionHandle the session handle to start ranging for
- * @param parameters the parameters to reconfigure and their new values
- */
- void reconfigureRanging(in SessionHandle sessionHandle,
- in PersistableBundle parameters);
-
- /**
- * Request to stop ranging
- *
- * IUwbAdapterCallbacks#onRangingStopped must be called after
- * successfully stopping the session.
- *
- * IUwbAdapterCallbacks#onRangingStopFailed must be called after failing
- * to stop the session.
- *
- * @param sessionHandle the session handle to stop ranging for
- */
- void stopRanging(in SessionHandle sessionHandle);
-
- /**
- * Close ranging for the session associated with the given handle
- *
- * Calling with an invalid handle or a handle that has already been closed
- * is a no-op.
- *
- * IUwbAdapterCallbacks#onRangingClosed must be called within
- * RANGING_SESSION_CLOSE_THRESHOLD_MS of #closeRanging being called.
- *
- * @param sessionHandle the session handle to close ranging for
- */
- void closeRanging(in SessionHandle sessionHandle);
-
- /**
- * Disables or enables UWB for a user
- *
- * The provided callback's IUwbAdapterStateCallbacks#onAdapterStateChanged
- * function must be called immediately following state change.
- *
- * @param enabled value representing intent to disable or enable UWB. If
- * true, any subsequent calls to #openRanging will be allowed. If false,
- * all active ranging sessions will be closed and subsequent calls to
- * #openRanging will be disallowed.
- */
- void setEnabled(boolean enabled);
-
- /**
- * Returns the current enabled/disabled UWB state.
- *
- * Possible values are:
- * IUwbAdapterState#STATE_DISABLED
- * IUwbAdapterState#STATE_ENABLED_ACTIVE
- * IUwbAdapterState#STATE_ENABLED_INACTIVE
- *
- * @return value representing enabled/disabled UWB state.
- */
- int getAdapterState();
-
- /**
- * The maximum allowed time to open a ranging session.
- */
- const int RANGING_SESSION_OPEN_THRESHOLD_MS = 3000; // Value TBD
-
- /**
- * The maximum allowed time to start a ranging session.
- */
- const int RANGING_SESSION_START_THRESHOLD_MS = 3000; // Value TBD
-
- /**
- * The maximum allowed time to notify the framework that a session has been
- * closed.
- */
- const int RANGING_SESSION_CLOSE_THRESHOLD_MS = 3000; // Value TBD
-}
diff --git a/core/java/android/uwb/IUwbRangingCallbacks.aidl b/core/java/android/uwb/IUwbRangingCallbacks.aidl
deleted file mode 100644
index 555bafee8b1e..000000000000
--- a/core/java/android/uwb/IUwbRangingCallbacks.aidl
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.os.PersistableBundle;
-import android.uwb.RangingChangeReason;
-import android.uwb.RangingReport;
-import android.uwb.SessionHandle;
-
-/**
- * @hide
- */
-oneway interface IUwbRangingCallbacks {
- /**
- * Called when the ranging session has been opened
- *
- * @param sessionHandle the session the callback is being invoked for
- */
- void onRangingOpened(in SessionHandle sessionHandle);
-
- /**
- * Called when a ranging session fails to start
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session failed to start
- * @param parameters protocol specific parameters
- */
- void onRangingOpenFailed(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Called when ranging has started
- *
- * May output parameters generated by the lower layers that must be sent to the
- * remote device(s). The PersistableBundle must be constructed using the UWB
- * support library.
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param rangingOutputParameters parameters generated by the lower layer that
- * should be sent to the remote device.
- */
- void onRangingStarted(in SessionHandle sessionHandle,
- in PersistableBundle parameters);
-
- /**
- * Called when a ranging session fails to start
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session failed to start
- * @param parameters protocol specific parameters
- */
- void onRangingStartFailed(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Called when ranging has been reconfigured
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param parameters the updated ranging configuration
- */
- void onRangingReconfigured(in SessionHandle sessionHandle,
- in PersistableBundle parameters);
-
- /**
- * Called when a ranging session fails to be reconfigured
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session failed to reconfigure
- * @param parameters protocol specific parameters
- */
- void onRangingReconfigureFailed(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Called when the ranging session has been stopped
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session was stopped
- * @param parameters protocol specific parameters
- */
-
- void onRangingStopped(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Called when a ranging session fails to stop
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session failed to stop
- * @param parameters protocol specific parameters
- */
- void onRangingStopFailed(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Called when a ranging session is closed
- *
- * @param sessionHandle the session the callback is being invoked for
- * @param reason the reason the session was closed
- * @param parameters protocol specific parameters
- */
- void onRangingClosed(in SessionHandle sessionHandle,
- RangingChangeReason reason,
- in PersistableBundle parameters);
-
- /**
- * Provides a new RangingResult to the framework
- *
- * The reported timestamp for a ranging measurement must be calculated as the
- * time which the ranging round that generated this measurement concluded.
- *
- * @param sessionHandle an identifier to associate the ranging results with a
- * session that is active
- * @param result the ranging report
- */
- void onRangingResult(in SessionHandle sessionHandle, in RangingReport result);
-}
diff --git a/core/java/android/uwb/OWNERS b/core/java/android/uwb/OWNERS
deleted file mode 100644
index 17936ae7bb73..000000000000
--- a/core/java/android/uwb/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-bstack@google.com
-eliptus@google.com
-jsolnit@google.com
-matbev@google.com
-siyuanh@google.com
-zachoverflow@google.com
diff --git a/core/java/android/uwb/RangingChangeReason.aidl b/core/java/android/uwb/RangingChangeReason.aidl
deleted file mode 100644
index 19d4b3949d07..000000000000
--- a/core/java/android/uwb/RangingChangeReason.aidl
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-/**
- * @hide
- */
-@Backing(type="int")
-enum RangingChangeReason {
- /**
- * Unknown reason
- */
- UNKNOWN,
-
- /**
- * A local API call triggered the change, such as a call to
- * IUwbAdapter.closeRanging.
- */
- LOCAL_API,
-
- /**
- * The maximum number of sessions has been reached. This may be generated for
- * an active session if a higher priority session begins.
- */
- MAX_SESSIONS_REACHED,
-
- /**
- * The system state has changed resulting in the session changing (e.g. the
- * user disables UWB, or the user's locale changes and an active channel is no
- * longer permitted to be used).
- */
- SYSTEM_POLICY,
-
- /**
- * The remote device has requested to change the session
- */
- REMOTE_REQUEST,
-
- /**
- * The session changed for a protocol specific reason
- */
- PROTOCOL_SPECIFIC,
-
- /**
- * The provided parameters were invalid
- */
- BAD_PARAMETERS,
-}
-
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
deleted file mode 100644
index 6bba79600598..000000000000
--- a/core/java/android/uwb/RangingManager.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.NonNull;
-import android.content.AttributionSource;
-import android.os.CancellationSignal;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.Hashtable;
-import java.util.concurrent.Executor;
-
-/**
- * @hide
- */
-public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
- private static final String TAG = "Uwb.RangingManager";
-
- private final IUwbAdapter mAdapter;
- private final Hashtable<SessionHandle, RangingSession> mRangingSessionTable = new Hashtable<>();
- private int mNextSessionId = 1;
-
- public RangingManager(IUwbAdapter adapter) {
- mAdapter = adapter;
- }
-
- /**
- * Open a new ranging session
- *
- * @param attributionSource Attribution source to use for the enforcement of
- * {@link android.Manifest.permission#ULTRAWIDEBAND_RANGING} runtime
- * permission.
- * @param params the parameters that define the ranging session
- * @param executor {@link Executor} to run callbacks
- * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession}
- * that is being opened.
- * @return a {@link CancellationSignal} that may be used to cancel the opening of the
- * {@link RangingSession}.
- */
- public CancellationSignal openSession(@NonNull AttributionSource attributionSource,
- @NonNull PersistableBundle params,
- @NonNull Executor executor,
- @NonNull RangingSession.Callback callbacks) {
- synchronized (this) {
- SessionHandle sessionHandle = new SessionHandle(mNextSessionId++);
- RangingSession session =
- new RangingSession(executor, callbacks, mAdapter, sessionHandle);
- mRangingSessionTable.put(sessionHandle, session);
- try {
- mAdapter.openRanging(attributionSource, sessionHandle, this, params);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- CancellationSignal cancellationSignal = new CancellationSignal();
- cancellationSignal.setOnCancelListener(() -> session.close());
- return cancellationSignal;
- }
- }
-
- private boolean hasSession(SessionHandle sessionHandle) {
- return mRangingSessionTable.containsKey(sessionHandle);
- }
-
- @Override
- public void onRangingOpened(SessionHandle sessionHandle) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG,
- "onRangingOpened - received unexpected SessionHandle: " + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingOpened();
- }
- }
-
- @Override
- public void onRangingOpenFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
- PersistableBundle parameters) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG,
- "onRangingOpenedFailed - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingOpenFailed(convertToReason(reason), parameters);
- mRangingSessionTable.remove(sessionHandle);
- }
- }
-
- @Override
- public void onRangingReconfigured(SessionHandle sessionHandle, PersistableBundle parameters) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG,
- "onRangingReconfigured - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingReconfigured(parameters);
- }
- }
-
- @Override
- public void onRangingReconfigureFailed(SessionHandle sessionHandle,
- @RangingChangeReason int reason, PersistableBundle params) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingReconfigureFailed - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingReconfigureFailed(convertToReason(reason), params);
- }
- }
-
-
- @Override
- public void onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG,
- "onRangingStarted - received unexpected SessionHandle: " + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingStarted(parameters);
- }
- }
-
- @Override
- public void onRangingStartFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
- PersistableBundle params) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingStartFailed - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingStartFailed(convertToReason(reason), params);
- }
- }
-
- @Override
- public void onRangingStopped(SessionHandle sessionHandle, @RangingChangeReason int reason,
- PersistableBundle params) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingStopped - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingStopped(convertToReason(reason), params);
- }
- }
-
- @Override
- public void onRangingStopFailed(SessionHandle sessionHandle, @RangingChangeReason int reason,
- PersistableBundle parameters) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingStopFailed - received unexpected SessionHandle: "
- + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingStopFailed(convertToReason(reason), parameters);
- }
- }
-
- @Override
- public void onRangingClosed(SessionHandle sessionHandle, @RangingChangeReason int reason,
- PersistableBundle params) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingClosed - received unexpected SessionHandle: " + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingClosed(convertToReason(reason), params);
- mRangingSessionTable.remove(sessionHandle);
- }
- }
-
- @Override
- public void onRangingResult(SessionHandle sessionHandle, RangingReport result) {
- synchronized (this) {
- if (!hasSession(sessionHandle)) {
- Log.w(TAG, "onRangingResult - received unexpected SessionHandle: " + sessionHandle);
- return;
- }
-
- RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingResult(result);
- }
- }
-
- @RangingSession.Callback.Reason
- private static int convertToReason(@RangingChangeReason int reason) {
- switch (reason) {
- case RangingChangeReason.LOCAL_API:
- return RangingSession.Callback.REASON_LOCAL_REQUEST;
-
- case RangingChangeReason.MAX_SESSIONS_REACHED:
- return RangingSession.Callback.REASON_MAX_SESSIONS_REACHED;
-
- case RangingChangeReason.SYSTEM_POLICY:
- return RangingSession.Callback.REASON_SYSTEM_POLICY;
-
- case RangingChangeReason.REMOTE_REQUEST:
- return RangingSession.Callback.REASON_REMOTE_REQUEST;
-
- case RangingChangeReason.PROTOCOL_SPECIFIC:
- return RangingSession.Callback.REASON_PROTOCOL_SPECIFIC_ERROR;
-
- case RangingChangeReason.BAD_PARAMETERS:
- return RangingSession.Callback.REASON_BAD_PARAMETERS;
-
- case RangingChangeReason.UNKNOWN:
- default:
- return RangingSession.Callback.REASON_UNKNOWN;
- }
- }
-}
diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java
deleted file mode 100644
index 249e2b746d0d..000000000000
--- a/core/java/android/uwb/RangingMeasurement.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Representation of a ranging measurement between the local device and a remote device
- *
- * @hide
- */
-@SystemApi
-public final class RangingMeasurement implements Parcelable {
- private final UwbAddress mRemoteDeviceAddress;
- private final @Status int mStatus;
- private final long mElapsedRealtimeNanos;
- private final DistanceMeasurement mDistanceMeasurement;
- private final AngleOfArrivalMeasurement mAngleOfArrivalMeasurement;
-
- private RangingMeasurement(@NonNull UwbAddress remoteDeviceAddress, @Status int status,
- long elapsedRealtimeNanos, @Nullable DistanceMeasurement distanceMeasurement,
- @Nullable AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
- mRemoteDeviceAddress = remoteDeviceAddress;
- mStatus = status;
- mElapsedRealtimeNanos = elapsedRealtimeNanos;
- mDistanceMeasurement = distanceMeasurement;
- mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
- }
-
- /**
- * Get the remote device's {@link UwbAddress}
- *
- * @return the remote device's {@link UwbAddress}
- */
- @NonNull
- public UwbAddress getRemoteDeviceAddress() {
- return mRemoteDeviceAddress;
- }
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- RANGING_STATUS_SUCCESS,
- RANGING_STATUS_FAILURE_OUT_OF_RANGE,
- RANGING_STATUS_FAILURE_UNKNOWN_ERROR})
- public @interface Status {}
-
- /**
- * Ranging attempt was successful for this device
- */
- public static final int RANGING_STATUS_SUCCESS = 0;
-
- /**
- * Ranging failed for this device because it is out of range
- */
- public static final int RANGING_STATUS_FAILURE_OUT_OF_RANGE = 1;
-
- /**
- * Ranging failed for this device because of unknown error
- */
- public static final int RANGING_STATUS_FAILURE_UNKNOWN_ERROR = -1;
-
- /**
- * Get the status of this ranging measurement
- *
- * <p>Possible values are
- * {@link #RANGING_STATUS_SUCCESS},
- * {@link #RANGING_STATUS_FAILURE_OUT_OF_RANGE},
- * {@link #RANGING_STATUS_FAILURE_UNKNOWN_ERROR}.
- *
- * @return the status of the ranging measurement
- */
- @Status
- public int getStatus() {
- return mStatus;
- }
-
- /**
- * Timestamp of this ranging measurement in time since boot nanos in the same namespace as
- * {@link SystemClock#elapsedRealtimeNanos()}
- *
- * @return timestamp of ranging measurement in nanoseconds
- */
- @SuppressLint("MethodNameUnits")
- public long getElapsedRealtimeNanos() {
- return mElapsedRealtimeNanos;
- }
-
- /**
- * Get the distance measurement
- *
- * @return a {@link DistanceMeasurement} or null if {@link #getStatus()} !=
- * {@link #RANGING_STATUS_SUCCESS}
- */
- @Nullable
- public DistanceMeasurement getDistanceMeasurement() {
- return mDistanceMeasurement;
- }
-
- /**
- * Get the angle of arrival measurement
- *
- * @return an {@link AngleOfArrivalMeasurement} or null if {@link #getStatus()} !=
- * {@link #RANGING_STATUS_SUCCESS}
- */
- @Nullable
- public AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() {
- return mAngleOfArrivalMeasurement;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof RangingMeasurement) {
- RangingMeasurement other = (RangingMeasurement) obj;
- return mRemoteDeviceAddress.equals(other.getRemoteDeviceAddress())
- && mStatus == other.getStatus()
- && mElapsedRealtimeNanos == other.getElapsedRealtimeNanos()
- && mDistanceMeasurement.equals(other.getDistanceMeasurement())
- && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrivalMeasurement());
- }
- return false;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos,
- mDistanceMeasurement, mAngleOfArrivalMeasurement);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mRemoteDeviceAddress, flags);
- dest.writeInt(mStatus);
- dest.writeLong(mElapsedRealtimeNanos);
- dest.writeParcelable(mDistanceMeasurement, flags);
- dest.writeParcelable(mAngleOfArrivalMeasurement, flags);
- }
-
- public static final @android.annotation.NonNull Creator<RangingMeasurement> CREATOR =
- new Creator<RangingMeasurement>() {
- @Override
- public RangingMeasurement createFromParcel(Parcel in) {
- Builder builder = new Builder();
- builder.setRemoteDeviceAddress(
- in.readParcelable(UwbAddress.class.getClassLoader()));
- builder.setStatus(in.readInt());
- builder.setElapsedRealtimeNanos(in.readLong());
- builder.setDistanceMeasurement(
- in.readParcelable(DistanceMeasurement.class.getClassLoader()));
- builder.setAngleOfArrivalMeasurement(
- in.readParcelable(AngleOfArrivalMeasurement.class.getClassLoader()));
- return builder.build();
- }
-
- @Override
- public RangingMeasurement[] newArray(int size) {
- return new RangingMeasurement[size];
- }
- };
-
- /**
- * Builder for a {@link RangingMeasurement} object.
- */
- public static final class Builder {
- private UwbAddress mRemoteDeviceAddress = null;
- private @Status int mStatus = RANGING_STATUS_FAILURE_UNKNOWN_ERROR;
- private long mElapsedRealtimeNanos = -1L;
- private DistanceMeasurement mDistanceMeasurement = null;
- private AngleOfArrivalMeasurement mAngleOfArrivalMeasurement = null;
-
- /**
- * Set the remote device address that this measurement is for
- *
- * @param remoteDeviceAddress remote device's address
- */
- @NonNull
- public Builder setRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
- mRemoteDeviceAddress = remoteDeviceAddress;
- return this;
- }
-
- /**
- * Set the status of ranging measurement
- *
- * @param status the status of the ranging measurement
- */
- @NonNull
- public Builder setStatus(@Status int status) {
- mStatus = status;
- return this;
- }
-
- /**
- * Set the elapsed realtime in nanoseconds when the ranging measurement occurred
- *
- * @param elapsedRealtimeNanos time the ranging measurement occurred
- */
- @NonNull
- public Builder setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
- if (elapsedRealtimeNanos < 0) {
- throw new IllegalArgumentException("elapsedRealtimeNanos must be >= 0");
- }
- mElapsedRealtimeNanos = elapsedRealtimeNanos;
- return this;
- }
-
- /**
- * Set the {@link DistanceMeasurement}
- *
- * @param distanceMeasurement the distance measurement for this ranging measurement
- */
- @NonNull
- public Builder setDistanceMeasurement(@NonNull DistanceMeasurement distanceMeasurement) {
- mDistanceMeasurement = distanceMeasurement;
- return this;
- }
-
- /**
- * Set the {@link AngleOfArrivalMeasurement}
- *
- * @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging
- * measurement
- */
- @NonNull
- public Builder setAngleOfArrivalMeasurement(
- @NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
- mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
- return this;
- }
-
- /**
- * Build the {@link RangingMeasurement} object
- *
- * @throws IllegalStateException if a distance or angle of arrival measurement is provided
- * but the measurement was not successful, if the
- * elapsedRealtimeNanos of the measurement is invalid, or
- * if no remote device address is set
- */
- @NonNull
- public RangingMeasurement build() {
- if (mStatus != RANGING_STATUS_SUCCESS) {
- if (mDistanceMeasurement != null) {
- throw new IllegalStateException(
- "Distance Measurement must be null if ranging is not successful");
- }
-
- if (mAngleOfArrivalMeasurement != null) {
- throw new IllegalStateException(
- "Angle of Arrival must be null if ranging is not successful");
- }
- }
-
- if (mRemoteDeviceAddress == null) {
- throw new IllegalStateException("No remote device address was set");
- }
-
- if (mElapsedRealtimeNanos < 0) {
- throw new IllegalStateException(
- "elapsedRealtimeNanos must be >=0: " + mElapsedRealtimeNanos);
- }
-
- return new RangingMeasurement(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos,
- mDistanceMeasurement, mAngleOfArrivalMeasurement);
- }
- }
-}
diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java
deleted file mode 100644
index 7a2df8617700..000000000000
--- a/core/java/android/uwb/RangingReport.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * This class contains the UWB ranging data
- *
- * @hide
- */
-@SystemApi
-public final class RangingReport implements Parcelable {
- private final List<RangingMeasurement> mRangingMeasurements;
-
- private RangingReport(@NonNull List<RangingMeasurement> rangingMeasurements) {
- mRangingMeasurements = rangingMeasurements;
- }
-
- /**
- * Get a {@link List} of {@link RangingMeasurement} objects in the last measurement interval
- * <p>The underlying UWB adapter may choose to do multiple measurements in each ranging
- * interval.
- *
- * <p>The entries in the {@link List} are ordered in ascending order based on
- * {@link RangingMeasurement#getElapsedRealtimeNanos()}
- *
- * @return a {@link List} of {@link RangingMeasurement} objects
- */
- @NonNull
- public List<RangingMeasurement> getMeasurements() {
- return mRangingMeasurements;
- }
-
- /**
- * @hide
- */
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof RangingReport) {
- RangingReport other = (RangingReport) obj;
- return mRangingMeasurements.equals(other.getMeasurements());
- }
-
- return false;
- }
-
- /**
- * @hide
- */
- @Override
- public int hashCode() {
- return Objects.hash(mRangingMeasurements);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeTypedList(mRangingMeasurements);
- }
-
- public static final @android.annotation.NonNull Creator<RangingReport> CREATOR =
- new Creator<RangingReport>() {
- @Override
- public RangingReport createFromParcel(Parcel in) {
- Builder builder = new Builder();
- builder.addMeasurements(in.createTypedArrayList(RangingMeasurement.CREATOR));
- return builder.build();
- }
-
- @Override
- public RangingReport[] newArray(int size) {
- return new RangingReport[size];
- }
- };
-
- /**
- * Builder for {@link RangingReport} object
- */
- public static final class Builder {
- List<RangingMeasurement> mMeasurements = new ArrayList<>();
-
- /**
- * Add a single {@link RangingMeasurement}
- *
- * @param rangingMeasurement a ranging measurement
- */
- @NonNull
- public Builder addMeasurement(@NonNull RangingMeasurement rangingMeasurement) {
- mMeasurements.add(rangingMeasurement);
- return this;
- }
-
- /**
- * Add a {@link List} of {@link RangingMeasurement}s
- *
- * @param rangingMeasurements {@link List} of {@link RangingMeasurement}s to add
- */
- @NonNull
- public Builder addMeasurements(@NonNull List<RangingMeasurement> rangingMeasurements) {
- mMeasurements.addAll(rangingMeasurements);
- return this;
- }
-
- /**
- * Build the {@link RangingReport} object
- *
- * @throws IllegalStateException if measurements are not in monotonically increasing order
- */
- @NonNull
- public RangingReport build() {
- // Verify that all measurement timestamps are monotonically increasing
- RangingMeasurement prevMeasurement = null;
- for (int curIndex = 0; curIndex < mMeasurements.size(); curIndex++) {
- RangingMeasurement curMeasurement = mMeasurements.get(curIndex);
- if (prevMeasurement != null
- && (prevMeasurement.getElapsedRealtimeNanos()
- > curMeasurement.getElapsedRealtimeNanos())) {
- throw new IllegalStateException(
- "Timestamp (" + curMeasurement.getElapsedRealtimeNanos()
- + ") at index " + curIndex + " is less than previous timestamp ("
- + prevMeasurement.getElapsedRealtimeNanos() + ")");
- }
- prevMeasurement = curMeasurement;
- }
- return new RangingReport(mMeasurements);
- }
- }
-}
-
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
deleted file mode 100644
index 345b69df84d5..000000000000
--- a/core/java/android/uwb/RangingSession.java
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.Manifest;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.os.Binder;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
-
-/**
- * This class provides a way to control an active UWB ranging session.
- * <p>It also defines the required {@link RangingSession.Callback} that must be implemented
- * in order to be notified of UWB ranging results and status events related to the
- * {@link RangingSession}.
- *
- * <p>To get an instance of {@link RangingSession}, first use
- * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
- * session. Once the session is opened, a {@link RangingSession} object is provided through
- * {@link RangingSession.Callback#onOpened(RangingSession)}. If opening a session fails, the failure
- * is reported through {@link RangingSession.Callback#onOpenFailed(int, PersistableBundle)} with the
- * failure reason.
- *
- * @hide
- */
-@SystemApi
-public final class RangingSession implements AutoCloseable {
- private static final String TAG = "Uwb.RangingSession";
- private final SessionHandle mSessionHandle;
- private final IUwbAdapter mAdapter;
- private final Executor mExecutor;
- private final Callback mCallback;
-
- private enum State {
- /**
- * The state of the {@link RangingSession} until
- * {@link RangingSession.Callback#onOpened(RangingSession)} is invoked
- */
- INIT,
-
- /**
- * The {@link RangingSession} is initialized and ready to begin ranging
- */
- IDLE,
-
- /**
- * The {@link RangingSession} is actively ranging
- */
- ACTIVE,
-
- /**
- * The {@link RangingSession} is closed and may not be used for ranging.
- */
- CLOSED
- }
-
- private State mState = State.INIT;
-
- /**
- * Interface for receiving {@link RangingSession} events
- */
- public interface Callback {
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- REASON_UNKNOWN,
- REASON_LOCAL_REQUEST,
- REASON_REMOTE_REQUEST,
- REASON_BAD_PARAMETERS,
- REASON_GENERIC_ERROR,
- REASON_MAX_SESSIONS_REACHED,
- REASON_SYSTEM_POLICY,
- REASON_PROTOCOL_SPECIFIC_ERROR})
- @interface Reason {}
-
- /**
- * Indicates that the session was closed or failed to open due to an unknown reason
- */
- int REASON_UNKNOWN = 0;
-
- /**
- * Indicates that the session was closed or failed to open because
- * {@link AutoCloseable#close()} or {@link RangingSession#close()} was called
- */
- int REASON_LOCAL_REQUEST = 1;
-
- /**
- * Indicates that the session was closed or failed to open due to an explicit request from
- * the remote device.
- */
- int REASON_REMOTE_REQUEST = 2;
-
- /**
- * Indicates that the session was closed or failed to open due to erroneous parameters
- */
- int REASON_BAD_PARAMETERS = 3;
-
- /**
- * Indicates an error on this device besides the error code already listed
- */
- int REASON_GENERIC_ERROR = 4;
-
- /**
- * Indicates that the number of currently open sessions is equal to
- * {@link UwbManager#getMaxSimultaneousSessions()} and additional sessions may not be
- * opened.
- */
- int REASON_MAX_SESSIONS_REACHED = 5;
-
- /**
- * Indicates that the local system policy caused the change, such
- * as privacy policy, power management policy, permissions, and more.
- */
- int REASON_SYSTEM_POLICY = 6;
-
- /**
- * Indicates a protocol specific error. The associated {@link PersistableBundle} should be
- * consulted for additional information.
- */
- int REASON_PROTOCOL_SPECIFIC_ERROR = 7;
-
- /**
- * Invoked when {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
- * is successful
- *
- * @param session the newly opened {@link RangingSession}
- */
- void onOpened(@NonNull RangingSession session);
-
- /**
- * Invoked if {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}}
- * fails
- *
- * @param reason the failure reason
- * @param params protocol specific parameters
- */
- void onOpenFailed(@Reason int reason, @NonNull PersistableBundle params);
-
- /**
- * Invoked when {@link RangingSession#start(PersistableBundle)} is successful
- * @param sessionInfo session specific parameters from the lower layers
- */
- void onStarted(@NonNull PersistableBundle sessionInfo);
-
- /**
- * Invoked when {@link RangingSession#start(PersistableBundle)} fails
- *
- * @param reason the failure reason
- * @param params protocol specific parameters
- */
- void onStartFailed(@Reason int reason, @NonNull PersistableBundle params);
-
- /**
- * Invoked when a request to reconfigure the session succeeds
- *
- * @param params the updated ranging configuration
- */
- void onReconfigured(@NonNull PersistableBundle params);
-
- /**
- * Invoked when a request to reconfigure the session fails
- *
- * @param reason reason the session failed to be reconfigured
- * @param params protocol specific failure reasons
- */
- void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params);
-
- /**
- * Invoked when a request to stop the session succeeds
- *
- * @param reason reason for the session stop
- * @param parameters protocol specific parameters related to the stop reason
- */
- void onStopped(@Reason int reason, @NonNull PersistableBundle parameters);
-
- /**
- * Invoked when a request to stop the session fails
- *
- * @param reason reason the session failed to be stopped
- * @param params protocol specific failure reasons
- */
- void onStopFailed(@Reason int reason, @NonNull PersistableBundle params);
-
- /**
- * Invoked when session is either closed spontaneously, or per user request via
- * {@link RangingSession#close()} or {@link AutoCloseable#close()}.
- *
- * @param reason reason for the session closure
- * @param parameters protocol specific parameters related to the close reason
- */
- void onClosed(@Reason int reason, @NonNull PersistableBundle parameters);
-
- /**
- * Called once per ranging interval even when a ranging measurement fails
- *
- * @param rangingReport ranging report for this interval's measurements
- */
- void onReportReceived(@NonNull RangingReport rangingReport);
- }
-
- /**
- * @hide
- */
- public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
- SessionHandle sessionHandle) {
- mState = State.INIT;
- mExecutor = executor;
- mCallback = callback;
- mAdapter = adapter;
- mSessionHandle = sessionHandle;
- }
-
- /**
- * @hide
- */
- public boolean isOpen() {
- return mState == State.IDLE || mState == State.ACTIVE;
- }
-
- /**
- * Begins ranging for the session.
- *
- * <p>On successfully starting a ranging session,
- * {@link RangingSession.Callback#onStarted(PersistableBundle)} is invoked.
- *
- * <p>On failure to start the session,
- * {@link RangingSession.Callback#onStartFailed(int, PersistableBundle)} is invoked.
- *
- * @param params configuration parameters for starting the session
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public void start(@NonNull PersistableBundle params) {
- if (mState != State.IDLE) {
- throw new IllegalStateException();
- }
-
- try {
- mAdapter.startRanging(mSessionHandle, params);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Attempts to reconfigure the session with the given parameters
- * <p>This call may be made when the session is open.
- *
- * <p>On successfully reconfiguring the session
- * {@link RangingSession.Callback#onReconfigured(PersistableBundle)} is invoked.
- *
- * <p>On failure to reconfigure the session,
- * {@link RangingSession.Callback#onReconfigureFailed(int, PersistableBundle)} is invoked.
- *
- * @param params the parameters to reconfigure and their new values
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public void reconfigure(@NonNull PersistableBundle params) {
- if (mState != State.ACTIVE && mState != State.IDLE) {
- throw new IllegalStateException();
- }
-
- try {
- mAdapter.reconfigureRanging(mSessionHandle, params);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Stops actively ranging
- *
- * <p>A session that has been stopped may be resumed by calling
- * {@link RangingSession#start(PersistableBundle)} without the need to open a new session.
- *
- * <p>Stopping a {@link RangingSession} is useful when the lower layers should not discard
- * the parameters of the session, or when a session needs to be able to be resumed quickly.
- *
- * <p>If the {@link RangingSession} is no longer needed, use {@link RangingSession#close()} to
- * completely close the session and allow lower layers of the stack to perform necessarily
- * cleanup.
- *
- * <p>Stopped sessions may be closed by the system at any time. In such a case,
- * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} is invoked.
- *
- * <p>On failure to stop the session,
- * {@link RangingSession.Callback#onStopFailed(int, PersistableBundle)} is invoked.
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public void stop() {
- if (mState != State.ACTIVE) {
- throw new IllegalStateException();
- }
-
- try {
- mAdapter.stopRanging(mSessionHandle);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Close the ranging session
- *
- * <p>After calling this function, in order resume ranging, a new {@link RangingSession} must
- * be opened by calling
- * {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}.
- *
- * <p>If this session is currently ranging, it will stop and close the session.
- * <p>If the session is in the process of being opened, it will attempt to stop the session from
- * being opened.
- * <p>If the session is already closed, the registered
- * {@link Callback#onClosed(int, PersistableBundle)} callback will still be invoked.
- *
- * <p>{@link Callback#onClosed(int, PersistableBundle)} will be invoked using the same callback
- * object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
- * when the {@link RangingSession} was opened. The callback will be invoked after each call to
- * {@link #close()}, even if the {@link RangingSession} is already closed.
- */
- @Override
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public void close() {
- if (mState == State.CLOSED) {
- mExecutor.execute(() -> mCallback.onClosed(
- Callback.REASON_LOCAL_REQUEST, new PersistableBundle()));
- return;
- }
-
- try {
- mAdapter.closeRanging(mSessionHandle);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
- public void onRangingOpened() {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingOpened invoked for a closed session");
- return;
- }
-
- mState = State.IDLE;
- executeCallback(() -> mCallback.onOpened(this));
- }
-
- /**
- * @hide
- */
- public void onRangingOpenFailed(@Callback.Reason int reason,
- @NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingOpenFailed invoked for a closed session");
- return;
- }
-
- mState = State.CLOSED;
- executeCallback(() -> mCallback.onOpenFailed(reason, params));
- }
-
- /**
- * @hide
- */
- public void onRangingStarted(@NonNull PersistableBundle parameters) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingStarted invoked for a closed session");
- return;
- }
-
- mState = State.ACTIVE;
- executeCallback(() -> mCallback.onStarted(parameters));
- }
-
- /**
- * @hide
- */
- public void onRangingStartFailed(@Callback.Reason int reason,
- @NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingStartFailed invoked for a closed session");
- return;
- }
-
- executeCallback(() -> mCallback.onStartFailed(reason, params));
- }
-
- /**
- * @hide
- */
- public void onRangingReconfigured(@NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingReconfigured invoked for a closed session");
- return;
- }
-
- executeCallback(() -> mCallback.onReconfigured(params));
- }
-
- /**
- * @hide
- */
- public void onRangingReconfigureFailed(@Callback.Reason int reason,
- @NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingReconfigureFailed invoked for a closed session");
- return;
- }
-
- executeCallback(() -> mCallback.onReconfigureFailed(reason, params));
- }
-
- /**
- * @hide
- */
- public void onRangingStopped(@Callback.Reason int reason,
- @NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingStopped invoked for a closed session");
- return;
- }
-
- mState = State.IDLE;
- executeCallback(() -> mCallback.onStopped(reason, params));
- }
-
- /**
- * @hide
- */
- public void onRangingStopFailed(@Callback.Reason int reason,
- @NonNull PersistableBundle params) {
- if (mState == State.CLOSED) {
- Log.w(TAG, "onRangingStopFailed invoked for a closed session");
- return;
- }
-
- executeCallback(() -> mCallback.onStopFailed(reason, params));
- }
-
- /**
- * @hide
- */
- public void onRangingClosed(@Callback.Reason int reason,
- @NonNull PersistableBundle parameters) {
- mState = State.CLOSED;
- executeCallback(() -> mCallback.onClosed(reason, parameters));
- }
-
- /**
- * @hide
- */
- public void onRangingResult(@NonNull RangingReport report) {
- if (!isOpen()) {
- Log.w(TAG, "onRangingResult invoked for non-open session");
- return;
- }
-
- executeCallback(() -> mCallback.onReportReceived(report));
- }
-
- /**
- * @hide
- */
- private void executeCallback(@NonNull Runnable runnable) {
- final long identity = Binder.clearCallingIdentity();
- try {
- mExecutor.execute(runnable);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-}
diff --git a/core/java/android/uwb/SessionHandle.java b/core/java/android/uwb/SessionHandle.java
deleted file mode 100644
index b23f5ad603ff..000000000000
--- a/core/java/android/uwb/SessionHandle.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * @hide
- */
-public final class SessionHandle implements Parcelable {
- private final int mId;
-
- public SessionHandle(int id) {
- mId = id;
- }
-
- protected SessionHandle(Parcel in) {
- mId = in.readInt();
- }
-
- public static final Creator<SessionHandle> CREATOR = new Creator<SessionHandle>() {
- @Override
- public SessionHandle createFromParcel(Parcel in) {
- return new SessionHandle(in);
- }
-
- @Override
- public SessionHandle[] newArray(int size) {
- return new SessionHandle[size];
- }
- };
-
- public int getId() {
- return mId;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mId);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof SessionHandle) {
- SessionHandle other = (SessionHandle) obj;
- return mId == other.mId;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(mId);
- }
-
- @Override
- public String toString() {
- return "SessionHandle [id=" + mId + "]";
- }
-}
diff --git a/core/java/android/uwb/StateChangeReason.aidl b/core/java/android/uwb/StateChangeReason.aidl
deleted file mode 100644
index 28eaf9f2b24e..000000000000
--- a/core/java/android/uwb/StateChangeReason.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-/**
- * @hide
- */
-@Backing(type="int")
-enum StateChangeReason {
- /**
- * The state changed for an unknown reason
- */
- UNKNOWN,
-
- /**
- * The adapter state changed because a session started.
- */
- SESSION_STARTED,
-
-
- /**
- * The adapter state changed because all sessions were closed.
- */
- ALL_SESSIONS_CLOSED,
-
- /**
- * The adapter state changed because of a device system change.
- */
- SYSTEM_POLICY,
-
- /**
- * Used to signal the first adapter state message after boot
- */
- SYSTEM_BOOT,
-}
-
diff --git a/core/java/android/uwb/TEST_MAPPING b/core/java/android/uwb/TEST_MAPPING
deleted file mode 100644
index 08ed2c7b71d9..000000000000
--- a/core/java/android/uwb/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presubmit": [
- {
- "name": "UwbManagerTests"
- },
- {
- "name": "CtsUwbTestCases"
- }
- ]
-}
diff --git a/core/java/android/uwb/UwbAddress.java b/core/java/android/uwb/UwbAddress.java
deleted file mode 100644
index 22883be88760..000000000000
--- a/core/java/android/uwb/UwbAddress.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * A class representing a UWB address
- *
- * @hide
- */
-@SystemApi
-public final class UwbAddress implements Parcelable {
- public static final int SHORT_ADDRESS_BYTE_LENGTH = 2;
- public static final int EXTENDED_ADDRESS_BYTE_LENGTH = 8;
-
- private final byte[] mAddressBytes;
-
- private UwbAddress(byte[] address) {
- mAddressBytes = address;
- }
-
- /**
- * Create a {@link UwbAddress} from a byte array.
- *
- * <p>If the provided array is {@link #SHORT_ADDRESS_BYTE_LENGTH} bytes, a short address is
- * created. If the provided array is {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes, then an
- * extended address is created.
- *
- * @param address a byte array to convert to a {@link UwbAddress}
- * @return a {@link UwbAddress} created from the input byte array
- * @throws IllegalArgumentException when the length is not one of
- * {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes
- */
- @NonNull
- public static UwbAddress fromBytes(@NonNull byte[] address) {
- if (address.length != SHORT_ADDRESS_BYTE_LENGTH
- && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) {
- throw new IllegalArgumentException("Invalid UwbAddress length " + address.length);
- }
- return new UwbAddress(address);
- }
-
- /**
- * Get the address as a byte array
- *
- * @return the byte representation of this {@link UwbAddress}
- */
- @NonNull
- public byte[] toBytes() {
- return mAddressBytes;
- }
-
- /**
- * The length of the address in bytes
- * <p>Possible values are {@link #SHORT_ADDRESS_BYTE_LENGTH} and
- * {@link #EXTENDED_ADDRESS_BYTE_LENGTH}.
- */
- public int size() {
- return mAddressBytes.length;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("0x");
- for (byte addressByte : mAddressBytes) {
- builder.append(String.format("%02X", addressByte));
- }
- return builder.toString();
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj instanceof UwbAddress) {
- return Arrays.equals(mAddressBytes, ((UwbAddress) obj).toBytes());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Arrays.hashCode(mAddressBytes);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mAddressBytes.length);
- dest.writeByteArray(mAddressBytes);
- }
-
- public static final @android.annotation.NonNull Creator<UwbAddress> CREATOR =
- new Creator<UwbAddress>() {
- @Override
- public UwbAddress createFromParcel(Parcel in) {
- byte[] address = new byte[in.readInt()];
- in.readByteArray(address);
- return UwbAddress.fromBytes(address);
- }
-
- @Override
- public UwbAddress[] newArray(int size) {
- return new UwbAddress[size];
- }
- };
-}
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
deleted file mode 100644
index f7406ae277de..000000000000
--- a/core/java/android/uwb/UwbManager.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.Manifest.permission;
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.content.Context;
-import android.os.CancellationSignal;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
-
-/**
- * This class provides a way to perform Ultra Wideband (UWB) operations such as querying the
- * device's capabilities and determining the distance and angle between the local device and a
- * remote device.
- *
- * <p>To get a {@link UwbManager}, call the <code>Context.getSystemService(UwbManager.class)</code>.
- *
- * @hide
- */
-@SystemApi
-@SystemService(Context.UWB_SERVICE)
-public final class UwbManager {
- private static final String SERVICE_NAME = Context.UWB_SERVICE;
-
- private final Context mContext;
- private final IUwbAdapter mUwbAdapter;
- private final AdapterStateListener mAdapterStateListener;
- private final RangingManager mRangingManager;
-
- /**
- * Interface for receiving UWB adapter state changes
- */
- public interface AdapterStateCallback {
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- STATE_CHANGED_REASON_SESSION_STARTED,
- STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED,
- STATE_CHANGED_REASON_SYSTEM_POLICY,
- STATE_CHANGED_REASON_SYSTEM_BOOT,
- STATE_CHANGED_REASON_ERROR_UNKNOWN})
- @interface StateChangedReason {}
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- STATE_ENABLED_INACTIVE,
- STATE_ENABLED_ACTIVE,
- STATE_DISABLED})
- @interface State {}
-
- /**
- * Indicates that the state change was due to opening of first UWB session
- */
- int STATE_CHANGED_REASON_SESSION_STARTED = 0;
-
- /**
- * Indicates that the state change was due to closure of all UWB sessions
- */
- int STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED = 1;
-
- /**
- * Indicates that the state change was due to changes in system policy
- */
- int STATE_CHANGED_REASON_SYSTEM_POLICY = 2;
-
- /**
- * Indicates that the current state is due to a system boot
- */
- int STATE_CHANGED_REASON_SYSTEM_BOOT = 3;
-
- /**
- * Indicates that the state change was due to some unknown error
- */
- int STATE_CHANGED_REASON_ERROR_UNKNOWN = 4;
-
- /**
- * Indicates that UWB is disabled on device
- */
- int STATE_DISABLED = 0;
- /**
- * Indicates that UWB is enabled on device but has no active ranging sessions
- */
- int STATE_ENABLED_INACTIVE = 1;
-
- /**
- * Indicates that UWB is enabled and has active ranging session
- */
- int STATE_ENABLED_ACTIVE = 2;
-
- /**
- * Invoked when underlying UWB adapter's state is changed
- * <p>Invoked with the adapter's current state after registering an
- * {@link AdapterStateCallback} using
- * {@link UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback)}.
- *
- * <p>Possible reasons for the state to change are
- * {@link #STATE_CHANGED_REASON_SESSION_STARTED},
- * {@link #STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED},
- * {@link #STATE_CHANGED_REASON_SYSTEM_POLICY},
- * {@link #STATE_CHANGED_REASON_SYSTEM_BOOT},
- * {@link #STATE_CHANGED_REASON_ERROR_UNKNOWN}.
- *
- * <p>Possible values for the UWB state are
- * {@link #STATE_ENABLED_INACTIVE},
- * {@link #STATE_ENABLED_ACTIVE},
- * {@link #STATE_DISABLED}.
- *
- * @param state the UWB state; inactive, active or disabled
- * @param reason the reason for the state change
- */
- void onStateChanged(@State int state, @StateChangedReason int reason);
- }
-
- /**
- * Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance.
- *
- * @param ctx Context of the client.
- * @param adapter an instance of an {@link android.uwb.IUwbAdapter}
- */
- private UwbManager(@NonNull Context ctx, @NonNull IUwbAdapter adapter) {
- mContext = ctx;
- mUwbAdapter = adapter;
- mAdapterStateListener = new AdapterStateListener(adapter);
- mRangingManager = new RangingManager(adapter);
- }
-
- /**
- * @hide
- */
- public static UwbManager getInstance(@NonNull Context ctx) {
- IBinder b = ServiceManager.getService(SERVICE_NAME);
- if (b == null) {
- return null;
- }
-
- IUwbAdapter adapter = IUwbAdapter.Stub.asInterface(b);
- if (adapter == null) {
- return null;
- }
-
- return new UwbManager(ctx, adapter);
- }
-
- /**
- * Register an {@link AdapterStateCallback} to listen for UWB adapter state changes
- * <p>The provided callback will be invoked by the given {@link Executor}.
- *
- * <p>When first registering a callback, the callbacks's
- * {@link AdapterStateCallback#onStateChanged(int, int)} is immediately invoked to indicate
- * the current state of the underlying UWB adapter with the most recent
- * {@link AdapterStateCallback.StateChangedReason} that caused the change.
- *
- * @param executor an {@link Executor} to execute given callback
- * @param callback user implementation of the {@link AdapterStateCallback}
- */
- @RequiresPermission(permission.UWB_PRIVILEGED)
- public void registerAdapterStateCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull AdapterStateCallback callback) {
- mAdapterStateListener.register(executor, callback);
- }
-
- /**
- * Unregister the specified {@link AdapterStateCallback}
- * <p>The same {@link AdapterStateCallback} object used when calling
- * {@link #registerAdapterStateCallback(Executor, AdapterStateCallback)} must be used.
- *
- * <p>Callbacks are automatically unregistered when application process goes away
- *
- * @param callback user implementation of the {@link AdapterStateCallback}
- */
- @RequiresPermission(permission.UWB_PRIVILEGED)
- public void unregisterAdapterStateCallback(@NonNull AdapterStateCallback callback) {
- mAdapterStateListener.unregister(callback);
- }
-
- /**
- * Get a {@link PersistableBundle} with the supported UWB protocols and parameters.
- * <p>The {@link PersistableBundle} should be parsed using a support library
- *
- * <p>Android reserves the '^android.*' namespace</p>
- *
- * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters
- */
- @NonNull
- @RequiresPermission(permission.UWB_PRIVILEGED)
- public PersistableBundle getSpecificationInfo() {
- try {
- return mUwbAdapter.getSpecificationInfo();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the timestamp resolution for events in nanoseconds
- * <p>This value defines the maximum error of all timestamps for events reported to
- * {@link RangingSession.Callback}.
- *
- * @return the timestamp resolution in nanoseconds
- */
- @SuppressLint("MethodNameUnits")
- @RequiresPermission(permission.UWB_PRIVILEGED)
- public long elapsedRealtimeResolutionNanos() {
- try {
- return mUwbAdapter.getTimestampResolutionNanos();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Open a {@link RangingSession} with the given parameters
- * <p>The {@link RangingSession.Callback#onOpened(RangingSession)} function is called with a
- * {@link RangingSession} object used to control ranging when the session is successfully
- * opened.
- *
- * <p>If a session cannot be opened, then
- * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} will be invoked with the
- * appropriate {@link RangingSession.Callback.Reason}.
- *
- * <p>An open {@link RangingSession} will be automatically closed if client application process
- * dies.
- *
- * <p>A UWB support library must be used in order to construct the {@code parameter}
- * {@link PersistableBundle}.
- *
- * @param parameters the parameters that define the ranging session
- * @param executor {@link Executor} to run callbacks
- * @param callbacks {@link RangingSession.Callback} to associate with the
- * {@link RangingSession} that is being opened.
- *
- * @return an {@link CancellationSignal} that is able to be used to cancel the opening of a
- * {@link RangingSession} that has been requested through {@link #openRangingSession}
- * but has not yet been made available by
- * {@link RangingSession.Callback#onOpened(RangingSession)}.
- */
- @NonNull
- @RequiresPermission(allOf = {
- permission.UWB_PRIVILEGED,
- permission.UWB_RANGING
- })
- public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull RangingSession.Callback callbacks) {
- return mRangingManager.openSession(
- mContext.getAttributionSource(), parameters, executor, callbacks);
- }
-
- /**
- * Returns the current enabled/disabled state for UWB.
- *
- * Possible values are:
- * AdapterStateCallback#STATE_DISABLED
- * AdapterStateCallback#STATE_ENABLED_INACTIVE
- * AdapterStateCallback#STATE_ENABLED_ACTIVE
- *
- * @return value representing current enabled/disabled state for UWB.
- * @hide
- */
- public @AdapterStateCallback.State int getAdapterState() {
- return mAdapterStateListener.getAdapterState();
- }
-
- /**
- * Disables or enables UWB for a user
- *
- * @param enabled value representing intent to disable or enable UWB. If true any subsequent
- * calls to IUwbAdapter#openRanging will be allowed. If false, all active ranging sessions will
- * be closed and subsequent calls to IUwbAdapter#openRanging will be disallowed.
- *
- * @hide
- */
- public void setUwbEnabled(boolean enabled) {
- mAdapterStateListener.setEnabled(enabled);
- }
-}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 9cb0d1ff2c3f..e7ff978266a2 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1463,10 +1463,10 @@ public final class Display {
return false;
}
final Configuration config = mResources.getConfiguration();
- // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking
- // if the caller is the recents component.
+ // TODO(b/179308296) Temporarily - never report max bounds to only Launcher if the feature
+ // is disabled.
return config != null && !config.windowConfiguration.getMaxBounds().isEmpty()
- && !isRecentsComponent();
+ && (mDisplayInfo.shouldConstrainMetricsForLauncher || !isRecentsComponent());
}
/**
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 8e5f905e9c74..657251046551 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -306,6 +306,13 @@ public final class DisplayInfo implements Parcelable {
public float brightnessDefault;
/**
+ * @hide
+ * True if Display#getRealSize and getRealMetrics should be constrained for Launcher, false
+ * otherwise.
+ */
+ public boolean shouldConstrainMetricsForLauncher = false;
+
+ /**
* The {@link RoundedCorners} if present, otherwise {@code null}.
*/
@Nullable
@@ -381,7 +388,8 @@ public final class DisplayInfo implements Parcelable {
&& brightnessMinimum == other.brightnessMinimum
&& brightnessMaximum == other.brightnessMaximum
&& brightnessDefault == other.brightnessDefault
- && Objects.equals(roundedCorners, other.roundedCorners);
+ && Objects.equals(roundedCorners, other.roundedCorners)
+ && shouldConstrainMetricsForLauncher == other.shouldConstrainMetricsForLauncher;
}
@Override
@@ -432,6 +440,7 @@ public final class DisplayInfo implements Parcelable {
brightnessMaximum = other.brightnessMaximum;
brightnessDefault = other.brightnessDefault;
roundedCorners = other.roundedCorners;
+ shouldConstrainMetricsForLauncher = other.shouldConstrainMetricsForLauncher;
}
public void readFromParcel(Parcel source) {
@@ -488,6 +497,7 @@ public final class DisplayInfo implements Parcelable {
for (int i = 0; i < numUserDisabledFormats; i++) {
userDisabledHdrTypes[i] = source.readInt();
}
+ shouldConstrainMetricsForLauncher = source.readBoolean();
}
@Override
@@ -542,6 +552,7 @@ public final class DisplayInfo implements Parcelable {
for (int i = 0; i < userDisabledHdrTypes.length; i++) {
dest.writeInt(userDisabledHdrTypes[i]);
}
+ dest.writeBoolean(shouldConstrainMetricsForLauncher);
}
@Override
@@ -796,6 +807,8 @@ public final class DisplayInfo implements Parcelable {
sb.append(brightnessMaximum);
sb.append(", brightnessDefault ");
sb.append(brightnessDefault);
+ sb.append(", shouldConstrainMetricsForLauncher ");
+ sb.append(shouldConstrainMetricsForLauncher);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 25dda5b2e0bb..2884d2279bfd 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -171,6 +171,16 @@ public abstract class InputEventReceiver {
}
/**
+ * Called when the display for the window associated with the input channel has entered or
+ * exited touch mode.
+ *
+ * @param isInTouchMode {@code true} if the display showing the window associated with the
+ * input channel entered touch mode.
+ */
+ public void onTouchModeChanged(boolean isInTouchMode) {
+ }
+
+ /**
* Called when a batched input event is pending.
*
* The batched input event will continue to accumulate additional movement
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index ff2d2eb3d334..aaf53ee1cfc1 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -29,6 +29,7 @@ import android.graphics.Canvas;
import android.graphics.ColorSpace;
import android.graphics.HardwareRenderer;
import android.graphics.Matrix;
+import android.graphics.Point;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RenderNode;
@@ -408,6 +409,20 @@ public class Surface implements Parcelable {
}
/**
+ * Returns the default size of this Surface provided by the consumer of the surface.
+ * Should only be used by the producer of the surface.
+ *
+ * @hide
+ */
+ @NonNull
+ public Point getDefaultSize() {
+ synchronized (mLock) {
+ checkNotReleasedLocked();
+ return new Point(nativeGetWidth(mNativeObject), nativeGetHeight(mNativeObject));
+ }
+ }
+
+ /**
* Gets a {@link Canvas} for drawing into this surface.
*
* After drawing into the provided {@link Canvas}, the caller must
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 48ef27f4342d..a4e7a43cc934 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,6 +33,7 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.RenderNode;
@@ -237,15 +238,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
new SurfaceControl.Transaction();
/**
- * Transaction that should be used for
- * {@link RenderNode.PositionUpdateListener#positionChanged(long, int, int, int, int)}
- * The callback is invoked from a thread pool so it's not thread safe with other render thread
- * transactions. Keep the transactions for position changed callbacks on its own transaction.
- */
- private final SurfaceControl.Transaction mPositionChangedTransaction =
- new SurfaceControl.Transaction();
-
- /**
* A temporary transaction holder that should only be used when applying right away. There
* should be no assumption about thread safety for this transaction.
*/
@@ -295,7 +287,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
int defStyleRes, boolean disableBackgroundLayer) {
super(context, attrs, defStyleAttr, defStyleRes);
mUseBlastAdapter = useBlastAdapter(context);
- mRenderNode.addPositionUpdateListener(mPositionListener);
setWillNotDraw(true);
mDisableBackgroundLayer = disableBackgroundLayer;
@@ -943,6 +934,24 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
}
+
+ // The position update listener is used to safely share the surface size between render thread
+ // workers and the UI thread. Both threads need to know the surface size to determine the scale.
+ // The parent layer scales the surface size to view size. The child (BBQ) layer scales
+ // the buffer to the surface size. Both scales along with the window crop must be applied
+ // synchronously otherwise we may see flickers.
+ // When the listener is updated, we will get at least a single position update call so we can
+ // guarantee any changes we post will be applied.
+ private void replacePositionUpdateListener(int surfaceWidth, int surfaceHeight,
+ @Nullable Transaction geometryTransaction) {
+ if (mPositionListener != null) {
+ mRenderNode.removePositionUpdateListener(mPositionListener);
+ }
+ mPositionListener = new SurfaceViewPositionUpdateListener(surfaceWidth, surfaceHeight,
+ geometryTransaction);
+ mRenderNode.addPositionUpdateListener(mPositionListener);
+ }
+
private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator,
boolean creating, boolean sizeChanged, boolean hintChanged) {
boolean realSizeChanged = false;
@@ -985,13 +994,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// While creating the surface, we will set it's initial
// geometry. Outside of that though, we should generally
// leave it to the RenderThread.
- //
- // There is one more case when the buffer size changes we aren't yet
- // prepared to sync (as even following the transaction applying
- // we still need to latch a buffer).
- // b/28866173
- if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
- onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
+ Transaction geometryTransaction = new Transaction();
+ geometryTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+ if ((sizeChanged || hintChanged) && !creating) {
+ setBufferSize(geometryTransaction);
+ }
+ if (sizeChanged || creating || !isHardwareAccelerated()) {
+ onSetSurfacePositionAndScaleRT(geometryTransaction, mSurfaceControl,
mScreenRect.left, /*positionLeft*/
mScreenRect.top /*positionTop*/ ,
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
@@ -1002,17 +1011,31 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// use SCALING_MODE_SCALE and submit a larger size than the surface
// size.
if (mClipSurfaceToBounds && mClipBounds != null) {
- mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+ geometryTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
} else {
- mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+ geometryTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
mSurfaceHeight);
}
- }
- mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
- if ((sizeChanged || hintChanged) && !creating) {
- setBufferSize(mTmpTransaction);
- }
+ boolean applyChangesOnRenderThread =
+ sizeChanged && !creating && isHardwareAccelerated();
+ if (isHardwareAccelerated()) {
+ // This will consume the passed in transaction and the transaction will be
+ // applied on a render worker thread.
+ replacePositionUpdateListener(mSurfaceWidth, mSurfaceHeight,
+ applyChangesOnRenderThread ? geometryTransaction : null);
+ }
+ if (DEBUG_POSITION) {
+ Log.d(TAG, String.format(
+ "%d updateSurfacePosition %s"
+ + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+ System.identityHashCode(this),
+ applyChangesOnRenderThread ? "RenderWorker" : "UiThread",
+ mScreenRect.left, mScreenRect.top, mScreenRect.right,
+ mScreenRect.bottom, mSurfaceWidth, mSurfaceHeight));
+ }
+ }
+ mTmpTransaction.merge(geometryTransaction);
mTmpTransaction.apply();
updateEmbeddedAccessibilityMatrix();
@@ -1399,19 +1422,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mTmpTransaction.apply();
}
- private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
- Rect position) {
- onSetSurfacePositionAndScaleRT(t, surface,
- position.left /*positionLeft*/,
- position.top /*positionTop*/,
- position.width() / (float) mSurfaceWidth /*postScaleX*/,
- position.height() / (float) mSurfaceHeight /*postScaleY*/);
-
- if (mViewVisibility) {
- t.show(surface);
- }
- }
-
/**
* @return The last render position of the backing surface or an empty rect.
*
@@ -1421,13 +1431,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
return mRTLastReportedPosition;
}
- private void setParentSpaceRectangle(Rect position, long frameNumber, Transaction t) {
- final ViewRootImpl viewRoot = getViewRootImpl();
- applySurfaceTransforms(mSurfaceControl, t, position);
- applyChildSurfaceTransaction_renderWorker(t, viewRoot.mSurface, frameNumber);
- applyOrMergeTransaction(t, frameNumber);
- }
-
private void applyOrMergeTransaction(Transaction t, long frameNumber) {
final ViewRootImpl viewRoot = getViewRootImpl();
boolean useBLAST = viewRoot != null && useBLASTSync(viewRoot);
@@ -1440,9 +1443,24 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
private Rect mRTLastReportedPosition = new Rect();
-
- private RenderNode.PositionUpdateListener mPositionListener =
- new RenderNode.PositionUpdateListener() {
+ private Point mRTLastReportedSurfaceSize = new Point();
+
+ private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
+ int mRtSurfaceWidth = -1;
+ int mRtSurfaceHeight = -1;
+ private final SurfaceControl.Transaction mPositionChangedTransaction =
+ new SurfaceControl.Transaction();
+ boolean mPendingTransaction = false;
+
+ SurfaceViewPositionUpdateListener(int surfaceWidth, int surfaceHeight,
+ @Nullable Transaction t) {
+ mRtSurfaceWidth = surfaceWidth;
+ mRtSurfaceHeight = surfaceHeight;
+ if (t != null) {
+ mPositionChangedTransaction.merge(t);
+ mPendingTransaction = true;
+ }
+ }
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
@@ -1464,21 +1482,34 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top
&& mRTLastReportedPosition.right == right
- && mRTLastReportedPosition.bottom == bottom) {
+ && mRTLastReportedPosition.bottom == bottom
+ && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
+ && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight
+ && !mPendingTransaction) {
return;
}
try {
if (DEBUG_POSITION) {
Log.d(TAG, String.format(
"%d updateSurfacePosition RenderWorker, frameNr = %d, "
- + "position = [%d, %d, %d, %d]",
- System.identityHashCode(this), frameNumber,
- left, top, right, bottom));
+ + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
+ System.identityHashCode(SurfaceView.this), frameNumber,
+ left, top, right, bottom, mRtSurfaceWidth, mRtSurfaceHeight));
}
mRTLastReportedPosition.set(left, top, right, bottom);
- setParentSpaceRectangle(mRTLastReportedPosition, frameNumber,
- mPositionChangedTransaction);
- // Now overwrite mRTLastReportedPosition with our values
+ mRTLastReportedSurfaceSize.set(mRtSurfaceWidth, mRtSurfaceHeight);
+ onSetSurfacePositionAndScaleRT(mPositionChangedTransaction, mSurfaceControl,
+ mRTLastReportedPosition.left /*positionLeft*/,
+ mRTLastReportedPosition.top /*positionTop*/,
+ mRTLastReportedPosition.width() / (float) mRtSurfaceWidth /*postScaleX*/,
+ mRTLastReportedPosition.height() / (float) mRtSurfaceHeight /*postScaleY*/);
+ if (mViewVisibility) {
+ mPositionChangedTransaction.show(mSurfaceControl);
+ }
+ applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
+ getViewRootImpl().mSurface, frameNumber);
+ applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
+ mPendingTransaction = false;
} catch (Exception ex) {
Log.e(TAG, "Exception from repositionChild", ex);
}
@@ -1502,7 +1533,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
System.identityHashCode(this), frameNumber));
}
mRTLastReportedPosition.setEmpty();
-
+ mRTLastReportedSurfaceSize.set(-1, -1);
+ if (mPendingTransaction) {
+ Log.w(TAG, System.identityHashCode(SurfaceView.this)
+ + "Pending transaction cleared.");
+ mPositionChangedTransaction.clear();
+ mPendingTransaction = false;
+ }
if (mSurfaceControl == null) {
return;
}
@@ -1521,7 +1558,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
mRtHandlingPositionUpdates = false;
}
}
- };
+ }
+
+ private SurfaceViewPositionUpdateListener mPositionListener = null;
private SurfaceHolder.Callback[] getSurfaceCallbacks() {
SurfaceHolder.Callback[] callbacks;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f3ebe5bfec7c..ffc98d2c8e90 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -19816,6 +19816,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Check if this view can be scrolled horizontally in a certain direction.
*
+ * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+ * in response to user input or not.
+ *
* @param direction Negative to check scrolling left, positive to check scrolling right.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
@@ -19833,6 +19836,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Check if this view can be scrolled vertically in a certain direction.
*
+ * <p>This is without regard to whether the view is enabled or not, or if it will scroll
+ * in response to user input or not.
+ *
* @param direction Negative to check scrolling up, positive to check scrolling down.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 0a3d0da6da1e..495edab57abd 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -600,6 +600,8 @@ public class ViewConfiguration {
}
/**
+ * Used for both key and motion events.
+ *
* @return the duration in milliseconds before a press turns into
* a long press
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5bd3aefa25c5..ec21a581c915 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -9936,7 +9936,10 @@ public final class ViewRootImpl implements ViewParent,
if (!mUseMTRenderer) {
return;
}
- mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
+ // Only wait if it will report next draw.
+ if (mReportNextDraw) {
+ mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
+ }
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 5f036a348808..5185dc2543c7 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -843,9 +843,14 @@ public interface InputConnection {
/**
* Called back when the connected IME switches between fullscreen and normal modes.
*
- * <p>Note: On {@link android.os.Build.VERSION_CODES#O} and later devices, input methods are no
- * longer allowed to directly call this method at any time. To signal this event in the target
- * application, input methods should always call
+ * <p><p><strong>Editor authors:</strong> There is a bug on
+ * {@link android.os.Build.VERSION_CODES#O} and later devices that this method is called back
+ * on the main thread even when {@link #getHandler()} is overridden. This bug is fixed in
+ * {@link android.os.Build.VERSION_CODES#TIRAMISU}.</p>
+ *
+ * <p><p><strong>IME authors:</strong> On {@link android.os.Build.VERSION_CODES#O} and later
+ * devices, input methods are no longer allowed to directly call this method at any time.
+ * To signal this event in the target application, input methods should always call
* {@link InputMethodService#updateFullscreenMode()} instead. This approach should work on API
* {@link android.os.Build.VERSION_CODES#N_MR1} and prior devices.</p>
*
@@ -927,14 +932,20 @@ public interface InputConnection {
boolean requestCursorUpdates(int cursorUpdateMode);
/**
- * Called by the {@link InputMethodManager} to enable application developers to specify a
- * dedicated {@link Handler} on which incoming IPC method calls from input methods will be
- * dispatched.
+ * Called by the system to enable application developers to specify a dedicated thread on which
+ * {@link InputConnection} methods are called back.
*
- * <p>Note: This does nothing when called from input methods.</p>
+ * <p><strong>Editor authors</strong>: although you can return your custom subclasses of
+ * {@link Handler}, the system only uses {@link android.os.Looper} returned from
+ * {@link Handler#getLooper()}. You cannot intercept or cancel {@link InputConnection}
+ * callbacks by implementing this method.</p>
+ *
+ * <p><strong>IME authors</strong>: This method is not intended to be called from the IME. You
+ * will always receive {@code null}.</p>
*
* @return {@code null} to use the default {@link Handler}.
*/
+ @Nullable
Handler getHandler();
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c46b77f1dbe6..ab7e5a92284f 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -90,12 +90,12 @@ import com.android.internal.inputmethod.ImeTracing;
import com.android.internal.inputmethod.InputBindResult;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
+import com.android.internal.inputmethod.RemoteInputConnectionImpl;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason;
import com.android.internal.inputmethod.UnbindReason;
import com.android.internal.os.SomeArgs;
-import com.android.internal.view.IInputConnectionWrapper;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
@@ -365,7 +365,7 @@ public final class InputMethodManager {
final H mH;
// Our generic input connection if the current target does not have its own.
- private final IInputConnectionWrapper mFallbackInputConnection;
+ private final RemoteInputConnectionImpl mFallbackInputConnection;
private final int mDisplayId;
@@ -407,7 +407,7 @@ public final class InputMethodManager {
/**
* The InputConnection that was last retrieved from the served view.
*/
- IInputConnectionWrapper mServedInputConnection;
+ RemoteInputConnectionImpl mServedInputConnection;
/**
* The completions that were last provided by the served view.
*/
@@ -950,15 +950,15 @@ public final class InputMethodManager {
}
case MSG_REPORT_FULLSCREEN_MODE: {
final boolean fullscreen = msg.arg1 != 0;
- InputConnection ic = null;
+ RemoteInputConnectionImpl ic = null;
synchronized (mH) {
if (mFullscreenMode != fullscreen && mServedInputConnection != null) {
- ic = mServedInputConnection.getInputConnection();
+ ic = mServedInputConnection;
mFullscreenMode = fullscreen;
}
}
if (ic != null) {
- ic.reportFullscreenMode(fullscreen);
+ ic.dispatchReportFullscreenMode(fullscreen);
}
return;
}
@@ -1120,7 +1120,7 @@ public final class InputMethodManager {
mMainLooper = looper;
mH = new H(looper);
mDisplayId = displayId;
- mFallbackInputConnection = new IInputConnectionWrapper(looper,
+ mFallbackInputConnection = new RemoteInputConnectionImpl(looper,
new BaseInputConnection(this, false), this, null);
}
@@ -1381,8 +1381,7 @@ public final class InputMethodManager {
public boolean isAcceptingText() {
checkFocus();
synchronized (mH) {
- return mServedInputConnection != null
- && mServedInputConnection.getInputConnection() != null;
+ return mServedInputConnection != null && !mServedInputConnection.isFinished();
}
}
@@ -1938,7 +1937,7 @@ public final class InputMethodManager {
mServedInputConnection.deactivate();
mServedInputConnection = null;
}
- IInputConnectionWrapper servedInputConnection;
+ RemoteInputConnectionImpl servedInputConnection;
final int missingMethodFlags;
if (ic != null) {
mCursorSelStart = tba.initialSelStart;
@@ -1955,7 +1954,7 @@ public final class InputMethodManager {
} else {
icHandler = ic.getHandler();
}
- servedInputConnection = new IInputConnectionWrapper(
+ servedInputConnection = new RemoteInputConnectionImpl(
icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view);
} else {
servedInputConnection = null;
diff --git a/core/java/android/view/translation/Translator.java b/core/java/android/view/translation/Translator.java
index edd0d16a5ccb..606f39d6e25e 100644
--- a/core/java/android/view/translation/Translator.java
+++ b/core/java/android/view/translation/Translator.java
@@ -18,6 +18,7 @@ package android.view.translation;
import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
import static android.view.translation.TranslationManager.SYNC_CALLS_TIMEOUT_MS;
+import static android.view.translation.UiTranslationController.DEBUG;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
@@ -38,7 +39,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -395,27 +395,26 @@ public class Translator {
private static class TranslationResponseCallbackImpl extends ITranslationCallback.Stub {
- private final WeakReference<Consumer<TranslationResponse>> mCallback;
- private final WeakReference<Executor> mExecutor;
+ private final Consumer<TranslationResponse> mCallback;
+ private final Executor mExecutor;
TranslationResponseCallbackImpl(Consumer<TranslationResponse> callback, Executor executor) {
- mCallback = new WeakReference<>(callback);
- mExecutor = new WeakReference<>(executor);
+ mCallback = callback;
+ mExecutor = executor;
}
@Override
public void onTranslationResponse(TranslationResponse response) throws RemoteException {
- final Consumer<TranslationResponse> callback = mCallback.get();
+ if (DEBUG) {
+ Log.i(TAG, "onTranslationResponse called.");
+ }
final Runnable runnable =
- () -> callback.accept(response);
- if (callback != null) {
- final Executor executor = mExecutor.get();
- final long token = Binder.clearCallingIdentity();
- try {
- executor.execute(runnable);
- } finally {
- restoreCallingIdentity(token);
- }
+ () -> mCallback.accept(response);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(runnable);
+ } finally {
+ restoreCallingIdentity(token);
}
}
}
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index b7de7b8d217b..702a8baf0f15 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -23,6 +23,7 @@ import static android.app.ActivityOptions.ANIM_SCALE_UP;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -94,8 +95,16 @@ public final class TransitionInfo implements Parcelable {
/** The container can show on top of lock screen. */
public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6;
+ /**
+ * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is
+ * used to prevent seamless rotation.
+ * TODO(b/194540864): Once we can include all windows in transition, then replace this with
+ * something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations.
+ */
+ public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7;
+
/** The first unused bit. This can be used by remotes to attach custom flags to this change. */
- public static final int FLAG_FIRST_CUSTOM = 1 << 7;
+ public static final int FLAG_FIRST_CUSTOM = 1 << 8;
/** @hide */
@IntDef(prefix = { "FLAG_" }, value = {
@@ -107,6 +116,7 @@ public final class TransitionInfo implements Parcelable {
FLAG_IS_VOICE_INTERACTION,
FLAG_IS_DISPLAY,
FLAG_OCCLUDES_KEYGUARD,
+ FLAG_DISPLAY_HAS_ALERT_WINDOWS,
FLAG_FIRST_CUSTOM
})
public @interface ChangeFlags {}
@@ -209,6 +219,10 @@ public final class TransitionInfo implements Parcelable {
return mOptions;
}
+ /**
+ * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom
+ * in Z (meaning index 0 is the top-most container).
+ */
@NonNull
public List<Change> getChanges() {
return mChanges;
@@ -290,6 +304,9 @@ public final class TransitionInfo implements Parcelable {
if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) {
sb.append((sb.length() == 0 ? "" : "|") + "OCCLUDES_KEYGUARD");
}
+ if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+ sb.append((sb.length() == 0 ? "" : "|") + "DISPLAY_HAS_ALERT_WINDOWS");
+ }
if ((flags & FLAG_FIRST_CUSTOM) != 0) {
sb.append((sb.length() == 0 ? "" : "|") + "FIRST_CUSTOM");
}
@@ -335,8 +352,10 @@ public final class TransitionInfo implements Parcelable {
private final Rect mEndAbsBounds = new Rect();
private final Point mEndRelOffset = new Point();
private ActivityManager.RunningTaskInfo mTaskInfo = null;
+ private boolean mAllowEnterPip;
private int mStartRotation = ROTATION_UNDEFINED;
private int mEndRotation = ROTATION_UNDEFINED;
+ private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
mContainer = container;
@@ -354,8 +373,10 @@ public final class TransitionInfo implements Parcelable {
mEndAbsBounds.readFromParcel(in);
mEndRelOffset.readFromParcel(in);
mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ mAllowEnterPip = in.readBoolean();
mStartRotation = in.readInt();
mEndRotation = in.readInt();
+ mRotationAnimation = in.readInt();
}
/** Sets the parent of this change's container. The parent must be a participant or null. */
@@ -396,12 +417,25 @@ public final class TransitionInfo implements Parcelable {
mTaskInfo = taskInfo;
}
+ /** Sets the allowEnterPip flag which represents AppOpsManager check on PiP permission */
+ public void setAllowEnterPip(boolean allowEnterPip) {
+ mAllowEnterPip = allowEnterPip;
+ }
+
/** Sets the start and end rotation of this container. */
public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) {
mStartRotation = start;
mEndRotation = end;
}
+ /**
+ * Sets the app-requested animation type for rotation. Will be one of the
+ * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams};
+ */
+ public void setRotationAnimation(int anim) {
+ mRotationAnimation = anim;
+ }
+
/** @return the container that is changing. May be null if non-remotable (eg. activity) */
@Nullable
public WindowContainerToken getContainer() {
@@ -465,6 +499,10 @@ public final class TransitionInfo implements Parcelable {
return mTaskInfo;
}
+ public boolean getAllowEnterPip() {
+ return mAllowEnterPip;
+ }
+
public int getStartRotation() {
return mStartRotation;
}
@@ -473,6 +511,11 @@ public final class TransitionInfo implements Parcelable {
return mEndRotation;
}
+ /** @return the rotation animation. */
+ public int getRotationAnimation() {
+ return mRotationAnimation;
+ }
+
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -485,8 +528,10 @@ public final class TransitionInfo implements Parcelable {
mEndAbsBounds.writeToParcel(dest, flags);
mEndRelOffset.writeToParcel(dest, flags);
dest.writeTypedObject(mTaskInfo, flags);
+ dest.writeBoolean(mAllowEnterPip);
dest.writeInt(mStartRotation);
dest.writeInt(mEndRotation);
+ dest.writeInt(mRotationAnimation);
}
@NonNull
@@ -514,7 +559,7 @@ public final class TransitionInfo implements Parcelable {
return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
+ " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
+ mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
- + mStartRotation + "->" + mEndRotation + "}";
+ + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + "}";
}
}
diff --git a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
index 3a108e7e1d94..06640cb4ee06 100644
--- a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
@@ -18,5 +18,6 @@ package com.android.internal.app;
// Iterface to observe op starts
oneway interface IAppOpsStartedCallback {
- void opStarted(int op, int uid, String packageName, String attributionTag, int flags, int mode);
+ void opStarted(int op, int uid, String packageName, String attributionTag, int flags, int mode,
+ int startedType, int attributionFlags, int attributionChainId);
}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index 191bdf3cbbd7..0c2701219ef4 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.view;
+package com.android.internal.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,25 +40,29 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.SurroundingText;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.inputmethod.IBooleanResultCallback;
-import com.android.internal.inputmethod.ICharSequenceResultCallback;
-import com.android.internal.inputmethod.IExtractedTextResultCallback;
-import com.android.internal.inputmethod.IIntResultCallback;
-import com.android.internal.inputmethod.ISurroundingTextResultCallback;
-import com.android.internal.inputmethod.ImeTracing;
-import com.android.internal.inputmethod.InputConnectionProtoDumper;
+import com.android.internal.view.IInputContext;
import java.lang.ref.WeakReference;
-public final class IInputConnectionWrapper extends IInputContext.Stub {
- private static final String TAG = "IInputConnectionWrapper";
+/**
+ * Takes care of remote method invocations of {@link InputConnection} in the IME client side.
+ *
+ * <p>{@link android.inputmethodservice.RemoteInputConnection} code is executed in the IME process.
+ * It makes IInputContext binder calls under the hood. {@link RemoteInputConnectionImpl} receives
+ * {@link IInputContext} binder calls in the IME client (editor app) process, and forwards them to
+ * {@link InputConnection} that the IME client provided, on the {@link Looper} associated to the
+ * {@link InputConnection}.</p>
+ */
+public final class RemoteInputConnectionImpl extends IInputContext.Stub {
+ private static final String TAG = "RemoteInputConnectionImpl";
private static final boolean DEBUG = false;
@GuardedBy("mLock")
@Nullable
private InputConnection mInputConnection;
- private final Looper mMainLooper;
+ @NonNull
+ private final Looper mLooper;
private final Handler mH;
private final Object mLock = new Object();
@@ -68,24 +72,31 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
- public IInputConnectionWrapper(@NonNull Looper mainLooper,
+ public RemoteInputConnectionImpl(@NonNull Looper looper,
@NonNull InputConnection inputConnection,
@NonNull InputMethodManager inputMethodManager, @Nullable View servedView) {
mInputConnection = inputConnection;
- mMainLooper = mainLooper;
- mH = new Handler(mMainLooper);
+ mLooper = looper;
+ mH = new Handler(mLooper);
mParentInputMethodManager = inputMethodManager;
mServedView = new WeakReference<>(servedView);
}
+ /**
+ * @return {@link InputConnection} to which incoming IPCs will be dispatched.
+ */
@Nullable
- public InputConnection getInputConnection() {
+ private InputConnection getInputConnection() {
synchronized (mLock) {
return mInputConnection;
}
}
- private boolean isFinished() {
+ /**
+ * @return {@code true} until the target {@link InputConnection} receives
+ * {@link InputConnection#closeConnection()} as a result of {@link #deactivate()}.
+ */
+ public boolean isFinished() {
synchronized (mLock) {
return mFinished;
}
@@ -99,36 +110,70 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
return mServedView.get();
}
+ /**
+ * Called when this object needs to be permanently deactivated.
+ *
+ * <p>Multiple invocations will be simply ignored.</p>
+ */
public void deactivate() {
if (isFinished()) {
// This is a small performance optimization. Still only the 1st call of
// reportFinish() will take effect.
return;
}
- closeConnection();
-
- // Notify the app that the InputConnection was closed.
- final View servedView = mServedView.get();
- if (servedView != null) {
- final Handler handler = servedView.getHandler();
- // The handler is null if the view is already detached. When that's the case, for
- // now, we simply don't dispatch this callback.
- if (handler != null) {
- if (DEBUG) {
- Log.v(TAG, "Calling View.onInputConnectionClosed: view=" + servedView);
- }
- if (handler.getLooper().isCurrentThread()) {
- servedView.onInputConnectionClosedInternal();
- } else {
- handler.post(servedView::onInputConnectionClosedInternal);
+ dispatch(() -> {
+ // Note that we do not need to worry about race condition here, because 1) mFinished is
+ // updated only inside this block, and 2) the code here is running on a Handler hence we
+ // assume multiple closeConnection() tasks will not be handled at the same time.
+ if (isFinished()) {
+ return;
+ }
+ Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection");
+ try {
+ InputConnection ic = getInputConnection();
+ // Note we do NOT check isActive() here, because this is safe
+ // for an IME to call at any time, and we need to allow it
+ // through to clean up our state after the IME has switched to
+ // another client.
+ if (ic == null) {
+ return;
+ }
+ @MissingMethodFlags
+ final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic);
+ if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) {
+ ic.closeConnection();
}
+ } finally {
+ synchronized (mLock) {
+ mInputConnection = null;
+ mFinished = true;
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_INPUT);
}
- }
+
+ // Notify the app that the InputConnection was closed.
+ final View servedView = mServedView.get();
+ if (servedView != null) {
+ final Handler handler = servedView.getHandler();
+ // The handler is null if the view is already detached. When that's the case, for
+ // now, we simply don't dispatch this callback.
+ if (handler != null) {
+ if (DEBUG) {
+ Log.v(TAG, "Calling View.onInputConnectionClosed: view=" + servedView);
+ }
+ if (handler.getLooper().isCurrentThread()) {
+ servedView.onInputConnectionClosedInternal();
+ } else {
+ handler.post(servedView::onInputConnectionClosedInternal);
+ }
+ }
+ }
+ });
}
@Override
public String toString() {
- return "IInputConnectionWrapper{"
+ return "RemoteInputConnectionImpl{"
+ "connection=" + getInputConnection()
+ " finished=" + isFinished()
+ " mParentInputMethodManager.isActive()=" + mParentInputMethodManager.isActive()
@@ -136,20 +181,45 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
+ "}";
}
+ /**
+ * Called by {@link InputMethodManager} to dump the editor state.
+ *
+ * @param proto {@link ProtoOutputStream} to which the editor state should be dumped.
+ * @param fieldId the ID to be passed to
+ * {@link DumpableInputConnection#dumpDebug(ProtoOutputStream, long)}.
+ */
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
synchronized (mLock) {
- // Check that the call is initiated in the main thread of the current InputConnection
+ // Check that the call is initiated in the target thread of the current InputConnection
// {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are
// executed on this thread. Otherwise the messages are dispatched to the correct thread
// in IInputConnectionWrapper, but this is not wanted while dumpng, for performance
// reasons.
if ((mInputConnection instanceof DumpableInputConnection)
- && Looper.myLooper() == mMainLooper) {
+ && mLooper.isCurrentThread()) {
((DumpableInputConnection) mInputConnection).dumpDebug(proto, fieldId);
}
}
}
+ /**
+ * Invoke {@link InputConnection#reportFullscreenMode(boolean)} or schedule it on the target
+ * thread associated with {@link InputConnection#getHandler()}.
+ *
+ * @param enabled the parameter to be passed to
+ * {@link InputConnection#reportFullscreenMode(boolean)}.
+ */
+ public void dispatchReportFullscreenMode(boolean enabled) {
+ dispatch(() -> {
+ final InputConnection ic = getInputConnection();
+ if (ic == null || !isActive()) {
+ return;
+ }
+ ic.reportFullscreenMode(enabled);
+ });
+ }
+
+ @Override
public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor");
@@ -180,6 +250,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextBeforeCursor");
@@ -210,6 +281,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void getSelectedText(int flags, ICharSequenceResultCallback callback) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSelectedText");
@@ -240,11 +312,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
- /**
- * Dispatches the request for retrieving surrounding text.
- *
- * <p>See {@link InputConnection#getSurroundingText(int, int, int)}.
- */
+ @Override
public void getSurroundingText(int beforeLength, int afterLength, int flags,
ISurroundingTextResultCallback callback) {
dispatch(() -> {
@@ -276,6 +344,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void getCursorCapsMode(int reqModes, IIntResultCallback callback) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getCursorCapsMode");
@@ -306,6 +375,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void getExtractedText(ExtractedTextRequest request, int flags,
IExtractedTextResultCallback callback) {
dispatch(() -> {
@@ -337,6 +407,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void commitText(CharSequence text, int newCursorPosition) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitText");
@@ -353,6 +424,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void commitCompletion(CompletionInfo text) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCompletion");
@@ -369,6 +441,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void commitCorrection(CorrectionInfo info) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCorrection");
@@ -385,6 +458,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void setSelection(int start, int end) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setSelection");
@@ -401,6 +475,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void performEditorAction(int id) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performEditorAction");
@@ -417,6 +492,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void performContextMenuAction(int id) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performContextMenuAction");
@@ -433,6 +509,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void setComposingRegion(int start, int end) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingRegion");
@@ -449,6 +526,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void setComposingText(CharSequence text, int newCursorPosition) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingText");
@@ -465,6 +543,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void finishComposingText() {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#finishComposingText");
@@ -493,6 +572,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void sendKeyEvent(KeyEvent event) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#sendKeyEvent");
@@ -509,6 +589,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void clearMetaKeyStates(int states) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#clearMetaKeyStates");
@@ -525,6 +606,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void deleteSurroundingText(int beforeLength, int afterLength) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#deleteSurroundingText");
@@ -541,6 +623,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT,
@@ -558,6 +641,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void beginBatchEdit() {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#beginBatchEdit");
@@ -574,6 +658,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void endBatchEdit() {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#endBatchEdit");
@@ -590,11 +675,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
- /**
- * Dispatches the request for performing spell check.
- *
- * @see InputConnection#performSpellCheck()
- */
+ @Override
public void performSpellCheck() {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performSpellCheck");
@@ -611,6 +692,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void performPrivateCommand(String action, Bundle data) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand");
@@ -627,6 +709,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
+ @Override
public void requestCursorUpdates(int cursorUpdateMode, IBooleanResultCallback callback) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#requestCursorUpdates");
@@ -651,39 +734,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
- public void closeConnection() {
- dispatch(() -> {
- // Note that we do not need to worry about race condition here, because 1) mFinished is
- // updated only inside this block, and 2) the code here is running on a Handler hence we
- // assume multiple closeConnection() tasks will not be handled at the same time.
- if (isFinished()) {
- return;
- }
- Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection");
- try {
- InputConnection ic = getInputConnection();
- // Note we do NOT check isActive() here, because this is safe
- // for an IME to call at any time, and we need to allow it
- // through to clean up our state after the IME has switched to
- // another client.
- if (ic == null) {
- return;
- }
- @MissingMethodFlags
- final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic);
- if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) {
- ic.closeConnection();
- }
- } finally {
- synchronized (mLock) {
- mInputConnection = null;
- mFinished = true;
- }
- Trace.traceEnd(Trace.TRACE_TAG_INPUT);
- }
- });
- }
-
+ @Override
public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
IBooleanResultCallback callback) {
dispatch(() -> {
@@ -715,11 +766,7 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
});
}
- /**
- * Dispatches the request for setting ime consumes input.
- *
- * <p>See {@link InputConnection#setImeConsumesInput(boolean)}.
- */
+ @Override
public void setImeConsumesInput(boolean imeConsumesInput) {
dispatch(() -> {
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setImeConsumesInput");
@@ -737,10 +784,9 @@ public final class IInputConnectionWrapper extends IInputContext.Stub {
}
private void dispatch(@NonNull Runnable runnable) {
- // If we are calling this from the main thread, then we can call
- // right through. Otherwise, we need to send the message to the
- // main thread.
- if (mMainLooper.isCurrentThread()) {
+ // If we are calling this from the target thread, then we can call right through.
+ // Otherwise, we need to send the message to the target thread.
+ if (mLooper.isCurrentThread()) {
runnable.run();
return;
}
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 0c2d2a9bcf41..3191e23a9883 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -53,6 +53,8 @@ public class NotificationActionListLayout extends LinearLayout {
private int mEmphasizedHeight;
private int mRegularHeight;
@DimenRes private int mCollapsibleIndentDimen = R.dimen.notification_actions_padding_start;
+ int mNumNotGoneChildren;
+ int mNumPriorityChildren;
public NotificationActionListLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -76,15 +78,14 @@ public class NotificationActionListLayout extends LinearLayout {
&& ((EmphasizedNotificationButton) actionView).isPriority();
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int N = getChildCount();
+ private void countAndRebuildMeasureOrder() {
+ final int numChildren = getChildCount();
int textViews = 0;
int otherViews = 0;
- int notGoneChildren = 0;
- int priorityChildren = 0;
+ mNumNotGoneChildren = 0;
+ mNumPriorityChildren = 0;
- for (int i = 0; i < N; i++) {
+ for (int i = 0; i < numChildren; i++) {
View c = getChildAt(i);
if (c instanceof TextView) {
textViews++;
@@ -92,9 +93,9 @@ public class NotificationActionListLayout extends LinearLayout {
otherViews++;
}
if (c.getVisibility() != GONE) {
- notGoneChildren++;
+ mNumNotGoneChildren++;
if (isPriority(c)) {
- priorityChildren++;
+ mNumPriorityChildren++;
}
}
}
@@ -119,17 +120,20 @@ public class NotificationActionListLayout extends LinearLayout {
if (needRebuild) {
rebuildMeasureOrder(textViews, otherViews);
}
+ }
+ private int measureAndGetUsedWidth(int widthMeasureSpec, int heightMeasureSpec, int innerWidth,
+ boolean collapsePriorityActions) {
+ final int numChildren = getChildCount();
final boolean constrained =
MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED;
-
- final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
final int otherSize = mMeasureOrderOther.size();
int usedWidth = 0;
+ int maxPriorityWidth = 0;
int measuredChildren = 0;
int measuredPriorityChildren = 0;
- for (int i = 0; i < N; i++) {
+ for (int i = 0; i < numChildren; i++) {
// Measure shortest children first. To avoid measuring twice, we approximate by looking
// at the text length.
final boolean isPriority;
@@ -154,12 +158,20 @@ public class NotificationActionListLayout extends LinearLayout {
// measure in the order of (approx.) size, a large view can still take more than its
// share if the others are small.
int availableWidth = innerWidth - usedWidth;
- int unmeasuredChildren = notGoneChildren - measuredChildren;
+ int unmeasuredChildren = mNumNotGoneChildren - measuredChildren;
int maxWidthForChild = availableWidth / unmeasuredChildren;
- if (isPriority) {
+ if (isPriority && collapsePriorityActions) {
+ // Collapsing the actions to just the width required to show the icon.
+ if (maxPriorityWidth == 0) {
+ maxPriorityWidth = getResources().getDimensionPixelSize(
+ R.dimen.notification_actions_collapsed_priority_width);
+ }
+ maxWidthForChild = maxPriorityWidth + lp.leftMargin + lp.rightMargin;
+ } else if (isPriority) {
// Priority children get a larger maximum share of the total space:
// maximum priority share = (nPriority + 1) / (MAX + 1)
- int unmeasuredPriorityChildren = priorityChildren - measuredPriorityChildren;
+ int unmeasuredPriorityChildren = mNumPriorityChildren
+ - measuredPriorityChildren;
int unmeasuredOtherChildren = unmeasuredChildren - unmeasuredPriorityChildren;
int widthReservedForOtherChildren = innerWidth * unmeasuredOtherChildren
/ (Notification.MAX_ACTION_BUTTONS + 1);
@@ -187,6 +199,19 @@ public class NotificationActionListLayout extends LinearLayout {
} else {
mExtraStartPadding = 0;
}
+ return usedWidth;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ countAndRebuildMeasureOrder();
+ final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
+ int usedWidth = measureAndGetUsedWidth(widthMeasureSpec, heightMeasureSpec, innerWidth,
+ false /* collapsePriorityButtons */);
+ if (mNumPriorityChildren != 0 && usedWidth >= innerWidth) {
+ usedWidth = measureAndGetUsedWidth(widthMeasureSpec, heightMeasureSpec, innerWidth,
+ true /* collapsePriorityButtons */);
+ }
mTotalWidth = usedWidth + mPaddingRight + mPaddingLeft + mExtraStartPadding;
setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec),
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 4fc135c515b0..627381c620c1 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -66,15 +66,15 @@ public class PointerLocationView extends View implements InputDeviceListener,
private float[] mTraceY = new float[32];
private boolean[] mTraceCurrent = new boolean[32];
private int mTraceCount;
-
+
// True if the pointer is down.
@UnsupportedAppUsage
private boolean mCurDown;
-
+
// Most recent coordinates.
private PointerCoords mCoords = new PointerCoords();
private int mToolType;
-
+
// Most recent velocity.
private float mXVelocity;
private float mYVelocity;
@@ -107,7 +107,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
float[] newTraceX = new float[traceCapacity];
System.arraycopy(mTraceX, 0, newTraceX, 0, mTraceCount);
mTraceX = newTraceX;
-
+
float[] newTraceY = new float[traceCapacity];
System.arraycopy(mTraceY, 0, newTraceY, 0, mTraceCount);
mTraceY = newTraceY;
@@ -116,7 +116,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
System.arraycopy(mTraceCurrent, 0, newTraceCurrent, 0, mTraceCount);
mTraceCurrent= newTraceCurrent;
}
-
+
mTraceX[mTraceCount] = x;
mTraceY[mTraceCount] = y;
mTraceCurrent[mTraceCount] = current;
@@ -162,7 +162,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
@UnsupportedAppUsage
private boolean mPrintCoords = true;
-
+
public PointerLocationView(Context c) {
super(c);
setFocusableInTouchMode(true);
@@ -211,7 +211,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
PointerState ps = new PointerState();
mPointers.add(ps);
mActivePointerId = 0;
-
+
mVelocity = VelocityTracker.obtain();
String altStrategy = SystemProperties.get(ALT_STRATEGY_PROPERY_KEY);
@@ -252,7 +252,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
+ " bottom=" + mTextMetrics.bottom);
}
}
-
+
// Draw an oval. When angle is 0 radians, orients the major axis vertically,
// angles less than or greater than 0 radians rotate the major axis left or right.
private RectF mReusableOvalRect = new RectF();
@@ -399,7 +399,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
}
private void drawLabels(Canvas canvas) {
- if (mActivePointerId < 0) {
+ if (mActivePointerId < 0 || mActivePointerId >= mPointers.size()) {
return;
}
@@ -614,8 +614,8 @@ public class PointerLocationView extends View implements InputDeviceListener,
NP++;
}
- if (mActivePointerId < 0 ||
- !mPointers.get(mActivePointerId).mCurDown) {
+ if (mActivePointerId < 0 || mActivePointerId >= NP
+ || !mPointers.get(mActivePointerId).mCurDown) {
mActivePointerId = id;
}
@@ -710,7 +710,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
invalidate();
}
-
+
@Override
public boolean onTouchEvent(MotionEvent event) {
onPointerEvent(event);
@@ -862,16 +862,16 @@ public class PointerLocationView extends View implements InputDeviceListener,
private static final class FasterStringBuilder {
private char[] mChars;
private int mLength;
-
+
public FasterStringBuilder() {
mChars = new char[64];
}
-
+
public FasterStringBuilder clear() {
mLength = 0;
return this;
}
-
+
public FasterStringBuilder append(String value) {
final int valueLength = value.length();
final int index = reserve(valueLength);
@@ -879,11 +879,11 @@ public class PointerLocationView extends View implements InputDeviceListener,
mLength += valueLength;
return this;
}
-
+
public FasterStringBuilder append(int value) {
return append(value, 0);
}
-
+
public FasterStringBuilder append(int value, int zeroPadWidth) {
final boolean negative = value < 0;
if (negative) {
@@ -893,16 +893,16 @@ public class PointerLocationView extends View implements InputDeviceListener,
return this;
}
}
-
+
int index = reserve(11);
final char[] chars = mChars;
-
+
if (value == 0) {
chars[index++] = '0';
mLength += 1;
return this;
}
-
+
if (negative) {
chars[index++] = '-';
}
@@ -916,18 +916,18 @@ public class PointerLocationView extends View implements InputDeviceListener,
chars[index++] = '0';
}
}
-
+
do {
int digit = value / divisor;
value -= digit * divisor;
divisor /= 10;
chars[index++] = (char) (digit + '0');
} while (divisor != 0);
-
+
mLength = index;
return this;
}
-
+
public FasterStringBuilder append(float value, int precision) {
int scale = 1;
for (int i = 0; i < precision; i++) {
@@ -947,15 +947,15 @@ public class PointerLocationView extends View implements InputDeviceListener,
value -= Math.floor(value);
append((int) (value * scale), precision);
}
-
+
return this;
}
-
+
@Override
public String toString() {
return new String(mChars, 0, mLength);
}
-
+
private int reserve(int length) {
final int oldLength = mLength;
final int newLength = mLength + length;
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a6d038d83234..8a1f1a09b3c9 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2432,6 +2432,12 @@ android_media_AudioSystem_setAssistantUid(JNIEnv *env, jobject thiz, jint uid)
return (jint)nativeToJavaStatus(status);
}
+static jint android_media_AudioSystem_setHotwordDetectionServiceUid(JNIEnv *env, jobject thiz,
+ jint uid) {
+ status_t status = AudioSystem::setHotwordDetectionServiceUid(uid);
+ return (jint)nativeToJavaStatus(status);
+}
+
static jint
android_media_AudioSystem_setA11yServicesUids(JNIEnv *env, jobject thiz, jintArray uids) {
std::vector<uid_t> nativeUidsVector;
@@ -2804,6 +2810,8 @@ static const JNINativeMethod gMethods[] =
{"setSurroundFormatEnabled", "(IZ)I",
(void *)android_media_AudioSystem_setSurroundFormatEnabled},
{"setAssistantUid", "(I)I", (void *)android_media_AudioSystem_setAssistantUid},
+ {"setHotwordDetectionServiceUid", "(I)I",
+ (void *)android_media_AudioSystem_setHotwordDetectionServiceUid},
{"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
{"isHapticPlaybackSupported", "()Z",
(void *)android_media_AudioSystem_isHapticPlaybackSupported},
diff --git a/core/jni/android_os_ServiceManager.cpp b/core/jni/android_os_ServiceManager.cpp
index c7479492d404..d642d0ebbfc1 100644
--- a/core/jni/android_os_ServiceManager.cpp
+++ b/core/jni/android_os_ServiceManager.cpp
@@ -29,11 +29,8 @@ namespace android {
// Native because we have a client-side wait in waitForService() and we do not
// want an unnecessary second copy of it.
-static jobject android_os_ServiceManager_waitForService(
- JNIEnv *env,
- jclass /* clazzObj */,
- jstring serviceNameObj) {
-
+static jobject android_os_ServiceManager_waitForServiceNative(JNIEnv* env, jclass /* clazzObj */,
+ jstring serviceNameObj) {
const jchar* serviceName = env->GetStringCritical(serviceNameObj, nullptr);
if (!serviceName) {
jniThrowNullPointerException(env, nullptr);
@@ -55,12 +52,9 @@ static jobject android_os_ServiceManager_waitForService(
// ----------------------------------------------------------------------------
static const JNINativeMethod method_table[] = {
- /* name, signature, funcPtr */
- {
- "waitForService",
- "(Ljava/lang/String;)Landroid/os/IBinder;",
- (void*)android_os_ServiceManager_waitForService
- },
+ /* name, signature, funcPtr */
+ {"waitForServiceNative", "(Ljava/lang/String;)Landroid/os/IBinder;",
+ (void*)android_os_ServiceManager_waitForServiceNative},
};
int register_android_os_ServiceManager(JNIEnv* env) {
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index a699f912806d..7b79b3844a86 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -54,6 +54,7 @@ static struct {
jmethodID onPointerCaptureEvent;
jmethodID onDragEvent;
jmethodID onBatchedInputEventPending;
+ jmethodID onTouchModeChanged;
} gInputEventReceiverClassInfo;
// Add prefix to the beginning of each line in 'str'
@@ -424,6 +425,18 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
finishInputEvent(seq, true /* handled */);
continue;
}
+ case AINPUT_EVENT_TYPE_TOUCH_MODE: {
+ const TouchModeEvent* touchModeEvent = static_cast<TouchModeEvent*>(inputEvent);
+ if (kDebugDispatchCycle) {
+ ALOGD("channel '%s' ~ Received touch mode event: isInTouchMode=%s",
+ getInputChannelName().c_str(), toString(touchModeEvent->isInTouchMode()));
+ }
+ env->CallVoidMethod(receiverObj.get(),
+ gInputEventReceiverClassInfo.onTouchModeChanged,
+ jboolean(touchModeEvent->isInTouchMode()));
+ finishInputEvent(seq, true /* handled */);
+ continue;
+ }
default:
assert(false); // InputConsumer should prevent this from ever happening
diff --git a/core/proto/android/server/accessibilitytrace.proto b/core/proto/android/server/accessibilitytrace.proto
index 41fecfd6cdb7..0ce39abfe352 100644
--- a/core/proto/android/server/accessibilitytrace.proto
+++ b/core/proto/android/server/accessibilitytrace.proto
@@ -59,4 +59,5 @@ message AccessibilityTraceProto {
optional AccessibilityDumpProto accessibility_service = 10;
optional com.android.server.wm.WindowManagerServiceDumpProto window_manager_service = 11;
+ optional string cpu_stats = 12;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fffc37c9a6c5..f924229a8fa4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -552,6 +552,8 @@
<protected-broadcast android:name="com.android.server.telecom.intent.action.CALLS_ADD_ENTRY" />
<protected-broadcast android:name="com.android.settings.location.MODE_CHANGING" />
<protected-broadcast android:name="com.android.settings.bluetooth.ACTION_DISMISS_PAIRING" />
+ <protected-broadcast android:name="com.android.settings.network.DELETE_SUBSCRIPTION" />
+ <protected-broadcast android:name="com.android.settings.network.SWITCH_TO_SUBSCRIPTION" />
<protected-broadcast android:name="com.android.settings.wifi.action.NETWORK_REQUEST" />
<protected-broadcast android:name="NotificationManagerService.TIMEOUT" />
diff --git a/core/res/res/drawable/btn_notification_emphasized.xml b/core/res/res/drawable/btn_notification_emphasized.xml
index 29c51f2a33c9..7c09fb889c48 100644
--- a/core/res/res/drawable/btn_notification_emphasized.xml
+++ b/core/res/res/drawable/btn_notification_emphasized.xml
@@ -24,9 +24,9 @@
android:insetBottom="@dimen/button_inset_vertical_material">
<shape android:shape="rectangle">
<corners android:radius="@dimen/notification_action_button_radius" />
- <padding android:left="12dp"
+ <padding android:left="16dp"
android:top="@dimen/button_padding_vertical_material"
- android:right="12dp"
+ android:right="16dp"
android:bottom="@dimen/button_padding_vertical_material" />
<solid android:color="@color/white" />
</shape>
diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml
index aa050f3a364d..2b9f95227f08 100644
--- a/core/res/res/layout/splash_screen_view.xml
+++ b/core/res/res/layout/splash_screen_view.xml
@@ -26,6 +26,7 @@
android:layout_width="wrap_content"
android:layout_gravity="center"
android:padding="0dp"
+ android:background="@null"
android:contentDescription="@string/splash_screen_view_icon_description"/>
<View android:id="@+id/splashscreen_branding_view"
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5245437a6cf0..4b1c544d8442 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1938,7 +1938,7 @@
<string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-Warnung"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeitsprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Gewarnt"</string>
- <string name="notification_verified_content_description" msgid="6401483602782359391">"Bestätigt"</string>
+ <string name="notification_verified_content_description" msgid="6401483602782359391">"Verifiziert"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Maximieren"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Minimieren"</string>
<string name="expand_action_accessibility" msgid="1947657036871746627">"Maximierung ein-/auschalten"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 1c49d95ebe43..b0bc2c29eeab 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1950,7 +1950,7 @@
<string name="maximize_button_text" msgid="4258922519914732645">"بزرگ کردن"</string>
<string name="close_button_text" msgid="10603510034455258">"بستن"</string>
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>:‏ <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
- <string name="call_notification_answer_action" msgid="5999246836247132937">"پاسخ"</string>
+ <string name="call_notification_answer_action" msgid="5999246836247132937">"پاسخ دادن"</string>
<string name="call_notification_answer_video_action" msgid="2086030940195382249">"ویدیو"</string>
<string name="call_notification_decline_action" msgid="3700345945214000726">"رد کردن"</string>
<string name="call_notification_hang_up_action" msgid="9130720590159188131">"قطع تماس"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 09b3c2b6b952..fb17c515cbfd 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -57,7 +57,7 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"შემომავალი ზარის აბონენტის ID"</string>
- <string name="ClirMmi" msgid="6752346475055446417">"გამავალი აბონენტის ID-ის დამალვა"</string>
+ <string name="ClirMmi" msgid="6752346475055446417">"გამავალი აბონენტის ID-ს დამალვა"</string>
<string name="ColpMmi" msgid="4736462893284419302">"დაუკავშირდა Line ID-ს"</string>
<string name="ColrMmi" msgid="5889782479745764278">"დაუკავშირდა Line ID Restriction-ს"</string>
<string name="CfMmi" msgid="8390012691099787178">"ზარის გადამისამართება"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 2a619e1f14fd..1f18b7029249 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -68,7 +68,7 @@
<string name="CnipMmi" msgid="4897531155968151160">"కాలింగ్ నంబర్ అందుబాటులో ఉంది"</string>
<string name="CnirMmi" msgid="885292039284503036">"కాలింగ్ నంబర్ పరిమితం చేయబడింది"</string>
<string name="ThreeWCMmi" msgid="2436550866139999411">"మూడు మార్గాల కాలింగ్"</string>
- <string name="RuacMmi" msgid="1876047385848991110">"అవాంఛిత అంతరాయ కాల్‌ల తిరస్కరణ"</string>
+ <string name="RuacMmi" msgid="1876047385848991110">"అవాంఛిత అంతరాయ కాల్స్‌ల తిరస్కరణ"</string>
<string name="CndMmi" msgid="185136449405618437">"కాలింగ్ నంబర్ బట్వాడా"</string>
<string name="DndMmi" msgid="8797375819689129800">"అంతరాయం కలిగించవద్దు"</string>
<string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"కాలర్ ID డిఫాల్ట్‌గా పరిమితానికి ఉంటుంది. తర్వాత కాల్: పరిమితం చేయబడింది"</string>
@@ -86,7 +86,7 @@
<string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"మొబైల్ నెట్‌వర్క్ అందుబాటులో లేదు"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ప్రాధాన్య నెట్‌వర్క్‌ను మార్చుకోవడానికి ప్రయత్నించండి. మార్చడానికి నొక్కండి."</string>
<string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"అత్యవసర కాలింగ్ అందుబాటులో లేదు"</string>
- <string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"Wi-Fiతో అత్యవసర కాల్‌లు చేయలేరు"</string>
+ <string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"Wi-Fiతో అత్యవసర కాల్స్‌ చేయలేరు"</string>
<string name="notification_channel_network_alert" msgid="4788053066033851841">"అలర్ట్‌లు"</string>
<string name="notification_channel_call_forward" msgid="8230490317314272406">"కాల్ ఫార్వార్డింగ్"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"అత్యవసర కాల్‌బ్యాక్ మోడ్"</string>
@@ -124,7 +124,7 @@
<string name="roamingTextSearching" msgid="5323235489657753486">"సేవ కోసం శోధిస్తోంది"</string>
<string name="wfcRegErrorTitle" msgid="3193072971584858020">"Wi‑Fi కాలింగ్‌ని సెటప్ చేయడం సాధ్యపడలేదు"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"Wi-Fiతో కాల్‌లను చేయడానికి మరియు సందేశాలను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్‌‌కి చెప్పండి. ఆ తర్వాత సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"Wi-Fiతో కాల్స్‌ను చేయడానికి మరియు సందేశాలను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్‌‌కి చెప్పండి. ఆ తర్వాత సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="4795145070505729156">"మీ క్యారియర్‌తో Wi‑Fi కాలింగ్‌ని నమోదు చేయడంలో సమస్య: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -176,10 +176,10 @@
<string name="contentServiceSync" msgid="2341041749565687871">"సమకాలీకరణ"</string>
<string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"సమకాలీకరించడం సాధ్యపడదు"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"చాలా ఎక్కువ <xliff:g id="CONTENT_TYPE">%s</xliff:g> తొలగించడానికి ప్రయత్నించారు."</string>
- <string name="low_memory" product="tablet" msgid="5557552311566179924">"టాబ్లెట్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైల్‌లను తొలగించండి."</string>
- <string name="low_memory" product="watch" msgid="3479447988234030194">"వాచ్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైల్‌లను తొలగించండి."</string>
+ <string name="low_memory" product="tablet" msgid="5557552311566179924">"టాబ్లెట్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైళ్లను తొలగించండి."</string>
+ <string name="low_memory" product="watch" msgid="3479447988234030194">"వాచ్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైళ్లను తొలగించండి."</string>
<string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV పరికరం నిల్వ నిండింది. కొంత ప్రదేశాన్ని ఖాళీ చేయడానికి కొన్ని ఫైల్‌‌‌లను తొలగించండి."</string>
- <string name="low_memory" product="default" msgid="2539532364144025569">"ఫోన్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైల్‌లను తొలగించండి."</string>
+ <string name="low_memory" product="default" msgid="2539532364144025569">"ఫోన్ నిల్వ నిండింది. స్థలాన్ని ఖాళీ చేయడానికి కొన్ని ఫైళ్లను తొలగించండి."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="other">ప్రమాణపత్ర అధికారాలు ఇన్‌స్టాల్ చేయబడ్డాయి</item>
<item quantity="one">ప్రమాణపత్ర అధికారం ఇన్‌స్టాల్ చేయబడింది</item>
@@ -247,21 +247,21 @@
<string name="global_action_power_options" msgid="1185286119330160073">"పవర్"</string>
<string name="global_action_restart" msgid="4678451019561687074">"రీస్టార్ట్ చేయి"</string>
<string name="global_action_emergency" msgid="1387617624177105088">"ఎమర్జెన్సీ"</string>
- <string name="global_action_bug_report" msgid="5127867163044170003">"బగ్ నివేదిక"</string>
+ <string name="global_action_bug_report" msgid="5127867163044170003">"బగ్ రిపోర్ట్‌"</string>
<string name="global_action_logout" msgid="6093581310002476511">"సెషన్‌ను ముగించు"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"స్క్రీన్‌షాట్"</string>
<string name="bugreport_title" msgid="8549990811777373050">"బగ్ రిపోర్ట్‌"</string>
- <string name="bugreport_message" msgid="5212529146119624326">"ఇది ఇ-మెయిల్ సందేశం రూపంలో పంపడానికి మీ ప్రస్తుత పరికర స్థితి గురించి సమాచారాన్ని సేకరిస్తుంది. బగ్ నివేదికను ప్రారంభించడం మొదలుకొని పంపడానికి సిద్ధం చేసే వరకు ఇందుకు కొంత సమయం పడుతుంది; దయచేసి ఓపిక పట్టండి."</string>
- <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"ప్రభావశీల నివేదిక"</string>
- <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"చాలా సందర్భాల్లో దీన్ని ఉపయోగించండి. ఇది నివేదిక ప్రోగ్రెస్‌ను ట్రాక్ చేయడానికి, సమస్య గురించి మరిన్ని వివరాలను నమోదు చేయడానికి మరియు స్క్రీన్‌షాట్‌లు తీయడానికి మిమ్మల్ని అనుమతిస్తుంది. ఇది నివేదించడానికి ఎక్కువ సమయం పట్టే తక్కువ వినియోగ విభాగాలను విడిచిపెట్టవచ్చు."</string>
- <string name="bugreport_option_full_title" msgid="7681035745950045690">"పూర్తి నివేదిక"</string>
- <string name="bugreport_option_full_summary" msgid="1975130009258435885">"మీ పరికరం ప్రతిస్పందనరహితంగా ఉన్నప్పుడు లేదా చాలా నెమ్మదిగా ఉన్నప్పుడు లేదా మీకు అన్ని నివేదిక విభాగాలు అవసరమైనప్పుడు సిస్టమ్‌కి అంతరాయ స్థాయి కనిష్టంగా ఉండేలా చేయడానికి ఈ ఎంపిక ఉపయోగించండి. ఇది మరిన్ని వివరాలను నమోదు చేయడానికి లేదా అదనపు స్క్రీన్‌షాట్‌లు తీయడానికి మిమ్మల్ని అనుమతించదు."</string>
+ <string name="bugreport_message" msgid="5212529146119624326">"ఇది ఇ-మెయిల్ సందేశం రూపంలో పంపడానికి మీ ప్రస్తుత పరికర స్థితి గురించి సమాచారాన్ని సేకరిస్తుంది. బగ్ రిపోర్ట్‌ను ప్రారంభించడం మొదలుకొని పంపడానికి సిద్ధం చేసే వరకు ఇందుకు కొంత సమయం పడుతుంది; దయచేసి ఓపిక పట్టండి."</string>
+ <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"ప్రభావశీల రిపోర్ట్‌"</string>
+ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"చాలా సందర్భాల్లో దీన్ని ఉపయోగించండి. ఇది రిపోర్ట్‌ ప్రోగ్రెస్‌ను ట్రాక్ చేయడానికి, సమస్య గురించి మరిన్ని వివరాలను నమోదు చేయడానికి మరియు స్క్రీన్‌షాట్‌లు తీయడానికి మిమ్మల్ని అనుమతిస్తుంది. ఇది నివేదించడానికి ఎక్కువ సమయం పట్టే తక్కువ వినియోగ విభాగాలను విడిచిపెట్టవచ్చు."</string>
+ <string name="bugreport_option_full_title" msgid="7681035745950045690">"పూర్తి రిపోర్ట్‌"</string>
+ <string name="bugreport_option_full_summary" msgid="1975130009258435885">"మీ పరికరం ప్రతిస్పందనరహితంగా ఉన్నప్పుడు లేదా చాలా నెమ్మదిగా ఉన్నప్పుడు లేదా మీకు అన్ని రిపోర్ట్‌ విభాగాలు అవసరమైనప్పుడు సిస్టమ్‌కి అంతరాయ స్థాయి కనిష్టంగా ఉండేలా చేయడానికి ఈ ఎంపిక ఉపయోగించండి. ఇది మరిన్ని వివరాలను నమోదు చేయడానికి లేదా అదనపు స్క్రీన్‌షాట్‌లు తీయడానికి మిమ్మల్ని అనుమతించదు."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
- <item quantity="other">బగ్ నివేదిక కోసం <xliff:g id="NUMBER_1">%d</xliff:g> సెకన్లలో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
- <item quantity="one">బగ్ నివేదిక కోసం <xliff:g id="NUMBER_0">%d</xliff:g> సెకనులో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
+ <item quantity="other">బగ్ రిపోర్ట్‌ కోసం <xliff:g id="NUMBER_1">%d</xliff:g> సెకన్లలో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
+ <item quantity="one">బగ్ రిపోర్ట్‌ కోసం <xliff:g id="NUMBER_0">%d</xliff:g> సెకనులో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
</plurals>
- <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"బగ్ నివేదికతో ఉన్న స్క్రీన్‌షాట్ తీయబడింది"</string>
- <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"బగ్ నివేదికతో ఉన్న స్క్రీన్‌షాట్‌ను తీయడం విఫలమైంది"</string>
+ <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"బగ్ రిపోర్ట్‌తో ఉన్న స్క్రీన్‌షాట్ తీయబడింది"</string>
+ <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"బగ్ రిపోర్ట్‌తో ఉన్న స్క్రీన్‌షాట్‌ను తీయడం విఫలమైంది"</string>
<string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"నిశ్శబ్ద మోడ్"</string>
<string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"ధ్వని ఆఫ్‌లో ఉంది"</string>
<string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"ధ్వని ఆన్‌లో ఉంది"</string>
@@ -311,7 +311,7 @@
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"ఫైల్స్, మీడియా"</string>
- <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్‌లను యాక్సెస్ చేయడానికి"</string>
+ <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైళ్లను యాక్సెస్ చేయడానికి"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"ఆడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ఫిజికల్ యాక్టివిటీ"</string>
@@ -323,7 +323,7 @@
<string name="permgrouplab_calllog" msgid="7926834372073550288">"కాల్ లాగ్‌లు"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"ఫోన్ కాల్ లాగ్‌ని చదవండి మరియు రాయండి"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"ఫోన్"</string>
- <string name="permgroupdesc_phone" msgid="270048070781478204">"ఫోన్ కాల్‌లు చేయడం మరియు నిర్వహించడం"</string>
+ <string name="permgroupdesc_phone" msgid="270048070781478204">"ఫోన్ కాల్స్‌ చేయడం మరియు నిర్వహించడం"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"శరీర సెన్సార్‌లు"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేస్తుంది"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"విండో కంటెంట్‍ను తిరిగి పొందుతుంది"</string>
@@ -352,10 +352,10 @@
<string name="permdesc_install_shortcut" msgid="4476328467240212503">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్‌స్క్రీన్ సత్వరమార్గాలను జోడించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_uninstall_shortcut" msgid="295263654781900390">"సత్వరమార్గాలను అన్ఇన్‌స్టాల్ చేయడం"</string>
<string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్‌స్క్రీన్ సత్వరమార్గాలను తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"అవుట్‌గోయింగ్ కాల్‌లను దారి మళ్లించడం"</string>
+ <string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"అవుట్‌గోయింగ్ కాల్స్‌ను దారి మళ్లించడం"</string>
<string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"కాల్‌ను వేరే నంబర్‌కు దారి మళ్లించే లేదా మొత్తంగా కాల్‌ను ఆపివేసే ఎంపిక సహాయంతో అవుట్‌గోయింగ్ కాల్ సమయంలో డయల్ చేయబడుతున్న నంబర్‌ను చూడటానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"ఫోన్ కాల్‌లకు సమాధానమివ్వు"</string>
- <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"ఇన్‌కమింగ్ ఫోన్ కాల్‌లకు సమాధానమివ్వడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"ఫోన్ కాల్స్‌కు సమాధానమివ్వు"</string>
+ <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"ఇన్‌కమింగ్ ఫోన్ కాల్స్‌కు సమాధానమివ్వడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_receiveSms" msgid="505961632050451881">"వచన సందేశాలను (SMS) స్వీకరించడం"</string>
<string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
<string name="permlab_receiveMms" msgid="4000650116674380275">"వచన సందేశాలను (MMS) స్వీకరించడం"</string>
@@ -376,15 +376,15 @@
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"ఈ యాప్‌ మీ ఫోన్‌లో నిల్వ చేసిన అన్ని SMS (వచన) సందేశాలను చదవగలదు."</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"వచన సందేశాలను (WAP) స్వీకరించడం"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string>
- <string name="permlab_getTasks" msgid="7460048811831750262">"అమలవుతున్న అనువర్తనాలను పునరుద్ధరించడం"</string>
+ <string name="permlab_getTasks" msgid="7460048811831750262">"అమలవుతున్న యాప్‌లను పునరుద్ధరించడం"</string>
<string name="permdesc_getTasks" msgid="7388138607018233726">"ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి యాప్‌ను అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన యాప్‌ల గురించి సమాచారాన్ని కనుగొనడానికి యాప్‌ను అనుమతించవచ్చు."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"ప్రొఫైల్ మరియు పరికర యజమానులను నిర్వహించడం"</string>
- <string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"ప్రొఫైల్ యజమానులను మరియు పరికరం యజమానిని సెట్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది."</string>
+ <string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"ప్రొఫైల్ యజమానులను మరియు పరికరం యజమానిని సెట్ చేయడానికి యాప్‌లను అనుమతిస్తుంది."</string>
<string name="permlab_reorderTasks" msgid="7598562301992923804">"అమలవుతోన్న యాప్‌లను మళ్లీ క్రమం చేయడం"</string>
<string name="permdesc_reorderTasks" msgid="8796089937352344183">"విధులను ముందుకు మరియు నేపథ్యానికి తరలించడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ ప్రమేయం లేకుండానే దీన్ని చేయవచ్చు."</string>
<string name="permlab_enableCarMode" msgid="893019409519325311">"కారు మోడ్‌ను ప్రారంభించడం"</string>
<string name="permdesc_enableCarMode" msgid="56419168820473508">"కారు మోడ్‌ను ప్రారంభించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"ఇతర అనువర్తనాలను మూసివేయడం"</string>
+ <string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"ఇతర యాప్‌లను మూసివేయడం"</string>
<string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"ఇతర యాప్‌ల నేపథ్య ప్రాసెస్‌లను ముగించడానికి యాప్‌ను అనుమతిస్తుంది. దీని వలన ఇతర యాప్‌లు అమలు కాకుండా ఆపివేయబడవచ్చు."</string>
<string name="permlab_systemAlertWindow" msgid="5757218350944719065">"ఈ యాప్ ఇతర యాప్‌ల పైభాగాన కనిపించగలదు"</string>
<string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"ఈ యాప్ ఇతర యాప్‌ల పైభాగాన లేదా స్క్రీన్ యొక్క ఇతర భాగాలపైన కనిపించగలదు. ఇది సాధారణ యాప్ వినియోగానికి అంతరాయం కలిగించవచ్చు మరియు ఆ ఇతర యాప్‌లు కనిపించే విధానాన్ని మార్చవచ్చు."</string>
@@ -421,9 +421,9 @@
<string name="permlab_readCallLog" msgid="1739990210293505948">"కాల్ లాగ్‌ను చదవడం"</string>
<string name="permdesc_readCallLog" msgid="8964770895425873433">"ఈ యాప్‌ మీ కాల్ చరిత్రను చదవగలదు."</string>
<string name="permlab_writeCallLog" msgid="670292975137658895">"కాల్ లాగ్‌ను వ్రాయడం"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌ల గురించిన డేటాతో సహా మీ టాబ్లెట్ యొక్క కాల్ లాగ్‌ను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
- <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌లకు సంబంధించిన డేటాతో సహా మీ Android TV పరికరం కాల్ లాగ్‌ను సవరించడానికి యాప్‌ని అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను తీసివేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
- <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్‌ల గురించిన డేటాతో సహా మీ ఫోన్ యొక్క కాల్ లాగ్‌ను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్స్‌ల గురించిన డేటాతో సహా మీ టాబ్లెట్ యొక్క కాల్ లాగ్‌ను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
+ <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్స్‌కు సంబంధించిన డేటాతో సహా మీ Android TV పరికరం కాల్ లాగ్‌ను సవరించడానికి యాప్‌ని అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను తీసివేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"ఇన్‌కమింగ్ మరియు అవుట్‌గోయింగ్ కాల్స్‌ల గురించిన డేటాతో సహా మీ ఫోన్ యొక్క కాల్ లాగ్‌ను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. హానికరమైన యాప్‌లు మీ కాల్ లాగ్‌ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string>
<string name="permlab_bodySensors" msgid="3411035315357380862">"శరీర సెన్సార్‌లను (గుండె స్పందన రేటు మానిటర్‌ల వంటివి) యాక్సెస్ చేయండి"</string>
<string name="permdesc_bodySensors" product="default" msgid="2365357960407973997">"మీ శారీరక పరిస్థితిని అనగా మీ గుండె స్పందన రేటు వంటి వాటిని పర్యవేక్షించే సెన్సార్‌ల నుండి డేటాను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_readCalendar" msgid="6408654259475396200">"క్యాలెండర్ ఈవెంట్‌లు మరియు వివరాలను చదవడం"</string>
@@ -464,15 +464,15 @@
<string name="permdesc_vibrate" msgid="8733343234582083721">"వైబ్రేటర్‌ను నియంత్రించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permdesc_vibrator_state" msgid="7050024956594170724">"వైబ్రేటర్ స్థితిని యాక్సెస్ చేసేందుకు యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_callPhone" msgid="1798582257194643320">"నేరుగా కాల్ చేసే ఫోన్ నంబర్‌లు"</string>
- <string name="permdesc_callPhone" msgid="5439809516131609109">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్‌లు రావచ్చు. ఇది అత్యవసర నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతించదని గుర్తుంచుకోండి. హానికరమైన యాప్‌లు మీ నిర్ధారణ లేకుండానే కాల్‌లు చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string>
+ <string name="permdesc_callPhone" msgid="5439809516131609109">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్స్‌ రావచ్చు. ఇది అత్యవసర నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతించదని గుర్తుంచుకోండి. హానికరమైన యాప్‌లు మీ నిర్ధారణ లేకుండానే కాల్స్‌ చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string>
<string name="permlab_accessImsCallService" msgid="442192920714863782">"IMS కాల్ సేవ యాక్సెస్ అనుమతి"</string>
- <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"మీ ప్రమేయం లేకుండా కాల్‌లు చేయడం కోసం IMS సేవను ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"మీ ప్రమేయం లేకుండా కాల్స్‌ చేయడం కోసం IMS సేవను ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_readPhoneState" msgid="8138526903259297969">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string>
<string name="permdesc_readPhoneState" msgid="7229063553502788058">"పరికరం యొక్క ఫోన్ ఫీచర్‌లను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్‌ను కనుగొనడానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"కాల్‌లను సిస్టమ్ ద్వారా వెళ్లేలా చేయి"</string>
- <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్‌లను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_callCompanionApp" msgid="3654373653014126884">"సిస్టమ్ ద్వారా కాల్‌లను చూసి, నియంత్రించండి."</string>
- <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"పరికరంలో కొనసాగుతున్న కాల్‌లను చూడడానికి మరియు నియంత్రించడానికి యాప్‌ను అనుమతిస్తుంది. ఇందులో కాల్ కోసం కాల్‌ల నంబర్‌లు మరియు రాష్ట్ర కాల్ వంటి సమాచారం ఉంటుంది."</string>
+ <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"కాల్స్‌ను సిస్టమ్ ద్వారా వెళ్లేలా చేయి"</string>
+ <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్స్‌ను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permlab_callCompanionApp" msgid="3654373653014126884">"సిస్టమ్ ద్వారా కాల్స్‌ను చూసి, నియంత్రించండి."</string>
+ <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"పరికరంలో కొనసాగుతున్న కాల్స్‌ను చూడడానికి మరియు నియంత్రించడానికి యాప్‌ను అనుమతిస్తుంది. ఇందులో కాల్ కోసం కాల్స్‌ల నంబర్‌లు మరియు రాష్ట్ర కాల్ వంటి సమాచారం ఉంటుంది."</string>
<string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"ఆడియో రికార్డ్ పరిమితుల నుండి మినహాయింపు"</string>
<string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"ఆడియోను రికార్డ్ చేయడానికి యాప్‌ను పరిమితుల నుండి మినహాయించండి."</string>
<string name="permlab_acceptHandover" msgid="2925523073573116523">"మరో యాప్ నుండి కాల్‌ని కొనసాగించండి"</string>
@@ -672,8 +672,8 @@
<string name="permdesc_sdcardRead" msgid="6872973242228240382">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్‌లను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_sdcardWrite" msgid="4863021819671416668">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్‌లను సవరించండి లేదా తొలగించండి"</string>
<string name="permdesc_sdcardWrite" msgid="8376047679331387102">"మీ షేర్ చేసిన నిల్వ యొక్క కంటెంట్‌లను రాయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
- <string name="permlab_use_sip" msgid="8250774565189337477">"SIP కాల్‌లను చేయడానికి/స్వీకరించడానికి"</string>
- <string name="permdesc_use_sip" msgid="3590270893253204451">"SIP కాల్‌లను చేయడానికి మరియు స్వీకరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permlab_use_sip" msgid="8250774565189337477">"SIP కాల్స్‌ను చేయడానికి/స్వీకరించడానికి"</string>
+ <string name="permdesc_use_sip" msgid="3590270893253204451">"SIP కాల్స్‌ను చేయడానికి మరియు స్వీకరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_register_sim_subscription" msgid="1653054249287576161">"కొత్త టెలికామ్ SIM కనెక్షన్‌లను నమోదు చేయడం"</string>
<string name="permdesc_register_sim_subscription" msgid="4183858662792232464">"కొత్త టెలికామ్ SIM కనెక్షన్‌లను నమోదు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_register_call_provider" msgid="6135073566140050702">"కొత్త టెలికామ్ కనెక్షన్‌లను నమోదు చేయడం"</string>
@@ -683,7 +683,7 @@
<string name="permlab_bind_incall_service" msgid="5990625112603493016">"ఇన్-కాల్ స్క్రీన్‌తో పరస్పర చర్య చేయడం"</string>
<string name="permdesc_bind_incall_service" msgid="4124917526967765162">"వినియోగదారునికి ఇన్-కాల్ స్క్రీన్ ఎప్పుడు, ఎలా కనిపించాలనే దాన్ని నియంత్రించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_bind_connection_service" msgid="5409268245525024736">"టెలిఫోన్ సేవలతో పరస్పర చర్య చేయడం"</string>
- <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"కాల్‌లు చేయడం/స్వీకరించడం కోసం టెలిఫోన్ సేవలతో పరస్పర చర్య చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"కాల్స్‌ చేయడం/స్వీకరించడం కోసం టెలిఫోన్ సేవలతో పరస్పర చర్య చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_control_incall_experience" msgid="6436863486094352987">"ఇన్-కాల్ వినియోగదారు అనుభవాన్ని అందించడం"</string>
<string name="permdesc_control_incall_experience" msgid="5896723643771737534">"ఇన్-కాల్ వినియోగదారుని అనుభవాన్ని అందించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"చారిత్రక నెట్‌వర్క్ వినియోగాన్ని చదవడం"</string>
@@ -693,29 +693,29 @@
<string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"నెట్‌వర్క్ వినియోగ అకౌంటింగ్‌ను సవరించడం"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"యాప్‌లలో నెట్‌వర్క్ వినియోగం ఎలా గణించాలనే దాన్ని సవరించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌ల ద్వారా ఉపయోగించడానికి ఉద్దేశించినది కాదు."</string>
<string name="permlab_accessNotifications" msgid="7130360248191984741">"నోటిఫికేషన్‌లను యాక్సెస్ చేయడం"</string>
- <string name="permdesc_accessNotifications" msgid="761730149268789668">"నోటిఫికేషన్‌లను, ఇతర అనువర్తనాల ద్వారా పోస్ట్ చేయబడిన వాటిని తిరిగి పొందడానికి, పరిశీలించడానికి మరియు క్లియర్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+ <string name="permdesc_accessNotifications" msgid="761730149268789668">"నోటిఫికేషన్‌లను, ఇతర యాప్‌ల ద్వారా పోస్ట్ చేయబడిన వాటిని తిరిగి పొందడానికి, పరిశీలించడానికి మరియు క్లియర్ చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_bindNotificationListenerService" msgid="5848096702733262458">"నోటిఫికేషన్ పరిశీలన సేవకు అనుబంధించడం"</string>
- <string name="permdesc_bindNotificationListenerService" msgid="4970553694467137126">"నోటిఫికేషన్ పరిశీలన సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాల కోసం ఎప్పటికీ అవసరం ఉండకూడదు."</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="4970553694467137126">"నోటిఫికేషన్ పరిశీలన సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌ల కోసం ఎప్పటికీ అవసరం ఉండకూడదు."</string>
<string name="permlab_bindConditionProviderService" msgid="5245421224814878483">"షరతు ప్రదాత సేవకు అనుబంధించడం"</string>
- <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"షరతు ప్రదాత సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"షరతు ప్రదాత సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"డ్రీమ్ సేవ‌కి అనుబంధించడం"</string>
- <string name="permdesc_bindDreamService" msgid="9129615743300572973">"డ్రీమ్ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_bindDreamService" msgid="9129615743300572973">"డ్రీమ్ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"క్యారియర్ అందించిన కాన్ఫిగరేషన్ యాప్‌ను అభ్యర్థించడం"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"క్యారియర్ అందించిన కాన్ఫిగరేషన్ యాప్‌ను అభ్యర్థించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాల కోసం ఎప్పటికీ అవసరం ఉండకూడదు."</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"క్యారియర్ అందించిన కాన్ఫిగరేషన్ యాప్‌ను అభ్యర్థించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌ల కోసం ఎప్పటికీ అవసరం ఉండకూడదు."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"నెట్‌వర్క్ పరిస్థితులపై పరిశీలనల గురించి తెలుసుకోవడం"</string>
- <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"నెట్‌వర్క్ పరిస్థితులపై పరిశీలనల గురించి తెలుసుకోవడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండకూడదు."</string>
+ <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"నెట్‌వర్క్ పరిస్థితులపై పరిశీలనల గురించి తెలుసుకోవడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండకూడదు."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"ఇన్‌పుట్ పరికరం క్రమాంకనాన్ని మార్చండి"</string>
- <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM ప్రమాణపత్రాలను యాక్సెస్ చేయడం"</string>
- <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam బదిలీ స్థితిని స్వీకరించడం"</string>
<string name="permdesc_handoverStatus" msgid="3842269451732571070">"ప్రస్తుత Android Beam బదిలీలకు సంబంధించిన సమాచారాన్ని స్వీకరించడానికి ఈ యాప్‌ను అనుమతిస్తుంది"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"DRM ప్రమాణపత్రాలను తీసివేయడం"</string>
- <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ప్రమాణపత్రాలను తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ప్రమాణపత్రాలను తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"క్యారియర్ సందేశ సేవకు అనుబంధించడం"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"క్యారియర్ సందేశ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="6316457028173478345">"క్యారియర్ సందేశ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"క్యారియర్ సేవలకు అనుబంధించడం"</string>
- <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"క్యారియర్ సేవలకు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+ <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"క్యారియర్ సేవలకు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"అంతరాయం కలిగించవద్దును యాక్సెస్ చేయడం"</string>
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"అంతరాయం కలిగించవద్దు ఎంపిక కాన్ఫిగరేషన్ చదవడానికి మరియు వ్రాయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"వీక్షణ అనుమతి వినియోగాన్ని ప్రారంభించండి"</string>
@@ -1259,7 +1259,7 @@
<string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>ని అప్‌గ్రేడ్ చేస్తోంది…"</string>
<string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> యాప్‌ను అనుకూలీకరిస్తోంది."</string>
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
- <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"అనువర్తనాలను ప్రారంభిస్తోంది."</string>
+ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"యాప్‌లను ప్రారంభిస్తోంది."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"బూట్‌ను ముగిస్తోంది."</string>
<string name="fp_enrollment_powerbutton_intent_title" msgid="3385634173366119903">"స్క్రీన్‌ను ఆఫ్ చేయాలా?"</string>
<string name="fp_enrollment_powerbutton_intent_message" msgid="6582149052513682522">"మీ వేలిముద్రను సెటప్ చేస్తున్నప్పుడు, మీరు పవర్ బటన్‌ను నొక్కారు.\n\nఇది సాధారణంగా మీ స్క్రీన్‌ను ఆఫ్ చేస్తుంది."</string>
@@ -1385,10 +1385,10 @@
<string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB పోర్ట్ ఆటోమేటిక్‌గా నిలిపివేయబడింది. మరింత తెలుసుకోవడానికి నొక్కండి."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB పోర్ట్‌ను ఉపయోగించడం సురక్షితం"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"ఫోన్ ఇకపై ద్రవ లేదా వ్యర్థ పదార్థాలను గుర్తించదు."</string>
- <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"బగ్ నివేదికను తీస్తోంది…"</string>
- <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ నివేదికను భాగస్వామ్యం చేయాలా?"</string>
- <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ నివేదికను భాగస్వామ్యం చేస్తోంది..."</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ నివేదికను అభ్యర్థించారు. యాప్‌లు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
+ <string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"బగ్ రిపోర్ట్‌ను తీస్తోంది…"</string>
+ <string name="share_remote_bugreport_notification_title" msgid="6708897723753334999">"బగ్ రిపోర్ట్‌ను భాగస్వామ్యం చేయాలా?"</string>
+ <string name="sharing_remote_bugreport_notification_title" msgid="3077385149217638550">"బగ్ రిపోర్ట్‌ను భాగస్వామ్యం చేస్తోంది..."</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="7325635795739260135">"మీ నిర్వాహకులు ఈ పరికరం సమస్యకు పరిష్కారాన్ని కనుగొనడంలో సహాయం కోసం బగ్ రిపోర్ట్‌ను అభ్యర్థించారు. యాప్‌లు మరియు డేటా భాగస్వామ్యం చేయబడవచ్చు."</string>
<string name="share_remote_bugreport_action" msgid="7630880678785123682">"షేర్ చేయి"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"తిరస్కరిస్తున్నాను"</string>
<string name="select_input_method" msgid="3971267998568587025">"ఇన్‌పుట్ పద్ధతిని ఎంచుకోండి"</string>
@@ -1991,7 +1991,7 @@
<string name="profile_encrypted_detail" msgid="5279730442756849055">"కార్యాలయ ప్రొఫైల్ లాక్ అయింది"</string>
<string name="profile_encrypted_message" msgid="1128512616293157802">"కార్యాలయ ప్రొఫైల్ అన్‌లాక్ చేయుటకు నొక్కండి"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది"</string>
- <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ఫైల్‌లను వీక్షించడానికి నొక్కండి"</string>
+ <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"ఫైళ్లను వీక్షించడానికి నొక్కండి"</string>
<string name="pin_target" msgid="8036028973110156895">"పిన్ చేయి"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g>ను పిన్ చేయండి"</string>
<string name="unpin_target" msgid="3963318576590204447">"అన్‌‌పిన్‌ ‌చేయి"</string>
@@ -2077,8 +2077,8 @@
<string name="harmful_app_warning_title" msgid="8794823880881113856">"హానికరమైన యాప్ గుర్తించబడింది"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> <xliff:g id="APP_2">%2$s</xliff:g> స్లైస్‌లను చూపించాలనుకుంటోంది"</string>
<string name="screenshot_edit" msgid="7408934887203689207">"ఎడిట్ చేయండి"</string>
- <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"కాల్‌లు మరియు నోటిఫికేషన్‌లు వైబ్రేట్ అవుతాయి"</string>
- <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"కాల్‌లు మరియు నోటిఫికేషన్‌లు మ్యూట్ చేయబడతాయి"</string>
+ <string name="volume_dialog_ringer_guidance_vibrate" msgid="2055927873175228519">"కాల్స్‌ మరియు నోటిఫికేషన్‌లు వైబ్రేట్ అవుతాయి"</string>
+ <string name="volume_dialog_ringer_guidance_silent" msgid="1011246774949993783">"కాల్స్‌ మరియు నోటిఫికేషన్‌లు మ్యూట్ చేయబడతాయి"</string>
<string name="notification_channel_system_changes" msgid="2462010596920209678">"సిస్టమ్ మార్పులు"</string>
<string name="notification_channel_do_not_disturb" msgid="7832584281883687653">"అంతరాయం కలిగించవద్దు"</string>
<string name="zen_upgrade_notification_visd_title" msgid="2001148984371968620">"కొత్తది: అంతరాయం కలిగించవద్దు నోటిఫికేషన్‌లను దాస్తోంది"</string>
@@ -2100,7 +2100,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"సరే"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ఆఫ్ చేయండి"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"మరింత తెలుసుకోండి"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్‌లను, మెరుగైన నోటిఫికేషన్‌లు భర్తీ చేశాయి. సూచించిన చర్యలు, రిప్లయిలను ఈ ఫీచర్ చూపించి, మీ నోటిఫికేషన్‌లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్‌లు లాంటి వ్యక్తిగత సమాచారంతో సహా నోటిఫికేషన్ కంటెంట్‌ను మెరుగైన నోటిఫికేషన్‌లు యాక్సెస్ చేయవచ్చు. ఫోన్ కాల్‌లకు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్‌ను కంట్రోల్ చేయడం లాంటి నోటిఫికేషన్‌లను విస్మరించడం లేదా ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్‌లను, మెరుగైన నోటిఫికేషన్‌లు భర్తీ చేశాయి. సూచించిన చర్యలు, రిప్లయిలను ఈ ఫీచర్ చూపించి, మీ నోటిఫికేషన్‌లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్‌లు లాంటి వ్యక్తిగత సమాచారంతో సహా నోటిఫికేషన్ కంటెంట్‌ను మెరుగైన నోటిఫికేషన్‌లు యాక్సెస్ చేయవచ్చు. ఫోన్ కాల్స్‌కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్‌ను కంట్రోల్ చేయడం లాంటి నోటిఫికేషన్‌లను విస్మరించడం లేదా ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"రొటీన్ మోడ్ సమాచార నోటిఫికేషన్"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"మామూలుగా ఛార్జ్ చేసేలోపు బ్యాటరీ ఖాళీ కావచ్చు"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"బ్యాటరీ జీవితకాలాన్ని పెంచడానికి బ్యాటరీ సేవర్ యాక్టివేట్ చేయబడింది"</string>
@@ -2130,7 +2130,7 @@
<string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"విమానం మోడ్‌లో బ్లూటూత్ ఆన్‌లో ఉంటుంది"</string>
<string name="car_loading_profile" msgid="8219978381196748070">"లోడవుతోంది"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
- <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ఫైల్‌లు</item>
+ <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ఫైళ్లు</item>
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ఫైల్</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ఎవరికి షేర్ చేయాలనే దానికి సంబంధించి సిఫార్సులేవీ లేవు"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 78758e805039..de5a3014610a 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1950,7 +1950,7 @@
<string name="maximize_button_text" msgid="4258922519914732645">"بڑا کریں"</string>
<string name="close_button_text" msgid="10603510034455258">"بند کریں"</string>
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
- <string name="call_notification_answer_action" msgid="5999246836247132937">"جواب"</string>
+ <string name="call_notification_answer_action" msgid="5999246836247132937">"جواب دیں"</string>
<string name="call_notification_answer_video_action" msgid="2086030940195382249">"ویڈیو"</string>
<string name="call_notification_decline_action" msgid="3700345945214000726">"مسترد کریں"</string>
<string name="call_notification_hang_up_action" msgid="9130720590159188131">"منقطع کر دیں"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 7be9c7b42e5a..e8bb6067932e 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -237,6 +237,9 @@
value is calculated in ConversationLayout#updateActionListPadding() -->
<dimen name="notification_actions_padding_start">36dp</dimen>
+ <!-- The max width of a priority action button when it is collapsed to just the icon. -->
+ <dimen name="notification_actions_collapsed_priority_width">60dp</dimen>
+
<!-- The start padding to optionally use (e.g. if there's extra space) for CallStyle
notification actions.
this = conversation_content_start (80dp) - button inset (4dp) - action padding (12dp) -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5b69a73c7120..0daf358fc86c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3185,6 +3185,7 @@
<java-symbol type="id" name="notification_action_list_margin_target" />
<java-symbol type="dimen" name="notification_actions_padding_start"/>
+ <java-symbol type="dimen" name="notification_actions_collapsed_priority_width"/>
<java-symbol type="dimen" name="notification_action_disabled_alpha" />
<java-symbol type="id" name="tag_margin_end_when_icon_visible" />
<java-symbol type="id" name="tag_margin_end_when_icon_gone" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 2be5c4746345..37d059a575f0 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -88,9 +88,12 @@
<!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
- <!-- Czechia: 7-8 digits, starting with 9, plus EU:
- http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
- <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
+ <!-- Czechia: Premium numbers start with 90, and are either 5 or 7 digits (5 digits is a
+ subscription request, you will be charged for the messages received, but it's necessary
+ to warn on the _request_ as that's the last chance to stop), plus EU:
+ https://www.t-mobile.cz/platebni-a-premium-sms
+ https://www.vodafone.cz/pece/vyuctovani-platby-kredit/platby-mobilem/cena-premium-sms/ -->
+ <shortcode country="cz" premium="90\\d{5}|90\\d{3}" free="116\\d{3}" />
<!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
<shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438" />
diff --git a/core/tests/coretests/src/android/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
index 08edb4e9be97..bc92da928d1e 100644
--- a/core/tests/coretests/src/android/app/backup/FullBackupTest.java
+++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
@@ -16,6 +16,8 @@
package android.app.backup;
+import static android.app.backup.FullBackup.ConfigSection.CLOUD_BACKUP;
+
import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags;
import android.content.Context;
import android.test.AndroidTestCase;
@@ -414,6 +416,37 @@ public class FullBackupTest extends AndroidTestCase {
assertNull("Didn't throw away invalid \"..\" path.", fileDomainIncludes);
}
+ public void testParseNewBackupSchemeFromXml_emptyCloudSectionIsRespected() throws Exception {
+ mXpp.setInput(new StringReader(
+ "<data-extraction-rules>" +
+ "<cloud-backup>" +
+ "</cloud-backup>" +
+ "</data-extraction-rules>"));
+
+ FullBackup.BackupScheme backupScheme = FullBackup.getBackupSchemeForTest(mContext);
+ boolean result = backupScheme.parseNewBackupSchemeFromXmlLocked(mXpp, CLOUD_BACKUP,
+ excludesSet, includeMap);
+
+ assertTrue(result);
+ }
+
+ public void testParseNewBackupSchemeFromXml_emptyCloudSectionWithEncryptionFlagIsRespected()
+ throws Exception {
+ mXpp.setInput(new StringReader(
+ "<data-extraction-rules>" +
+ "<cloud-backup disableIfNoEncryptionCapabilities=\"true\">" +
+ "</cloud-backup>" +
+ "</data-extraction-rules>"));
+
+ FullBackup.BackupScheme backupScheme = FullBackup.getBackupSchemeForTest(mContext);
+ boolean result = backupScheme.parseNewBackupSchemeFromXmlLocked(mXpp, CLOUD_BACKUP,
+ excludesSet, includeMap);
+
+ assertTrue(result);
+ assertEquals(backupScheme.getRequiredTransportFlags(),
+ BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED);
+ }
+
public void testDoubleDotInPath_isIgnored() throws Exception {
mXpp.setInput(new StringReader(
"<full-backup-content>" +
diff --git a/core/tests/coretests/src/android/view/ViewInputConnectionTest.java b/core/tests/coretests/src/android/view/ViewInputConnectionTest.java
index d667af39f585..d60c0c688e1a 100644
--- a/core/tests/coretests/src/android/view/ViewInputConnectionTest.java
+++ b/core/tests/coretests/src/android/view/ViewInputConnectionTest.java
@@ -19,13 +19,25 @@ package android.view;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import android.annotation.DurationMillisLong;
import android.app.Instrumentation;
import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.text.InputType;
import android.text.format.DateUtils;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
@@ -45,12 +57,23 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
/**
* Tests for internal APIs/behaviors of {@link View} and {@link InputConnection}.
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ViewInputConnectionTest {
+ @DurationMillisLong
+ private static final long TIMEOUT = 5000;
+ @DurationMillisLong
+ private static final long EXPECTED_TIMEOUT = 500;
+
@Rule
public ActivityTestRule<ViewInputConnectionTestActivity> mActivityRule =
new ActivityTestRule<>(ViewInputConnectionTestActivity.class);
@@ -289,4 +312,282 @@ public class ViewInputConnectionTest {
super.onInputConnectionClosedInternal();
}
}
+
+
+ @Test
+ public void testInputConnectionCallbacks_nonUiThread() throws Throwable {
+ try (InputConnectionHandlingThread thread = new InputConnectionHandlingThread()) {
+ final ViewGroup viewGroup = getOnMainSync(() -> mActivity.findViewById(R.id.root));
+ final TestOffThreadEditor editor = getOnMainSync(() -> {
+ final TestOffThreadEditor myEditor =
+ new TestOffThreadEditor(viewGroup.getContext(), thread.getHandler());
+ viewGroup.addView(myEditor);
+ myEditor.requestFocus();
+ return myEditor;
+ });
+
+ mInstrumentation.waitForIdleSync();
+
+ assertThat(editor.mOnCreateInputConnectionCalled.await(TIMEOUT, TimeUnit.MILLISECONDS))
+ .isTrue();
+
+ // Invalidate the currently used InputConnection by moving the focus to a new EditText.
+ mActivityRule.runOnUiThread(() -> {
+ final EditText editText = new EditText(viewGroup.getContext());
+ viewGroup.addView(editText);
+ editText.requestFocus();
+ });
+
+ // Make sure that InputConnection#closeConnection() gets called on the handler thread.
+ assertThat(editor.mInputConnectionClosedCalled.await(TIMEOUT, TimeUnit.MILLISECONDS))
+ .isTrue();
+ assertThat(editor.mInputConnectionClosedCallingThreadId.get())
+ .isEqualTo(thread.getThreadId());
+
+ // Make sure that View#onInputConnectionClosed() is not yet dispatched, because
+ // InputConnection#closeConnection() is still blocked.
+ assertThat(editor.mOnInputConnectionClosedCalled.await(
+ EXPECTED_TIMEOUT, TimeUnit.MILLISECONDS)).isFalse();
+
+ // Unblock InputConnection#closeConnection()
+ editor.mInputConnectionClosedBlocker.countDown();
+
+ // Make sure that View#onInputConnectionClosed() is dispatched on the main thread.
+ assertThat(editor.mOnInputConnectionClosedCalled.await(TIMEOUT, TimeUnit.MILLISECONDS))
+ .isTrue();
+ assertThat(editor.mInputConnectionClosedBlockerTimedOut.get()).isFalse();
+ assertThat(editor.mOnInputConnectionClosedCallingThreadId.get())
+ .isEqualTo(getOnMainSync(Process::myTid));
+ }
+ }
+
+ private <T> T getOnMainSync(@NonNull Supplier<T> supplier) throws Throwable {
+ final AtomicReference<T> result = new AtomicReference<>();
+ mActivityRule.runOnUiThread(() -> result.set(supplier.get()));
+ return result.get();
+ }
+
+ private static class TestOffThreadEditor extends View {
+ private static final int TEST_VIEW_HEIGHT = 10;
+
+ public CountDownLatch mOnCreateInputConnectionCalled = new CountDownLatch(1);
+ public CountDownLatch mInputConnectionClosedCalled = new CountDownLatch(1);
+ public CountDownLatch mInputConnectionClosedBlocker = new CountDownLatch(1);
+ public AtomicBoolean mInputConnectionClosedBlockerTimedOut = new AtomicBoolean();
+ public AtomicReference<Integer> mInputConnectionClosedCallingThreadId =
+ new AtomicReference<>();
+
+ public CountDownLatch mOnInputConnectionClosedCalled = new CountDownLatch(1);
+ public AtomicReference<Integer> mOnInputConnectionClosedCallingThreadId =
+ new AtomicReference<>();
+
+ private final Handler mInputConnectionHandler;
+
+ TestOffThreadEditor(Context context, @NonNull Handler inputConnectionHandler) {
+ super(context);
+ setBackgroundColor(Color.YELLOW);
+ setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, TEST_VIEW_HEIGHT));
+ setFocusableInTouchMode(true);
+ setFocusable(true);
+ mInputConnectionHandler = inputConnectionHandler;
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ mOnCreateInputConnectionCalled.countDown();
+ outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
+ return new NoOpInputConnection() {
+ @Override
+ public Handler getHandler() {
+ return mInputConnectionHandler;
+ }
+
+ @Override
+ public void closeConnection() {
+ mInputConnectionClosedCallingThreadId.compareAndSet(null, Process.myTid());
+ mInputConnectionClosedCalled.countDown();
+ try {
+ if (mInputConnectionClosedBlocker.await(TIMEOUT, TimeUnit.MILLISECONDS)) {
+ return;
+ }
+ } catch (InterruptedException e) {
+ }
+ mInputConnectionClosedBlockerTimedOut.set(true);
+ }
+ };
+ }
+
+ @Override
+ public boolean onCheckIsTextEditor() {
+ return true;
+ }
+
+ @Override
+ public void onInputConnectionClosedInternal() {
+ mOnInputConnectionClosedCallingThreadId.compareAndSet(null, Process.myTid());
+ mOnInputConnectionClosedCalled.countDown();
+ super.onInputConnectionClosedInternal();
+ }
+ }
+
+ static class NoOpInputConnection implements InputConnection {
+
+ @Override
+ public CharSequence getTextBeforeCursor(int n, int flags) {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTextAfterCursor(int n, int flags) {
+ return null;
+ }
+
+ @Override
+ public CharSequence getSelectedText(int flags) {
+ return null;
+ }
+
+ @Override
+ public int getCursorCapsMode(int reqModes) {
+ return 0;
+ }
+
+ @Override
+ public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
+ return null;
+ }
+
+ @Override
+ public boolean deleteSurroundingText(int beforeLength, int afterLength) {
+ return false;
+ }
+
+ @Override
+ public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
+ return false;
+ }
+
+ @Override
+ public boolean setComposingText(CharSequence text, int newCursorPosition) {
+ return false;
+ }
+
+ @Override
+ public boolean setComposingRegion(int start, int end) {
+ return false;
+ }
+
+ @Override
+ public boolean finishComposingText() {
+ return false;
+ }
+
+ @Override
+ public boolean commitText(CharSequence text, int newCursorPosition) {
+ return false;
+ }
+
+ @Override
+ public boolean commitCompletion(CompletionInfo text) {
+ return false;
+ }
+
+ @Override
+ public boolean commitCorrection(CorrectionInfo correctionInfo) {
+ return false;
+ }
+
+ @Override
+ public boolean setSelection(int start, int end) {
+ return false;
+ }
+
+ @Override
+ public boolean performEditorAction(int editorAction) {
+ return false;
+ }
+
+ @Override
+ public boolean performContextMenuAction(int id) {
+ return false;
+ }
+
+ @Override
+ public boolean beginBatchEdit() {
+ return false;
+ }
+
+ @Override
+ public boolean endBatchEdit() {
+ return false;
+ }
+
+ @Override
+ public boolean sendKeyEvent(KeyEvent event) {
+ return false;
+ }
+
+ @Override
+ public boolean clearMetaKeyStates(int states) {
+ return false;
+ }
+
+ @Override
+ public boolean reportFullscreenMode(boolean enabled) {
+ return false;
+ }
+
+ @Override
+ public boolean performPrivateCommand(String action, Bundle data) {
+ return false;
+ }
+
+ @Override
+ public boolean requestCursorUpdates(int cursorUpdateMode) {
+ return false;
+ }
+
+ @Override
+ public Handler getHandler() {
+ return null;
+ }
+
+ @Override
+ public void closeConnection() {
+
+ }
+
+ @Override
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+ return false;
+ }
+ }
+
+ private static final class InputConnectionHandlingThread extends HandlerThread
+ implements AutoCloseable {
+
+ private final Handler mHandler;
+
+ InputConnectionHandlingThread() {
+ super("IC-callback");
+ start();
+ mHandler = Handler.createAsync(getLooper());
+ }
+
+ @NonNull
+ Handler getHandler() {
+ return mHandler;
+ }
+
+ @Override
+ public void close() {
+ quitSafely();
+ try {
+ join(TIMEOUT);
+ } catch (InterruptedException e) {
+ fail("Failed to stop the thread: " + e);
+ }
+ }
+ }
}
diff --git a/core/tests/uwbtests/AndroidManifest.xml b/core/tests/uwbtests/AndroidManifest.xml
deleted file mode 100644
index dc991ff636d2..000000000000
--- a/core/tests/uwbtests/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.uwb">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <!-- This is a self-instrumenting test package. -->
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.uwb"
- android:label="UWB Manager Tests">
- </instrumentation>
-
-</manifest>
-
diff --git a/core/tests/uwbtests/OWNERS b/core/tests/uwbtests/OWNERS
deleted file mode 100644
index c7b09a21e1d0..000000000000
--- a/core/tests/uwbtests/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /core/java/android/uwb/OWNERS
diff --git a/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java b/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java
deleted file mode 100644
index 4cad535a3a51..000000000000
--- a/core/tests/uwbtests/src/android/uwb/AdapterStateListenerTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.os.RemoteException;
-import android.uwb.UwbManager.AdapterStateCallback;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Test of {@link AdapterStateListener}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AdapterStateListenerTest {
-
- IUwbAdapter mUwbAdapter = mock(IUwbAdapter.class);
-
- Answer mRegisterSuccessAnswer = new Answer() {
- public Object answer(InvocationOnMock invocation) {
- Object[] args = invocation.getArguments();
- IUwbAdapterStateCallbacks cb = (IUwbAdapterStateCallbacks) args[0];
- try {
- cb.onAdapterStateChanged(AdapterState.STATE_DISABLED, StateChangeReason.UNKNOWN);
- } catch (RemoteException e) {
- // Nothing to do
- }
- return new Object();
- }
- };
-
- Throwable mThrowRemoteException = new RemoteException("RemoteException");
-
- private static Executor getExecutor() {
- return new Executor() {
- @Override
- public void execute(Runnable command) {
- command.run();
- }
- };
- }
-
- private static void verifyCallbackStateChangedInvoked(
- AdapterStateCallback callback, int numTimes) {
- verify(callback, times(numTimes)).onStateChanged(anyInt(), anyInt());
- }
-
- @Test
- public void testRegister_RegisterUnregister() throws RemoteException {
- doAnswer(mRegisterSuccessAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
-
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback1 = mock(AdapterStateCallback.class);
- AdapterStateCallback callback2 = mock(AdapterStateCallback.class);
-
- // Verify that the adapter state listener registered with the UWB Adapter
- adapterStateListener.register(getExecutor(), callback1);
- verify(mUwbAdapter, times(1)).registerAdapterStateCallbacks(any());
- verifyCallbackStateChangedInvoked(callback1, 1);
- verifyCallbackStateChangedInvoked(callback2, 0);
-
- // Register a second client and no new call to UWB Adapter
- adapterStateListener.register(getExecutor(), callback2);
- verify(mUwbAdapter, times(1)).registerAdapterStateCallbacks(any());
- verifyCallbackStateChangedInvoked(callback1, 1);
- verifyCallbackStateChangedInvoked(callback2, 1);
-
- // Unregister first callback
- adapterStateListener.unregister(callback1);
- verify(mUwbAdapter, times(1)).registerAdapterStateCallbacks(any());
- verify(mUwbAdapter, times(0)).unregisterAdapterStateCallbacks(any());
- verifyCallbackStateChangedInvoked(callback1, 1);
- verifyCallbackStateChangedInvoked(callback2, 1);
-
- // Unregister second callback
- adapterStateListener.unregister(callback2);
- verify(mUwbAdapter, times(1)).registerAdapterStateCallbacks(any());
- verify(mUwbAdapter, times(1)).unregisterAdapterStateCallbacks(any());
- verifyCallbackStateChangedInvoked(callback1, 1);
- verifyCallbackStateChangedInvoked(callback2, 1);
- }
-
- @Test
- public void testRegister_RegisterSameCallbackTwice() throws RemoteException {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
- doAnswer(mRegisterSuccessAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
-
- adapterStateListener.register(getExecutor(), callback);
- verifyCallbackStateChangedInvoked(callback, 1);
-
- adapterStateListener.register(getExecutor(), callback);
- verifyCallbackStateChangedInvoked(callback, 1);
-
- // Invoke a state change and ensure the callback is only called once
- adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
- StateChangeReason.UNKNOWN);
- verifyCallbackStateChangedInvoked(callback, 2);
- }
-
- @Test
- public void testCallback_RunViaExecutor_Success() throws RemoteException {
- // Verify that the callbacks are invoked on the executor when successful
- doAnswer(mRegisterSuccessAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
- runViaExecutor();
- }
-
- private void runViaExecutor() {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
-
- Executor executor = mock(Executor.class);
-
- // Do not run commands received and ensure that the callback is not invoked
- doAnswer(new ExecutorAnswer(false)).when(executor).execute(any());
- adapterStateListener.register(executor, callback);
- verify(executor, times(1)).execute(any());
- verifyCallbackStateChangedInvoked(callback, 0);
-
- // Manually invoke the callback and ensure callback is not invoked
- adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
- StateChangeReason.UNKNOWN);
- verify(executor, times(2)).execute(any());
- verifyCallbackStateChangedInvoked(callback, 0);
-
- // Run the command that the executor receives
- doAnswer(new ExecutorAnswer(true)).when(executor).execute(any());
- adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
- StateChangeReason.UNKNOWN);
- verify(executor, times(3)).execute(any());
- verifyCallbackStateChangedInvoked(callback, 1);
- }
-
- class ExecutorAnswer implements Answer {
-
- final boolean mShouldRun;
- ExecutorAnswer(boolean shouldRun) {
- mShouldRun = shouldRun;
- }
-
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- if (mShouldRun) {
- ((Runnable) invocation.getArgument(0)).run();
- }
- return null;
- }
- }
-
- @Test
- public void testNotify_AllCallbacksNotified() throws RemoteException {
- doAnswer(mRegisterSuccessAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
-
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- List<AdapterStateCallback> callbacks = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
- adapterStateListener.register(getExecutor(), callback);
- callbacks.add(callback);
- }
-
- // Ensure every callback got the initial state
- for (AdapterStateCallback callback : callbacks) {
- verifyCallbackStateChangedInvoked(callback, 1);
- }
-
- // Invoke a state change and ensure all callbacks are invoked
- adapterStateListener.onAdapterStateChanged(AdapterState.STATE_DISABLED,
- StateChangeReason.ALL_SESSIONS_CLOSED);
- for (AdapterStateCallback callback : callbacks) {
- verifyCallbackStateChangedInvoked(callback, 2);
- }
- }
-
- @Test
- public void testStateChange_CorrectValue() {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
-
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
-
- adapterStateListener.register(getExecutor(), callback);
-
- runStateChangeValue(StateChangeReason.ALL_SESSIONS_CLOSED,
- AdapterState.STATE_ENABLED_INACTIVE,
- AdapterStateCallback.STATE_CHANGED_REASON_ALL_SESSIONS_CLOSED,
- AdapterStateCallback.STATE_ENABLED_INACTIVE);
-
- runStateChangeValue(StateChangeReason.SESSION_STARTED, AdapterState.STATE_ENABLED_ACTIVE,
- AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED,
- AdapterStateCallback.STATE_ENABLED_ACTIVE);
-
- runStateChangeValue(StateChangeReason.SYSTEM_BOOT, AdapterState.STATE_DISABLED,
- AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT,
- AdapterStateCallback.STATE_DISABLED);
-
- runStateChangeValue(StateChangeReason.SYSTEM_POLICY, AdapterState.STATE_DISABLED,
- AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY,
- AdapterStateCallback.STATE_DISABLED);
-
- runStateChangeValue(StateChangeReason.UNKNOWN, AdapterState.STATE_DISABLED,
- AdapterStateCallback.STATE_CHANGED_REASON_ERROR_UNKNOWN,
- AdapterStateCallback.STATE_DISABLED);
- }
-
- private void runStateChangeValue(@StateChangeReason int reasonIn, @AdapterState int stateIn,
- @AdapterStateCallback.StateChangedReason int reasonOut,
- @AdapterStateCallback.State int stateOut) {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
- adapterStateListener.register(getExecutor(), callback);
-
- adapterStateListener.onAdapterStateChanged(stateIn, reasonIn);
- verify(callback, times(1)).onStateChanged(stateOut, reasonOut);
- }
-
- @Test
- public void testStateChange_FirstRegisterGetsCorrectState() throws RemoteException {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback = mock(AdapterStateCallback.class);
-
- Answer registerAnswer = new Answer() {
- public Object answer(InvocationOnMock invocation) {
- Object[] args = invocation.getArguments();
- IUwbAdapterStateCallbacks cb = (IUwbAdapterStateCallbacks) args[0];
- try {
- cb.onAdapterStateChanged(AdapterState.STATE_ENABLED_ACTIVE,
- StateChangeReason.SESSION_STARTED);
- } catch (RemoteException e) {
- // Nothing to do
- }
- return new Object();
- }
- };
-
- doAnswer(registerAnswer).when(mUwbAdapter).registerAdapterStateCallbacks(any());
-
- adapterStateListener.register(getExecutor(), callback);
- verify(callback).onStateChanged(AdapterStateCallback.STATE_ENABLED_ACTIVE,
- AdapterStateCallback.STATE_CHANGED_REASON_SESSION_STARTED);
- }
-
- @Test
- public void testStateChange_SecondRegisterGetsCorrectState() {
- AdapterStateListener adapterStateListener = new AdapterStateListener(mUwbAdapter);
- AdapterStateCallback callback1 = mock(AdapterStateCallback.class);
- AdapterStateCallback callback2 = mock(AdapterStateCallback.class);
-
- adapterStateListener.register(getExecutor(), callback1);
- adapterStateListener.onAdapterStateChanged(AdapterState.STATE_ENABLED_ACTIVE,
- StateChangeReason.SYSTEM_BOOT);
-
- adapterStateListener.register(getExecutor(), callback2);
- verify(callback2).onStateChanged(AdapterStateCallback.STATE_ENABLED_ACTIVE,
- AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_BOOT);
- }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
deleted file mode 100644
index 24267e46e9e2..000000000000
--- a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.AttributionSource;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.util.concurrent.Executor;
-
-/**
- * Test of {@link AdapterStateListener}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingManagerTest {
-
- private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
- private static final PersistableBundle PARAMS = new PersistableBundle();
- private static final @RangingChangeReason int REASON = RangingChangeReason.UNKNOWN;
- private static final int UID = 343453;
- private static final String PACKAGE_NAME = "com.uwb.test";
- private static final AttributionSource ATTRIBUTION_SOURCE =
- new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
-
- @Test
- public void testOpenSession_OpenRangingInvoked() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingManager rangingManager = new RangingManager(adapter);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), any(), any(), any());
- }
-
- @Test
- public void testOnRangingOpened_InvalidSessionHandle() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingManager rangingManager = new RangingManager(adapter);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
-
- rangingManager.onRangingOpened(new SessionHandle(2));
- verify(callback, times(0)).onOpened(any());
- }
-
- @Test
- public void testOnRangingOpened_MultipleSessionsRegistered() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
- RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
- ArgumentCaptor<SessionHandle> sessionHandleCaptor =
- ArgumentCaptor.forClass(SessionHandle.class);
-
- RangingManager rangingManager = new RangingManager(adapter);
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();
-
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
- verify(adapter, times(2)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();
-
- rangingManager.onRangingOpened(sessionHandle1);
- verify(callback1, times(1)).onOpened(any());
- verify(callback2, times(0)).onOpened(any());
-
- rangingManager.onRangingOpened(sessionHandle2);
- verify(callback1, times(1)).onOpened(any());
- verify(callback2, times(1)).onOpened(any());
- }
-
- @Test
- public void testCorrectCallbackInvoked() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingManager rangingManager = new RangingManager(adapter);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
-
- ArgumentCaptor<SessionHandle> sessionHandleCaptor =
- ArgumentCaptor.forClass(SessionHandle.class);
-
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle handle = sessionHandleCaptor.getValue();
-
- rangingManager.onRangingOpened(handle);
- verify(callback, times(1)).onOpened(any());
-
- rangingManager.onRangingStarted(handle, PARAMS);
- verify(callback, times(1)).onStarted(eq(PARAMS));
-
- rangingManager.onRangingStartFailed(handle, REASON, PARAMS);
- verify(callback, times(1)).onStartFailed(eq(REASON), eq(PARAMS));
-
- RangingReport report = UwbTestUtils.getRangingReports(1);
- rangingManager.onRangingResult(handle, report);
- verify(callback, times(1)).onReportReceived(eq(report));
-
- rangingManager.onRangingReconfigured(handle, PARAMS);
- verify(callback, times(1)).onReconfigured(eq(PARAMS));
-
- rangingManager.onRangingReconfigureFailed(handle, REASON, PARAMS);
- verify(callback, times(1)).onReconfigureFailed(eq(REASON), eq(PARAMS));
-
- rangingManager.onRangingStopped(handle, REASON, PARAMS);
- verify(callback, times(1)).onStopped(eq(REASON), eq(PARAMS));
-
- rangingManager.onRangingStopFailed(handle, REASON, PARAMS);
- verify(callback, times(1)).onStopFailed(eq(REASON), eq(PARAMS));
-
- rangingManager.onRangingClosed(handle, REASON, PARAMS);
- verify(callback, times(1)).onClosed(eq(REASON), eq(PARAMS));
- }
-
- @Test
- public void testOnRangingClosed_MultipleSessionsRegistered() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- // Verify that if multiple sessions are registered, only the session that is
- // requested to close receives the associated callbacks
- RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
- RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
-
- RangingManager rangingManager = new RangingManager(adapter);
- ArgumentCaptor<SessionHandle> sessionHandleCaptor =
- ArgumentCaptor.forClass(SessionHandle.class);
-
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();
-
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
- verify(adapter, times(2)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();
-
- rangingManager.onRangingClosed(sessionHandle1, REASON, PARAMS);
- verify(callback1, times(1)).onClosed(anyInt(), any());
- verify(callback2, times(0)).onClosed(anyInt(), any());
-
- rangingManager.onRangingClosed(sessionHandle2, REASON, PARAMS);
- verify(callback1, times(1)).onClosed(anyInt(), any());
- verify(callback2, times(1)).onClosed(anyInt(), any());
- }
-
- @Test
- public void testOnRangingReport_MultipleSessionsRegistered() throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
- RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
-
- ArgumentCaptor<SessionHandle> sessionHandleCaptor =
- ArgumentCaptor.forClass(SessionHandle.class);
-
- RangingManager rangingManager = new RangingManager(adapter);
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();
-
- rangingManager.onRangingStarted(sessionHandle1, PARAMS);
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
- verify(adapter, times(2)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();
- rangingManager.onRangingStarted(sessionHandle2, PARAMS);
-
- rangingManager.onRangingResult(sessionHandle1, UwbTestUtils.getRangingReports(1));
- verify(callback1, times(1)).onReportReceived(any());
- verify(callback2, times(0)).onReportReceived(any());
-
- rangingManager.onRangingResult(sessionHandle2, UwbTestUtils.getRangingReports(1));
- verify(callback1, times(1)).onReportReceived(any());
- verify(callback2, times(1)).onReportReceived(any());
- }
-
- @Test
- public void testReasons() throws RemoteException {
- runReason(RangingChangeReason.LOCAL_API,
- RangingSession.Callback.REASON_LOCAL_REQUEST);
-
- runReason(RangingChangeReason.MAX_SESSIONS_REACHED,
- RangingSession.Callback.REASON_MAX_SESSIONS_REACHED);
-
- runReason(RangingChangeReason.PROTOCOL_SPECIFIC,
- RangingSession.Callback.REASON_PROTOCOL_SPECIFIC_ERROR);
-
- runReason(RangingChangeReason.REMOTE_REQUEST,
- RangingSession.Callback.REASON_REMOTE_REQUEST);
-
- runReason(RangingChangeReason.SYSTEM_POLICY,
- RangingSession.Callback.REASON_SYSTEM_POLICY);
-
- runReason(RangingChangeReason.BAD_PARAMETERS,
- RangingSession.Callback.REASON_BAD_PARAMETERS);
-
- runReason(RangingChangeReason.UNKNOWN,
- RangingSession.Callback.REASON_UNKNOWN);
- }
-
- private void runReason(@RangingChangeReason int reasonIn,
- @RangingSession.Callback.Reason int reasonOut) throws RemoteException {
- IUwbAdapter adapter = mock(IUwbAdapter.class);
- RangingManager rangingManager = new RangingManager(adapter);
- RangingSession.Callback callback = mock(RangingSession.Callback.class);
-
- ArgumentCaptor<SessionHandle> sessionHandleCaptor =
- ArgumentCaptor.forClass(SessionHandle.class);
-
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
- verify(adapter, times(1)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- SessionHandle handle = sessionHandleCaptor.getValue();
-
- rangingManager.onRangingOpenFailed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onOpenFailed(eq(reasonOut), eq(PARAMS));
-
- // Open a new session
- rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
- verify(adapter, times(2)).openRanging(
- eq(ATTRIBUTION_SOURCE), sessionHandleCaptor.capture(), any(), any());
- handle = sessionHandleCaptor.getValue();
- rangingManager.onRangingOpened(handle);
-
- rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onStartFailed(eq(reasonOut), eq(PARAMS));
-
- rangingManager.onRangingReconfigureFailed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onReconfigureFailed(eq(reasonOut), eq(PARAMS));
-
- rangingManager.onRangingStopFailed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onStopFailed(eq(reasonOut), eq(PARAMS));
-
- rangingManager.onRangingClosed(handle, reasonIn, PARAMS);
- verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
- }
-}
diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
deleted file mode 100644
index 75c6924a1939..000000000000
--- a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.uwb;
-
-import android.os.SystemClock;
-
-import java.util.concurrent.Executor;
-
-public class UwbTestUtils {
- private UwbTestUtils() {}
-
- public static AngleMeasurement getAngleMeasurement() {
- return new AngleMeasurement(
- getDoubleInRange(-Math.PI, Math.PI),
- getDoubleInRange(0, Math.PI),
- getDoubleInRange(0, 1));
- }
-
- public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() {
- return new AngleOfArrivalMeasurement.Builder(getAngleMeasurement())
- .setAltitude(getAngleMeasurement())
- .build();
- }
-
- public static DistanceMeasurement getDistanceMeasurement() {
- return new DistanceMeasurement.Builder()
- .setMeters(getDoubleInRange(0, 100))
- .setErrorMeters(getDoubleInRange(0, 10))
- .setConfidenceLevel(getDoubleInRange(0, 1))
- .build();
- }
-
- public static RangingMeasurement getRangingMeasurement() {
- return getRangingMeasurement(getUwbAddress(false));
- }
-
- public static RangingMeasurement getRangingMeasurement(UwbAddress address) {
- return new RangingMeasurement.Builder()
- .setDistanceMeasurement(getDistanceMeasurement())
- .setAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement())
- .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos())
- .setRemoteDeviceAddress(address != null ? address : getUwbAddress(false))
- .setStatus(RangingMeasurement.RANGING_STATUS_SUCCESS)
- .build();
- }
-
- public static RangingReport getRangingReports(int numMeasurements) {
- RangingReport.Builder builder = new RangingReport.Builder();
- for (int i = 0; i < numMeasurements; i++) {
- builder.addMeasurement(getRangingMeasurement());
- }
- return builder.build();
- }
-
- private static double getDoubleInRange(double min, double max) {
- return min + (max - min) * Math.random();
- }
-
- public static UwbAddress getUwbAddress(boolean isShortAddress) {
- byte[] addressBytes = new byte[isShortAddress ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH :
- UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH];
- for (int i = 0; i < addressBytes.length; i++) {
- addressBytes[i] = (byte) getDoubleInRange(1, 255);
- }
- return UwbAddress.fromBytes(addressBytes);
- }
-
- public static Executor getExecutor() {
- return new Executor() {
- @Override
- public void execute(Runnable command) {
- command.run();
- }
- };
- }
-}
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/BinderIdentityChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/BinderIdentityChecker.java
index 68477edf97d1..00cd18ca596a 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/BinderIdentityChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/BinderIdentityChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.contains;
import static com.google.errorprone.matchers.Matchers.methodInvocation;
@@ -52,6 +53,7 @@ import javax.lang.model.element.Modifier;
@BugPattern(
name = "AndroidFrameworkBinderIdentity",
summary = "Verifies that Binder.clearCallingIdentity() is always restored",
+ linkType = NONE,
severity = WARNING)
public final class BinderIdentityChecker extends BugChecker implements MethodInvocationTreeMatcher {
private static final Matcher<ExpressionTree> CLEAR_CALL = methodInvocation(staticMethod()
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java
index 9d1cf87a5f9d..4bee99e0ffca 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.bugpatterns.android.RequiresPermissionChecker.simpleNameMatches;
import static com.google.errorprone.matchers.Matchers.allOf;
@@ -60,6 +61,7 @@ import java.util.regex.Pattern;
@BugPattern(
name = "AndroidFrameworkBluetoothPermission",
summary = "Verifies that all Bluetooth APIs have consistent permissions",
+ linkType = NONE,
severity = WARNING)
public final class BluetoothPermissionChecker extends BugChecker implements MethodTreeMatcher {
private static final Matcher<MethodTree> BLUETOOTH_API = allOf(
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/ClientSidePermissionCheckChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/ClientSidePermissionCheckChecker.java
index 8651a1a7fbeb..d27e7a146866 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/ClientSidePermissionCheckChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/ClientSidePermissionCheckChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.enclosingClass;
@@ -42,6 +43,7 @@ import com.sun.source.tree.Tree;
@BugPattern(
name = "AndroidFrameworkClientSidePermissionCheck",
summary = "Verifies that permission checks aren't done in the app's process",
+ linkType = NONE,
severity = WARNING)
public final class ClientSidePermissionCheckChecker
extends BugChecker implements MethodInvocationTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java
index e759663b5d16..43abc8bc3e54 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.bugpatterns.android.TargetSdkChecker.binaryTreeExact;
import static com.google.errorprone.matchers.Matchers.allOf;
@@ -51,6 +52,7 @@ import com.sun.source.tree.Tree.Kind;
@BugPattern(
name = "AndroidFrameworkCompatChange",
summary = "Verifies that behavior changes use the modern compatibility framework",
+ linkType = NONE,
severity = WARNING)
public final class CompatChangeChecker extends BugChecker implements BinaryTreeMatcher {
private static final Matcher<ExpressionTree> VERSION_CODE =
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
index 3a1bc1eeb9ae..c1a2048fb59d 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.bugpatterns.android.UidChecker.getFlavor;
import static com.google.errorprone.matchers.Matchers.anyOf;
@@ -54,6 +55,7 @@ import java.util.List;
@BugPattern(
name = "AndroidFrameworkContextUserId",
summary = "Verifies that system_server calls use Context.getUserId()",
+ linkType = NONE,
severity = WARNING)
public final class ContextUserIdChecker extends BugChecker implements MethodInvocationTreeMatcher {
private static final Matcher<Tree> INSIDE_MANAGER =
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientCollectionsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientCollectionsChecker.java
index c4c1ab6482ee..209dafaaa8fe 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientCollectionsChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientCollectionsChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
@@ -43,6 +44,7 @@ import java.util.List;
@BugPattern(
name = "AndroidFrameworkEfficientCollections",
summary = "Verifies efficient collections best-practices",
+ linkType = NONE,
severity = WARNING)
public final class EfficientCollectionsChecker extends BugChecker implements NewClassTreeMatcher {
private static final Matcher<Tree> IS_LIST = isSubtypeOf("java.util.List");
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java
index c29a095ecc1b..cae5d8e6846d 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.enclosingClass;
@@ -45,6 +46,7 @@ import com.sun.source.tree.Tree;
@BugPattern(
name = "AndroidFrameworkEfficientParcelable",
summary = "Verifies Parcelable performance best-practices",
+ linkType = NONE,
severity = WARNING)
public final class EfficientParcelableChecker extends BugChecker
implements MethodInvocationTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
index 3a0fbd33933f..5c60d779188c 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
@@ -63,6 +64,7 @@ import javax.lang.model.element.Modifier;
@BugPattern(
name = "AndroidFrameworkEfficientStrings",
summary = "Verifies efficient Strings best-practices",
+ linkType = NONE,
severity = WARNING)
public final class EfficientStringsChecker extends BugChecker
implements MethodInvocationTreeMatcher, NewClassTreeMatcher, CompoundAssignmentTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
index b5f26e7dc9dd..8706a68226ef 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
@@ -61,6 +62,7 @@ import javax.lang.model.element.Name;
@BugPattern(
name = "AndroidFrameworkEfficientXml",
summary = "Verifies efficient XML best-practices",
+ linkType = NONE,
severity = WARNING)
public final class EfficientXmlChecker extends BugChecker
implements MethodInvocationTreeMatcher, NewClassTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java
index e323a895ee94..c1e08217a163 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.contains;
@@ -45,6 +46,7 @@ import java.util.regex.Pattern;
@BugPattern(
name = "AndroidFrameworkPendingIntentMutability",
summary = "Verifies that FLAG_MUTABLE or FLAG_IMMUTABLE is always set",
+ linkType = NONE,
severity = WARNING)
public final class PendingIntentMutabilityChecker extends BugChecker
implements MethodInvocationTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index d1e4309c365e..9a41cb46f194 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
@@ -79,6 +80,7 @@ import javax.lang.model.element.Name;
@BugPattern(
name = "AndroidFrameworkRequiresPermission",
summary = "Verifies that @RequiresPermission annotations are consistent across AIDL",
+ linkType = NONE,
severity = WARNING)
public final class RequiresPermissionChecker extends BugChecker
implements MethodTreeMatcher, MethodInvocationTreeMatcher {
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RethrowFromSystemChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RethrowFromSystemChecker.java
index 130b256e6622..f8b401b213b8 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RethrowFromSystemChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RethrowFromSystemChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.contains;
@@ -60,6 +61,7 @@ import java.util.List;
@BugPattern(
name = "AndroidFrameworkRethrowFromSystem",
summary = "Verifies that system_server calls use rethrowFromSystemServer()",
+ linkType = NONE,
severity = WARNING)
public final class RethrowFromSystemChecker extends BugChecker implements TryTreeMatcher {
private static final Matcher<Tree> INSIDE_MANAGER =
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
index 032ae00536b9..5581d9987866 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
@@ -59,6 +60,7 @@ import com.sun.source.tree.Tree.Kind;
@BugPattern(
name = "AndroidFrameworkTargetSdk",
summary = "Verifies that all target SDK comparisons are sane",
+ linkType = NONE,
severity = WARNING)
public final class TargetSdkChecker extends BugChecker implements BinaryTreeMatcher {
private static final Matcher<ExpressionTree> VERSION_CODE = FieldMatchers
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/UidChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/UidChecker.java
index a2ee065cd1cc..a4ad069fdfac 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/UidChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/UidChecker.java
@@ -16,6 +16,7 @@
package com.google.errorprone.bugpatterns.android;
+import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import com.google.auto.service.AutoService;
@@ -46,6 +47,7 @@ import java.util.regex.Pattern;
@BugPattern(
name = "AndroidFrameworkUid",
summary = "Verifies that PID, UID and user ID arguments aren't crossed",
+ linkType = NONE,
severity = WARNING)
public final class UidChecker extends BugChecker implements MethodInvocationTreeMatcher,
NewClassTreeMatcher {
diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java
index e2a05723166f..d5a6a2fe158a 100644
--- a/graphics/java/android/graphics/HardwareRendererObserver.java
+++ b/graphics/java/android/graphics/HardwareRendererObserver.java
@@ -21,12 +21,14 @@ import android.os.Handler;
import com.android.internal.util.VirtualRefBasePtr;
+import java.lang.ref.WeakReference;
+
/**
* Provides streaming access to frame stats information from HardwareRenderer to apps.
*
* @hide
*/
-public class HardwareRendererObserver {
+public final class HardwareRendererObserver {
private final long[] mFrameMetrics;
private final Handler mHandler;
private final OnFrameMetricsAvailableListener mListener;
@@ -74,15 +76,14 @@ public class HardwareRendererObserver {
mFrameMetrics = frameMetrics;
mHandler = handler;
mListener = listener;
- mNativePtr = new VirtualRefBasePtr(nCreateObserver(waitForPresentTime));
+ mNativePtr = new VirtualRefBasePtr(nCreateObserver(
+ new WeakReference<>(this), waitForPresentTime));
}
/*package*/ long getNativeInstance() {
return mNativePtr.get();
}
- // Called by native on the provided Handler
- @SuppressWarnings("unused")
private void notifyDataAvailable() {
mHandler.post(() -> {
boolean hasMoreData = true;
@@ -98,6 +99,21 @@ public class HardwareRendererObserver {
});
}
- private native long nCreateObserver(boolean waitForPresentTime);
+ /**
+ * called by native
+ * @hide
+ * @return true to keep listening, false if this is a dead observer
+ */
+ static boolean invokeDataAvailable(WeakReference<HardwareRendererObserver> weakObserver) {
+ HardwareRendererObserver observer = weakObserver.get();
+ if (observer != null) {
+ observer.notifyDataAvailable();
+ return true;
+ }
+ return false;
+ }
+
+ private static native long nCreateObserver(WeakReference<HardwareRendererObserver> observer,
+ boolean waitForPresentTime);
private static native int nGetNextBuffer(long nativePtr, long[] data);
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 51bf6d539ce8..42e470b7f660 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -255,12 +255,6 @@ public class Paint {
| FILTER_BITMAP_FLAG;
/**
- * These flags are always set on a reset paint or a new paint instantiated using
- * {@link #Paint()}.
- */
- private static final int DEFAULT_PAINT_FLAGS = ANTI_ALIAS_FLAG | DITHER_FLAG;
-
- /**
* Font hinter option that disables font hinting.
*
* @see #setHinting(int)
@@ -577,12 +571,12 @@ public class Paint {
* On devices running {@link Build.VERSION_CODES#Q} and above,
* {@code FILTER_BITMAP_FLAG} is set by this constructor, and it can be
* cleared with {@link #setFlags} or {@link #setFilterBitmap}.
- * On devices running {@link Build.VERSION_CODES#S} and above, {@code ANTI_ALIAS_FLAG} and
- * {@code DITHER_FLAG} are set by this constructor, and they can be cleared with
- * {@link #setFlags} or {@link #setAntiAlias} and {@link #setDither}, respectively.</p>
+ * On devices running {@link Build.VERSION_CODES#S} and above, {@code ANTI_ALIAS_FLAG}
+ * is set by this constructor, and it can be cleared with {@link #setFlags} or
+ * {@link #setAntiAlias}.</p>
*/
public Paint() {
- this(DEFAULT_PAINT_FLAGS);
+ this(ANTI_ALIAS_FLAG);
}
/**
@@ -627,7 +621,7 @@ public class Paint {
/** Restores the paint to its default settings. */
public void reset() {
nReset(mNativePaint);
- setFlags(HIDDEN_DEFAULT_PAINT_FLAGS | DEFAULT_PAINT_FLAGS);
+ setFlags(HIDDEN_DEFAULT_PAINT_FLAGS | ANTI_ALIAS_FLAG);
// TODO: Turning off hinting has undesirable side effects, we need to
// revisit hinting once we add support for subpixel positioning
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 01fd231d011f..5fd53adc409a 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -35,6 +35,7 @@ import libcore.util.NativeAllocationRegistry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
/**
* <p>RenderNode is used to build hardware accelerated rendering hierarchies. Each RenderNode
@@ -263,7 +264,6 @@ public final class RenderNode {
* @hide
*/
public interface PositionUpdateListener {
-
/**
* Called by native by a Rendering Worker thread to update window position
*
@@ -272,6 +272,21 @@ public final class RenderNode {
void positionChanged(long frameNumber, int left, int top, int right, int bottom);
/**
+ * Called by JNI
+ *
+ * @hide */
+ static boolean callPositionChanged(WeakReference<PositionUpdateListener> weakListener,
+ long frameNumber, int left, int top, int right, int bottom) {
+ final PositionUpdateListener listener = weakListener.get();
+ if (listener != null) {
+ listener.positionChanged(frameNumber, left, top, right, bottom);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Call to apply a stretch effect to any child SurfaceControl layers
*
* TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls?
@@ -286,6 +301,26 @@ public final class RenderNode {
float childRelativeTop, float childRelativeRight, float childRelativeBottom) { }
/**
+ * Called by JNI
+ *
+ * @hide */
+ static boolean callApplyStretch(WeakReference<PositionUpdateListener> weakListener,
+ long frameNumber, float width, float height,
+ float vecX, float vecY,
+ float maxStretchX, float maxStretchY, float childRelativeLeft,
+ float childRelativeTop, float childRelativeRight, float childRelativeBottom) {
+ final PositionUpdateListener listener = weakListener.get();
+ if (listener != null) {
+ listener.applyStretch(frameNumber, width, height, vecX, vecY, maxStretchX,
+ maxStretchY, childRelativeLeft, childRelativeTop, childRelativeRight,
+ childRelativeBottom);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Called by native on RenderThread to notify that the view is no longer in the
* draw tree. UI thread is blocked at this point.
*
@@ -293,6 +328,21 @@ public final class RenderNode {
*/
void positionLost(long frameNumber);
+ /**
+ * Called by JNI
+ *
+ * @hide */
+ static boolean callPositionLost(WeakReference<PositionUpdateListener> weakListener,
+ long frameNumber) {
+ final PositionUpdateListener listener = weakListener.get();
+ if (listener != null) {
+ listener.positionLost(frameNumber);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
}
private static final class CompositePositionUpdateListener implements PositionUpdateListener {
@@ -353,7 +403,7 @@ public final class RenderNode {
comp = comp.with(listener);
}
mCompositePositionUpdateListener = comp;
- nRequestPositionUpdates(mNativeRenderNode, comp);
+ nRequestPositionUpdates(mNativeRenderNode, new WeakReference<>(comp));
}
/**
@@ -368,7 +418,7 @@ public final class RenderNode {
if (comp != null) {
comp = comp.without(listener);
mCompositePositionUpdateListener = comp;
- nRequestPositionUpdates(mNativeRenderNode, comp);
+ nRequestPositionUpdates(mNativeRenderNode, new WeakReference<>(comp));
}
}
@@ -1575,7 +1625,7 @@ public final class RenderNode {
private static native int nGetAllocatedSize(long renderNode);
private static native void nRequestPositionUpdates(long renderNode,
- PositionUpdateListener callback);
+ WeakReference<PositionUpdateListener> callback);
// Animations
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 3616a4d66399..166a795e1661 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -723,8 +723,17 @@ public class GradientDrawable extends Drawable {
*/
@Nullable
public int[] getColors() {
- return mGradientState.mGradientColors == null ?
- null : mGradientState.mGradientColors.clone();
+ if (mGradientState.mGradientColors == null) {
+ return null;
+ } else {
+ int[] colors = new int[mGradientState.mGradientColors.length];
+ for (int i = 0; i < mGradientState.mGradientColors.length; i++) {
+ if (mGradientState.mGradientColors[i] != null) {
+ colors[i] = mGradientState.mGradientColors[i].getDefaultColor();
+ }
+ }
+ return colors;
+ }
}
@Override
@@ -1277,7 +1286,15 @@ public class GradientDrawable extends Drawable {
mRect.set(bounds.left + inset, bounds.top + inset,
bounds.right - inset, bounds.bottom - inset);
- final int[] gradientColors = st.mGradientColors;
+ int[] gradientColors = null;
+ if (st.mGradientColors != null) {
+ gradientColors = new int[st.mGradientColors.length];
+ for (int i = 0; i < gradientColors.length; i++) {
+ if (st.mGradientColors[i] != null) {
+ gradientColors[i] = st.mGradientColors[i].getDefaultColor();
+ }
+ }
+ }
if (gradientColors != null) {
final RectF r = mRect;
final float x0, x1, y0, y1;
@@ -1439,6 +1456,14 @@ public class GradientDrawable extends Drawable {
state.mStrokeColors = state.mStrokeColors.obtainForTheme(t);
}
+ if (state.mGradientColors != null) {
+ for (int i = 0; i < state.mGradientColors.length; i++) {
+ if (state.mGradientColors[i] != null && state.mGradientColors[i].canApplyTheme()) {
+ state.mGradientColors[i] = state.mGradientColors[i].obtainForTheme(t);
+ }
+ }
+ }
+
applyThemeChildElements(t);
updateLocalState(t.getResources());
@@ -1726,38 +1751,46 @@ public class GradientDrawable extends Drawable {
st.mGradient = a.getInt(
R.styleable.GradientDrawableGradient_type, st.mGradient);
+ ColorStateList startCSL = a.getColorStateList(
+ R.styleable.GradientDrawableGradient_startColor);
+ ColorStateList centerCSL = a.getColorStateList(
+ R.styleable.GradientDrawableGradient_centerColor);
+ ColorStateList endCSL = a.getColorStateList(
+ R.styleable.GradientDrawableGradient_endColor);
+
final boolean hasGradientColors = st.mGradientColors != null;
final boolean hasGradientCenter = st.hasCenterColor();
- final int prevStart = hasGradientColors ? st.mGradientColors[0] : 0;
- final int prevCenter = hasGradientCenter ? st.mGradientColors[1] : 0;
- final int prevEnd;
- if (st.hasCenterColor()) {
+ int startColor = startCSL != null ? startCSL.getDefaultColor() : 0;
+ int centerColor = centerCSL != null ? centerCSL.getDefaultColor() : 0;
+ int endColor = endCSL != null ? endCSL.getDefaultColor() : 0;
+
+ if (hasGradientColors && st.mGradientColors[0] != null) {
+ startColor = st.mGradientColors[0].getDefaultColor();
+ }
+ if (hasGradientCenter && st.mGradientColors[1] != null) {
+ centerColor = st.mGradientColors[1].getDefaultColor();
+ }
+ if (hasGradientCenter && st.mGradientColors[2] != null) {
// if there is a center color, the end color is the last of the 3 values
- prevEnd = st.mGradientColors[2];
- } else if (hasGradientColors) {
+ endColor = st.mGradientColors[2].getDefaultColor();
+ } else if (hasGradientColors && st.mGradientColors[1] != null) {
// if there is not a center color but there are already colors configured, then
// the end color is the 2nd value in the array
- prevEnd = st.mGradientColors[1];
- } else {
- // otherwise, there isn't a previously configured end color
- prevEnd = 0;
+ endColor = st.mGradientColors[1].getDefaultColor();
}
- final int startColor = a.getColor(
- R.styleable.GradientDrawableGradient_startColor, prevStart);
final boolean hasCenterColor = a.hasValue(
R.styleable.GradientDrawableGradient_centerColor) || hasGradientCenter;
- final int centerColor = a.getColor(
- R.styleable.GradientDrawableGradient_centerColor, prevCenter);
- final int endColor = a.getColor(
- R.styleable.GradientDrawableGradient_endColor, prevEnd);
if (hasCenterColor) {
- st.mGradientColors = new int[3];
- st.mGradientColors[0] = startColor;
- st.mGradientColors[1] = centerColor;
- st.mGradientColors[2] = endColor;
+ st.mGradientColors = new ColorStateList[3];
+ st.mGradientColors[0] =
+ startCSL != null ? startCSL : ColorStateList.valueOf(startColor);
+ st.mGradientColors[1] =
+ centerCSL != null ? centerCSL : ColorStateList.valueOf(centerColor);
+ st.mGradientColors[2] =
+ endCSL != null ? endCSL : ColorStateList.valueOf(endColor);
st.mPositions = new float[3];
st.mPositions[0] = 0.0f;
@@ -1765,9 +1798,11 @@ public class GradientDrawable extends Drawable {
st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY;
st.mPositions[2] = 1f;
} else {
- st.mGradientColors = new int[2];
- st.mGradientColors[0] = startColor;
- st.mGradientColors[1] = endColor;
+ st.mGradientColors = new ColorStateList[2];
+ st.mGradientColors[0] =
+ startCSL != null ? startCSL : ColorStateList.valueOf(startColor);
+ st.mGradientColors[1] =
+ endCSL != null ? endCSL : ColorStateList.valueOf(endColor);
}
int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
@@ -1981,7 +2016,7 @@ public class GradientDrawable extends Drawable {
public ColorStateList mSolidColors;
public ColorStateList mStrokeColors;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
- public @ColorInt int[] mGradientColors;
+ public ColorStateList[] mGradientColors; // no support for state-based color
public @ColorInt int[] mTempColors; // no need to copy
public float[] mTempPositions; // no need to copy
@UnsupportedAppUsage
@@ -2188,6 +2223,13 @@ public class GradientDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
+ boolean mGradientColorState = mGradientColors != null;
+ if (mGradientColors != null) {
+ for (int i = 0; i < mGradientColors.length; i++) {
+ mGradientColorState |= (mGradientColors[i] != null && mGradientColors[i]
+ .canApplyTheme());
+ }
+ }
return mThemeAttrs != null
|| mAttrSize != null || mAttrGradient != null
|| mAttrSolid != null || mAttrStroke != null
@@ -2195,6 +2237,7 @@ public class GradientDrawable extends Drawable {
|| (mTint != null && mTint.canApplyTheme())
|| (mStrokeColors != null && mStrokeColors.canApplyTheme())
|| (mSolidColors != null && mSolidColors.canApplyTheme())
+ || mGradientColorState
|| super.canApplyTheme();
}
@@ -2246,7 +2289,18 @@ public class GradientDrawable extends Drawable {
}
public void setGradientColors(@Nullable int[] colors) {
- mGradientColors = colors;
+ if (colors == null) {
+ mGradientColors = null;
+ } else {
+ // allocate new CSL array only if the size of the current array is different
+ // from the size of the given parameter
+ if (mGradientColors == null || mGradientColors.length != colors.length) {
+ mGradientColors = new ColorStateList[colors.length];
+ }
+ for (int i = 0; i < colors.length; i++) {
+ mGradientColors[i] = ColorStateList.valueOf(colors[i]);
+ }
+ }
mSolidColors = null;
computeOpacity();
}
@@ -2263,7 +2317,8 @@ public class GradientDrawable extends Drawable {
if (mGradientColors != null) {
for (int i = 0; i < mGradientColors.length; i++) {
- if (!isOpaque(mGradientColors[i])) {
+ if (mGradientColors[i] != null
+ && !isOpaque(mGradientColors[i].getDefaultColor())) {
return;
}
}
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index 492520910afd..872331c82603 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -67,7 +67,7 @@ public final class RippleAnimationSession {
@NonNull RippleAnimationSession enter(Canvas canvas) {
mStartTime = AnimationUtils.currentAnimationTimeMillis();
- if (isHwAccelerated(canvas)) {
+ if (useRTAnimations(canvas)) {
enterHardware((RecordingCanvas) canvas);
} else {
enterSoftware();
@@ -82,7 +82,7 @@ public final class RippleAnimationSession {
}
@NonNull RippleAnimationSession exit(Canvas canvas) {
- if (isHwAccelerated(canvas)) exitHardware((RecordingCanvas) canvas);
+ if (useRTAnimations(canvas)) exitHardware((RecordingCanvas) canvas);
else exitSoftware();
return this;
}
@@ -102,8 +102,12 @@ public final class RippleAnimationSession {
return this;
}
- private boolean isHwAccelerated(Canvas canvas) {
- return canvas.isHardwareAccelerated() && !mForceSoftware;
+ private boolean useRTAnimations(Canvas canvas) {
+ if (mForceSoftware) return false;
+ if (!canvas.isHardwareAccelerated()) return false;
+ RecordingCanvas hwCanvas = (RecordingCanvas) canvas;
+ if (hwCanvas.mNode == null || !hwCanvas.mNode.isAttached()) return false;
+ return true;
}
private void exitSoftware() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index d3cff5cb81ff..7354c90c5c98 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -49,7 +49,9 @@ import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
+import android.os.Looper;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
@@ -113,6 +115,7 @@ import java.util.Arrays;
* @attr ref android.R.styleable#RippleDrawable_color
*/
public class RippleDrawable extends LayerDrawable {
+ private static final String TAG = "RippleDrawable";
/**
* Radius value that specifies the ripple radius should be computed based
* on the size of the ripple's container.
@@ -848,6 +851,10 @@ public class RippleDrawable extends LayerDrawable {
private void startBackgroundAnimation() {
mRunBackgroundAnimation = false;
+ if (Looper.myLooper() == null) {
+ Log.w(TAG, "Thread doesn't have a looper. Skipping animation.");
+ return;
+ }
mBackgroundAnimation = ValueAnimator.ofFloat(mBackgroundOpacity, mTargetBackgroundOpacity);
mBackgroundAnimation.setInterpolator(LINEAR_INTERPOLATOR);
mBackgroundAnimation.setDuration(BACKGROUND_OPACITY_DURATION);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
index 0f2f23ebdbf1..531df30a4e2c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
@@ -159,13 +159,22 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
* @param ownerToken The token of the activity that creates this task fragment. It does not
* have to be a child of this task fragment, but must belong to the same task.
*/
+ void createTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken,
+ IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
+ final TaskFragmentCreationParams fragmentOptions =
+ createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
+ wct.createTaskFragment(fragmentOptions);
+ }
+
+ /**
+ * @param ownerToken The token of the activity that creates this task fragment. It does not
+ * have to be a child of this task fragment, but must belong to the same task.
+ */
private void createTaskFragmentAndReparentActivity(
WindowContainerTransaction wct, IBinder fragmentToken, IBinder ownerToken,
@NonNull Rect bounds, @WindowingMode int windowingMode, Activity activity) {
- final TaskFragmentCreationParams fragmentOptions =
- createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
- wct.createTaskFragment(fragmentOptions)
- .reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
+ createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
+ wct.reparentActivityToTaskFragment(fragmentToken, activity.getActivityToken());
}
/**
@@ -176,11 +185,8 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
WindowContainerTransaction wct, IBinder fragmentToken, IBinder ownerToken,
@NonNull Rect bounds, @WindowingMode int windowingMode, Intent activityIntent,
@Nullable Bundle activityOptions) {
- final TaskFragmentCreationParams fragmentOptions =
- createFragmentOptions(fragmentToken, ownerToken, bounds, windowingMode);
- wct.createTaskFragment(fragmentOptions)
- .startActivityInTaskFragment(fragmentToken, ownerToken, activityIntent,
- activityOptions);
+ createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
+ wct.startActivityInTaskFragment(fragmentToken, ownerToken, activityIntent, activityOptions);
}
TaskFragmentCreationParams createFragmentOptions(IBinder fragmentToken, IBinder ownerToken,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
index e43c5bf71c05..802976fbfc6d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java
@@ -20,9 +20,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityClient;
+import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application.ActivityLifecycleCallbacks;
+import android.app.Instrumentation;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -61,9 +64,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
public SplitController() {
mPresenter = new SplitPresenter(new MainThreadExecutor(), this);
+ ActivityThread activityThread = ActivityThread.currentActivityThread();
// Register a callback to be notified about activities being created.
- ActivityThread.currentActivityThread().getApplication().registerActivityLifecycleCallbacks(
+ activityThread.getApplication().registerActivityLifecycleCallbacks(
new LifecycleCallbacks());
+ // Intercept activity starts to route activities to new containers if necessary.
+ Instrumentation instrumentation = activityThread.getInstrumentation();
+ instrumentation.addMonitor(new ActivityStartMonitor());
}
public void setSplitRules(@NonNull List<ExtensionSplitRule> splitRules) {
@@ -118,8 +125,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
container.setInfo(taskFragmentInfo);
- if (taskFragmentInfo.isEmpty()) {
- cleanupContainer(container, true /* shouldFinishDependent */);
+ // Check if there are no running activities - consider the container empty if there are no
+ // non-finishing activities left.
+ if (!taskFragmentInfo.hasRunningActivity()) {
+ mPresenter.cleanupContainer(container, true /* shouldFinishDependent */);
updateCallbackIfNecessary();
}
}
@@ -131,7 +140,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return;
}
- cleanupContainer(container, true /* shouldFinishDependent */);
+ mPresenter.cleanupContainer(container, true /* shouldFinishDependent */);
updateCallbackIfNecessary();
}
@@ -261,7 +270,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken,
Activity activityToAdd) {
final IBinder taskFragmentToken = ActivityThread.currentActivityThread().getActivityClient(
- activityToken).mTaskFragmentToken;
+ activityToken).mInitialTaskFragmentToken;
for (TaskFragmentContainer container : mContainers) {
if (container.hasActivity(activityToken)) {
return container;
@@ -298,13 +307,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
mSplitContainers.add(splitContainer);
}
- void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
- if (container.isFinished()) {
- return;
- }
-
- container.finish(shouldFinishDependent);
-
+ /**
+ * Removes the container from bookkeeping records.
+ */
+ void removeContainer(@NonNull TaskFragmentContainer container) {
// Remove all split containers that included this one
mContainers.remove(container);
List<SplitContainer> containersToRemove = new ArrayList<>();
@@ -315,8 +321,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
}
mSplitContainers.removeAll(containersToRemove);
-
- mPresenter.deleteContainer(container);
}
/**
@@ -453,7 +457,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false;
}
- cleanupContainer(splitContainer.getSecondaryContainer(),
+ mPresenter.cleanupContainer(splitContainer.getSecondaryContainer(),
false /* shouldFinishDependent */);
return true;
}
@@ -664,4 +668,40 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
handler.post(r);
}
}
+
+ /**
+ * A monitor that intercepts all activity start requests originating in the client process and
+ * can amend them to target a specific task fragment to form a split.
+ */
+ private class ActivityStartMonitor extends Instrumentation.ActivityMonitor {
+
+ @Override
+ public Instrumentation.ActivityResult onStartActivity(Context who, Intent intent,
+ Bundle options) {
+ // TODO(b/190433398): Check if the activity is configured to always be expanded.
+
+ // Check if activity should be put in a split with the activity that launched it.
+ if (!(who instanceof Activity)) {
+ return super.onStartActivity(who, intent, options);
+ }
+ final Activity launchingActivity = (Activity) who;
+
+ final ExtensionSplitPairRule splitPairRule = getSplitRule(
+ launchingActivity.getComponentName(), intent.getComponent(), getSplitRules());
+ if (splitPairRule == null) {
+ return super.onStartActivity(who, intent, options);
+ }
+
+ // Create a new split with an empty side container
+ final TaskFragmentContainer secondaryContainer = mPresenter
+ .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule);
+
+ // Amend the request to let the WM know that the activity should be placed in the
+ // dedicated container.
+ options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN,
+ secondaryContainer.getTaskFragmentToken());
+
+ return super.onStartActivity(who, intent, options);
+ }
+ }
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java
index 7ad83aafe771..0f356291f50e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java
@@ -68,11 +68,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
/**
- * Deletes the provided container and updates the presentation if necessary.
+ * Deletes the specified container and all other associated and dependent containers in the same
+ * transaction.
*/
- void deleteContainer(TaskFragmentContainer container) {
+ void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
- deleteTaskFragment(wct, container.getTaskFragmentToken());
+
+ container.finish(shouldFinishDependent, this, wct, mController);
final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer();
if (newTopContainer != null) {
@@ -83,6 +85,37 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
/**
+ * Creates a new split with the primary activity and an empty secondary container.
+ * @return The newly created secondary container.
+ */
+ TaskFragmentContainer createNewSplitWithEmptySideContainer(@NonNull Activity primaryActivity,
+ @NonNull ExtensionSplitPairRule rule) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+
+ final Rect parentBounds = getParentContainerBounds(primaryActivity);
+ final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
+ final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
+ primaryActivity, primaryRectBounds, null);
+
+ // Create new empty task fragment
+ TaskFragmentContainer secondaryContainer = mController.newContainer(null);
+ final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
+ createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
+ primaryActivity.getActivityToken(), secondaryRectBounds,
+ WINDOWING_MODE_MULTI_WINDOW);
+ secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
+
+ // Set adjacent to each other so that the containers below will be invisible.
+ wct.setAdjacentTaskFragments(
+ primaryContainer.getTaskFragmentToken(), secondaryContainer.getTaskFragmentToken());
+ applyTransaction(wct);
+
+ mController.registerSplit(primaryContainer, primaryActivity, secondaryContainer, rule);
+
+ return secondaryContainer;
+ }
+
+ /**
* Creates a new split container with the two provided activities.
* @param primaryActivity An activity that should be in the primary container. If it is not
* currently in an existing container, a new one will be created and the
@@ -99,55 +132,51 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final Rect parentBounds = getParentContainerBounds(primaryActivity);
final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
- TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
- primaryActivity.getActivityToken());
- if (primaryContainer == null) {
- primaryContainer = mController.newContainer(primaryActivity);
+ final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
+ primaryActivity, primaryRectBounds, null);
- final TaskFragmentCreationParams fragmentOptions =
- createFragmentOptions(
- primaryContainer.getTaskFragmentToken(),
- primaryActivity.getActivityToken(),
- primaryRectBounds,
- WINDOWING_MODE_MULTI_WINDOW);
- wct.createTaskFragment(fragmentOptions);
+ final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
+ final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
+ secondaryActivity, secondaryRectBounds, primaryContainer);
- wct.reparentActivityToTaskFragment(primaryContainer.getTaskFragmentToken(),
- primaryActivity.getActivityToken());
+ // Set adjacent to each other so that the containers below will be invisible.
+ wct.setAdjacentTaskFragments(
+ primaryContainer.getTaskFragmentToken(), secondaryContainer.getTaskFragmentToken());
+ applyTransaction(wct);
- primaryContainer.setLastRequestedBounds(primaryRectBounds);
- } else {
- resizeTaskFragmentIfRegistered(wct, primaryContainer, primaryRectBounds);
- }
+ mController.registerSplit(primaryContainer, primaryActivity, secondaryContainer, rule);
+ }
- final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
- TaskFragmentContainer secondaryContainer = mController.getContainerWithActivity(
- secondaryActivity.getActivityToken());
- if (secondaryContainer == null || secondaryContainer == primaryContainer) {
- secondaryContainer = mController.newContainer(secondaryActivity);
+ /**
+ * Creates a new container or resizes an existing container for activity to the provided bounds.
+ * @param activity The activity to be re-parented to the container if necessary.
+ * @param containerToAvoid Re-parent from this container if an activity is already in it.
+ */
+ private TaskFragmentContainer prepareContainerForActivity(
+ @NonNull WindowContainerTransaction wct, @NonNull Activity activity,
+ @NonNull Rect bounds, @Nullable TaskFragmentContainer containerToAvoid) {
+ TaskFragmentContainer container = mController.getContainerWithActivity(
+ activity.getActivityToken());
+ if (container == null || container == containerToAvoid) {
+ container = mController.newContainer(activity);
final TaskFragmentCreationParams fragmentOptions =
createFragmentOptions(
- secondaryContainer.getTaskFragmentToken(),
- secondaryActivity.getActivityToken(),
- secondaryRectBounds,
+ container.getTaskFragmentToken(),
+ activity.getActivityToken(),
+ bounds,
WINDOWING_MODE_MULTI_WINDOW);
wct.createTaskFragment(fragmentOptions);
- wct.reparentActivityToTaskFragment(secondaryContainer.getTaskFragmentToken(),
- secondaryActivity.getActivityToken());
+ wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(),
+ activity.getActivityToken());
- secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
+ container.setLastRequestedBounds(bounds);
} else {
- resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds);
+ resizeTaskFragmentIfRegistered(wct, container, bounds);
}
- // Set adjacent to each other so that the containers below will be invisible.
- wct.setAdjacentTaskFragments(
- primaryContainer.getTaskFragmentToken(), secondaryContainer.getTaskFragmentToken());
- applyTransaction(wct);
-
- mController.registerSplit(primaryContainer, primaryActivity, secondaryContainer, rule);
+ return container;
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
index f47dc245d2b0..a4f5c75276f5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java
@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.window.TaskFragmentInfo;
+import android.window.WindowContainerTransaction;
import java.util.ArrayList;
import java.util.List;
@@ -179,7 +180,8 @@ class TaskFragmentContainer {
* Removes all activities that belong to this process and finishes other containers/activities
* configured to finish together.
*/
- void finish(boolean shouldFinishDependent) {
+ void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter,
+ @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) {
if (mIsFinished) {
return;
}
@@ -190,13 +192,19 @@ class TaskFragmentContainer {
activity.finish();
}
+ // Cleanup the visuals
+ presenter.deleteTaskFragment(wct, getTaskFragmentToken());
+ // Cleanup the records
+ controller.removeContainer(this);
+
if (!shouldFinishDependent) {
return;
}
// Finish dependent containers
for (TaskFragmentContainer container : mContainersToFinishOnExit) {
- container.finish(true /* shouldFinishDependent */);
+ container.finish(true /* shouldFinishDependent */, presenter,
+ wct, controller);
}
mContainersToFinishOnExit.clear();
diff --git a/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml b/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
index 7658fca58822..0cf6d73162d2 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
@@ -17,7 +17,7 @@
<com.android.wm.shell.common.AlphaOptimizedButton
xmlns:android="http://schemas.android.com/apk/res/android"
style="@android:style/Widget.DeviceDefault.Button.Borderless"
- android:id="@+id/settings_button"
+ android:id="@+id/manage_button"
android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="@dimen/bubble_manage_button_height"
diff --git a/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml b/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
index fd4c3ba87026..87deb8b5a1fd 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_stack_user_education.xml
@@ -21,7 +21,6 @@
android:layout_width="wrap_content"
android:paddingTop="48dp"
android:paddingBottom="48dp"
- android:paddingStart="@dimen/bubble_stack_user_education_side_inset"
android:paddingEnd="16dp"
android:layout_marginEnd="24dp"
android:orientation="vertical"
diff --git a/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml b/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
index c5c42fca323d..fafe40e924f5 100644
--- a/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
+++ b/libs/WindowManager/Shell/res/layout/bubbles_manage_button_education.xml
@@ -23,7 +23,6 @@
android:clickable="true"
android:paddingTop="28dp"
android:paddingBottom="16dp"
- android:paddingStart="@dimen/bubble_expanded_view_padding"
android:paddingEnd="48dp"
android:layout_marginEnd="24dp"
android:orientation="vertical"
@@ -66,27 +65,21 @@
android:id="@+id/button_layout"
android:orientation="horizontal" >
- <com.android.wm.shell.common.AlphaOptimizedButton
- style="@android:style/Widget.Material.Button.Borderless"
- android:id="@+id/manage"
- android:layout_gravity="start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:clickable="false"
- android:text="@string/manage_bubbles_text"
- android:textColor="@android:color/system_neutral1_900"
+ <include
+ layout="@layout/bubble_manage_button"
/>
<com.android.wm.shell.common.AlphaOptimizedButton
- style="@android:style/Widget.Material.Button.Borderless"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless"
android:id="@+id/got_it"
android:layout_gravity="start"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/bubble_manage_button_height"
android:focusable="true"
android:text="@string/bubbles_user_education_got_it"
+ android:textSize="@*android:dimen/text_size_body_2_material"
android:textColor="@android:color/system_neutral1_900"
+ android:background="@drawable/bubble_manage_btn_bg"
/>
</LinearLayout>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 624b8b37a1ee..c2b6ffbd1048 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -31,7 +31,7 @@
<string name="accessibility_action_pip_stash" msgid="4060775037619702641">"స్టాచ్"</string>
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ఆన్‌స్టాచ్"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"స్క్రీన్ విభజనతో యాప్‌ పని చేయకపోవచ్చు."</string>
- <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"యాప్‌లో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్‌ప్లేలో యాప్ పని చేయకపోవచ్చు."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్‌ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string>
<string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 7da31aa7d03a..130f741def86 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -124,7 +124,7 @@
should also be updated. -->
<dimen name="bubble_expanded_default_height">180dp</dimen>
<!-- On large screens the width of the expanded view is restricted to this size. -->
- <dimen name="bubble_expanded_view_tablet_width">412dp</dimen>
+ <dimen name="bubble_expanded_view_phone_landscape_overflow_width">412dp</dimen>
<!-- Inset to apply to the icon in the overflow button. -->
<dimen name="bubble_overflow_icon_inset">30dp</dimen>
<!-- Default (and minimum) height of bubble overflow -->
@@ -184,14 +184,8 @@
<dimen name="bubble_dismiss_target_padding_x">40dp</dimen>
<dimen name="bubble_dismiss_target_padding_y">20dp</dimen>
<dimen name="bubble_manage_menu_elevation">4dp</dimen>
-
- <!-- Bubbles user education views -->
- <dimen name="bubbles_manage_education_width">160dp</dimen>
- <!-- The inset from the top bound of the manage button to place the user education. -->
- <dimen name="bubbles_manage_education_top_inset">65dp</dimen>
- <!-- Size of padding for the user education cling, this should at minimum be larger than
- individual_bubble_size + some padding. -->
- <dimen name="bubble_stack_user_education_side_inset">72dp</dimen>
+ <!-- Size of user education views on large screens (phone is just match parent). -->
+ <dimen name="bubbles_user_education_width_large_screen">400dp</dimen>
<!-- The width/height of the size compat restart button. -->
<dimen name="size_compat_button_size">48dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index d1fbf31e2b99..df4f2383c062 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -20,10 +20,13 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCR
import com.android.wm.shell.apppairs.AppPairsController;
import com.android.wm.shell.bubbles.BubbleController;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.splitscreen.SplitScreenController;
@@ -38,7 +41,9 @@ import java.util.Optional;
public class ShellInitImpl {
private static final String TAG = ShellInitImpl.class.getSimpleName();
+ private final DisplayController mDisplayController;
private final DisplayImeController mDisplayImeController;
+ private final DisplayInsetsController mDisplayInsetsController;
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<BubbleController> mBubblesOptional;
@@ -47,13 +52,17 @@ public class ShellInitImpl {
private final Optional<AppPairsController> mAppPairsOptional;
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
+ private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
private final StartingWindowController mStartingWindow;
private final InitImpl mImpl = new InitImpl();
- public ShellInitImpl(DisplayImeController displayImeController,
+ public ShellInitImpl(
+ DisplayController displayController,
+ DisplayImeController displayImeController,
+ DisplayInsetsController displayInsetsController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<BubbleController> bubblesOptional,
@@ -62,10 +71,13 @@ public class ShellInitImpl {
Optional<AppPairsController> appPairsOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
+ Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional,
Transitions transitions,
StartingWindowController startingWindow,
ShellExecutor mainExecutor) {
+ mDisplayController = displayController;
mDisplayImeController = displayImeController;
+ mDisplayInsetsController = displayInsetsController;
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
mBubblesOptional = bubblesOptional;
@@ -74,6 +86,7 @@ public class ShellInitImpl {
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mPipTouchHandlerOptional = pipTouchHandlerOptional;
+ mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f);
mTransitions = transitions;
mMainExecutor = mainExecutor;
mStartingWindow = startingWindow;
@@ -84,7 +97,9 @@ public class ShellInitImpl {
}
private void init() {
- // Start listening for display changes
+ // Start listening for display and insets changes
+ mDisplayController.initialize();
+ mDisplayInsetsController.initialize();
mDisplayImeController.startMonitorDisplays();
// Setup the shell organizer
@@ -108,6 +123,11 @@ public class ShellInitImpl {
// controller instead of the feature interface, can just initialize the touch handler if
// needed
mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
+
+ // Initialize optional freeform
+ mFreeformTaskListenerOptional.ifPresent(f ->
+ mShellTaskOrganizer.addListenerForType(
+ f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
}
@ExternalThread
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index ba0ab6db1003..ab8a21c58e9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -71,12 +71,14 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
public static final int TASK_LISTENER_TYPE_PIP = -4;
+ public static final int TASK_LISTENER_TYPE_FREEFORM = -5;
@IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
TASK_LISTENER_TYPE_UNDEFINED,
TASK_LISTENER_TYPE_FULLSCREEN,
TASK_LISTENER_TYPE_MULTI_WINDOW,
TASK_LISTENER_TYPE_PIP,
+ TASK_LISTENER_TYPE_FREEFORM,
})
public @interface TaskListenerType {}
@@ -572,6 +574,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
case WINDOWING_MODE_PINNED:
return TASK_LISTENER_TYPE_PIP;
case WINDOWING_MODE_FREEFORM:
+ return TASK_LISTENER_TYPE_FREEFORM;
case WINDOWING_MODE_UNDEFINED:
default:
return TASK_LISTENER_TYPE_UNDEFINED;
@@ -586,6 +589,8 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
return "TASK_LISTENER_TYPE_MULTI_WINDOW";
case TASK_LISTENER_TYPE_PIP:
return "TASK_LISTENER_TYPE_PIP";
+ case TASK_LISTENER_TYPE_FREEFORM:
+ return "TASK_LISTENER_TYPE_FREEFORM";
case TASK_LISTENER_TYPE_UNDEFINED:
return "TASK_LISTENER_TYPE_UNDEFINED";
default:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
index 8aca01d2467b..2aead9392e59 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
@@ -62,4 +62,10 @@ public class Interpolators {
*/
public static final Interpolator PANEL_CLOSE_ACCELERATED =
new PathInterpolator(0.3f, 0, 0.5f, 1);
+
+ public static final PathInterpolator SLOWDOWN_INTERPOLATOR =
+ new PathInterpolator(0.5f, 1f, 0.5f, 1f);
+
+ public static final PathInterpolator DIM_INTERPOLATOR =
+ new PathInterpolator(.23f, .87f, .52f, -0.11f);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index e7764ea1a21e..95b80df7fcbd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -636,10 +636,16 @@ public class BubbleController {
}
}
- /** For the overflow to be focusable & receive key events the flags must be update. **/
- void updateWindowFlagsForOverflow(boolean showingOverflow) {
+ /**
+ * In some situations bubble's should be able to receive key events for back:
+ * - when the bubble overflow is showing
+ * - when the user education for the stack is showing.
+ *
+ * @param interceptBack whether back should be intercepted or not.
+ */
+ void updateWindowFlagsForBackpress(boolean interceptBack) {
if (mStackView != null && mAddedToWindowManager) {
- mWmLayoutParams.flags = showingOverflow
+ mWmLayoutParams.flags = interceptBack
? 0
: WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 252b588ec63f..4ac7dcf3d23a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -228,7 +228,7 @@ public class BubbleExpandedView extends LinearLayout {
@Override
public void onBackPressedOnTaskRoot(int taskId) {
if (mTaskId == taskId && mStackView.isExpanded()) {
- mController.collapseStack();
+ mStackView.onBackPressed();
}
}
};
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
index ede42285d9cd..5e9d97f23c57 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
@@ -142,7 +142,7 @@ public class BubbleOverflowContainerView extends LinearLayout {
super.onAttachedToWindow();
if (mController != null) {
// For the overflow to get key events (e.g. back press) we need to adjust the flags
- mController.updateWindowFlagsForOverflow(true);
+ mController.updateWindowFlagsForBackpress(true);
}
setOnKeyListener(mKeyListener);
}
@@ -151,7 +151,7 @@ public class BubbleOverflowContainerView extends LinearLayout {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mController != null) {
- mController.updateWindowFlagsForOverflow(false);
+ mController.updateWindowFlagsForBackpress(false);
}
setOnKeyListener(null);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index df804ec174d3..7d4fb21584c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -65,7 +65,8 @@ public class BubblePositioner {
public static final float FLYOUT_MAX_WIDTH_PERCENT_LARGE_SCREEN = 0.3f;
/** The max percent of screen width to use for the flyout on phone. */
public static final float FLYOUT_MAX_WIDTH_PERCENT = 0.6f;
-
+ /** The percent of screen width that should be used for the expanded view on a large screen. **/
+ public static final float EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT = 0.72f;
private Context mContext;
private WindowManager mWindowManager;
@@ -78,7 +79,8 @@ public class BubblePositioner {
private int mBubbleSize;
private int mSpacingBetweenBubbles;
- private int mExpandedViewLargeScreenWidth;
+ private float mExpandedViewLargeScreenWidth;
+ private int mOverflowWidth;
private int mExpandedViewPadding;
private int mPointerMargin;
private int mPointerWidth;
@@ -166,9 +168,11 @@ public class BubblePositioner {
mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size);
mSpacingBetweenBubbles = res.getDimensionPixelSize(R.dimen.bubble_spacing);
mDefaultMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
-
- mExpandedViewLargeScreenWidth = res.getDimensionPixelSize(
- R.dimen.bubble_expanded_view_tablet_width);
+ mExpandedViewLargeScreenWidth = bounds.width() * EXPANDED_VIEW_LARGE_SCREEN_WIDTH_PERCENT;
+ mOverflowWidth = mIsLargeScreen
+ ? (int) mExpandedViewLargeScreenWidth
+ : res.getDimensionPixelSize(
+ R.dimen.bubble_expanded_view_phone_landscape_overflow_width);
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
@@ -242,6 +246,13 @@ public class BubblePositioner {
}
/**
+ * @return a rect of the screen size.
+ */
+ public Rect getScreenRect() {
+ return mScreenRect;
+ }
+
+ /**
* @return the relevant insets (status bar, nav bar, cutouts). If taskbar is showing, its
* inset is not included here.
*/
@@ -292,16 +303,19 @@ public class BubblePositioner {
int leftPadding = mInsets.left + mExpandedViewPadding;
int rightPadding = mInsets.right + mExpandedViewPadding;
final boolean isLargeOrOverflow = mIsLargeScreen || isOverflow;
+ final float expandedViewWidth = isOverflow
+ ? mOverflowWidth
+ : mExpandedViewLargeScreenWidth;
if (showBubblesVertically()) {
if (!onLeft) {
rightPadding += mBubbleSize - mPointerHeight;
leftPadding += isLargeOrOverflow
- ? (mPositionRect.width() - rightPadding - mExpandedViewLargeScreenWidth)
+ ? (mPositionRect.width() - rightPadding - expandedViewWidth)
: 0;
} else {
leftPadding += mBubbleSize - mPointerHeight;
rightPadding += isLargeOrOverflow
- ? (mPositionRect.width() - leftPadding - mExpandedViewLargeScreenWidth)
+ ? (mPositionRect.width() - leftPadding - expandedViewWidth)
: 0;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 8f2df4ab3972..3d2505ef7699 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -110,9 +110,6 @@ public class BubbleStackView extends FrameLayout
private static final int FADE_IN_DURATION = 320;
- /** Percent to darken the bubbles when they're in the dismiss target. */
- private static final float DARKEN_PERCENT = 0.3f;
-
/** How long to wait, in milliseconds, before hiding the flyout. */
@VisibleForTesting
static final int FLYOUT_HIDE_AFTER = 5000;
@@ -559,7 +556,7 @@ public class BubbleStackView extends FrameLayout
if (mBubbleData.isExpanded()) {
if (mManageEduView != null) {
- mManageEduView.hide(false /* show */);
+ mManageEduView.hide();
}
// If we're expanded, tell the animation controller to prepare to drag this bubble,
@@ -797,8 +794,6 @@ public class BubbleStackView extends FrameLayout
mBubbleContainer.setClipChildren(false);
addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- updateUserEdu();
-
mExpandedViewContainer = new FrameLayout(context);
mExpandedViewContainer.setElevation(elevation);
mExpandedViewContainer.setClipChildren(false);
@@ -932,8 +927,10 @@ public class BubbleStackView extends FrameLayout
setOnClickListener(view -> {
if (mShowingManage) {
showManageMenu(false /* show */);
+ } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ mManageEduView.hide();
} else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
- mStackEduView.hide(false);
+ mStackEduView.hide(false /* isExpanding */);
} else if (mBubbleData.isExpanded()) {
mBubbleData.setExpanded(false);
}
@@ -1132,10 +1129,10 @@ public class BubbleStackView extends FrameLayout
return;
}
if (mManageEduView == null) {
- mManageEduView = new ManageEducationView(mContext);
+ mManageEduView = new ManageEducationView(mContext, mPositioner);
addView(mManageEduView);
}
- mManageEduView.show(mExpandedBubble.getExpandedView(), mTempRect);
+ mManageEduView.show(mExpandedBubble.getExpandedView());
}
/**
@@ -1163,21 +1160,27 @@ public class BubbleStackView extends FrameLayout
return false;
}
if (mStackEduView == null) {
- mStackEduView = new StackEducationView(mContext);
+ mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController);
addView(mStackEduView);
}
mBubbleContainer.bringToFront();
return mStackEduView.show(mPositioner.getDefaultStartPosition());
}
+ // Recreates & shows the education views. Call when a theme/config change happens.
private void updateUserEdu() {
- maybeShowStackEdu();
- if (mManageEduView != null) {
- mManageEduView.invalidate();
+ if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
+ removeView(mStackEduView);
+ mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController);
+ addView(mStackEduView);
+ mBubbleContainer.bringToFront(); // Stack appears on top of the stack education
+ mStackEduView.show(mPositioner.getDefaultStartPosition());
}
- maybeShowManageEdu();
- if (mStackEduView != null) {
- mStackEduView.invalidate();
+ if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ removeView(mManageEduView);
+ mManageEduView = new ManageEducationView(mContext, mPositioner);
+ addView(mManageEduView);
+ mManageEduView.show(mExpandedBubble.getExpandedView());
}
}
@@ -1274,6 +1277,7 @@ public class BubbleStackView extends FrameLayout
setUpManageMenu();
setUpFlyout();
setUpDismissView();
+ updateUserEdu();
mBubbleSize = mPositioner.getBubbleSize();
for (Bubble b : mBubbleData.getBubbles()) {
if (b.getIconView() == null) {
@@ -1730,6 +1734,21 @@ public class BubbleStackView extends FrameLayout
notifyExpansionChanged(mExpandedBubble, mIsExpanded);
}
+ /**
+ * Called when back press occurs while bubbles are expanded.
+ */
+ public void onBackPressed() {
+ if (mIsExpanded) {
+ if (mShowingManage) {
+ showManageMenu(false);
+ } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ mManageEduView.hide();
+ } else {
+ setExpanded(false);
+ }
+ }
+ }
+
void setBubbleVisibility(Bubble b, boolean visible) {
if (b.getIconView() != null) {
b.getIconView().setVisibility(visible ? VISIBLE : GONE);
@@ -1955,6 +1974,9 @@ public class BubbleStackView extends FrameLayout
private void animateCollapse() {
cancelDelayedExpandCollapseSwitchAnimations();
+ if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ mManageEduView.hide();
+ }
// Hide the menu if it's visible.
showManageMenu(false);
@@ -2032,7 +2054,7 @@ public class BubbleStackView extends FrameLayout
final BubbleViewProvider previouslySelected = mExpandedBubble;
beforeExpandedViewAnimation();
if (mManageEduView != null) {
- mManageEduView.hide(false /* fromExpansion */);
+ mManageEduView.hide();
}
if (DEBUG_BUBBLE_STACK_VIEW) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt
index 4cc67025fff4..eb4737ac6c63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/ManageEducationView.kt
@@ -18,12 +18,13 @@ package com.android.wm.shell.bubbles
import android.content.Context
import android.graphics.Color
import android.graphics.Rect
+import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
-import android.widget.TextView
-import com.android.internal.util.ContrastColorUtil
+import com.android.internal.R.color.system_neutral1_900
import com.android.wm.shell.R
import com.android.wm.shell.animation.Interpolators
@@ -31,21 +32,22 @@ import com.android.wm.shell.animation.Interpolators
* User education view to highlight the manage button that allows a user to configure the settings
* for the bubble. Shown only the first time a user expands a bubble.
*/
-class ManageEducationView constructor(context: Context) : LinearLayout(context) {
+class ManageEducationView constructor(context: Context, positioner: BubblePositioner)
+ : LinearLayout(context) {
- private val TAG = if (BubbleDebugConfig.TAG_WITH_CLASS_NAME) "BubbleManageEducationView"
+ private val TAG = if (BubbleDebugConfig.TAG_WITH_CLASS_NAME) "ManageEducationView"
else BubbleDebugConfig.TAG_BUBBLES
private val ANIMATE_DURATION: Long = 200
- private val ANIMATE_DURATION_SHORT: Long = 40
- private val manageView by lazy { findViewById<View>(R.id.manage_education_view) }
- private val manageButton by lazy { findViewById<Button>(R.id.manage) }
+ private val positioner: BubblePositioner = positioner
+ private val manageView by lazy { findViewById<ViewGroup>(R.id.manage_education_view) }
+ private val manageButton by lazy { findViewById<Button>(R.id.manage_button) }
private val gotItButton by lazy { findViewById<Button>(R.id.got_it) }
- private val titleTextView by lazy { findViewById<TextView>(R.id.user_education_title) }
- private val descTextView by lazy { findViewById<TextView>(R.id.user_education_description) }
private var isHiding = false
+ private var realManageButtonRect = Rect()
+ private var bubbleExpandedView: BubbleExpandedView? = null
init {
LayoutInflater.from(context).inflate(R.layout.bubbles_manage_button_education, this)
@@ -66,18 +68,17 @@ class ManageEducationView constructor(context: Context) : LinearLayout(context)
override fun onFinishInflate() {
super.onFinishInflate()
layoutDirection = resources.configuration.layoutDirection
- setTextColor()
}
- private fun setTextColor() {
- val typedArray = mContext.obtainStyledAttributes(intArrayOf(android.R.attr.colorAccent,
- android.R.attr.textColorPrimaryInverse))
- val bgColor = typedArray.getColor(0 /* index */, Color.BLACK)
- var textColor = typedArray.getColor(1 /* index */, Color.WHITE)
+ private fun setButtonColor() {
+ val typedArray = mContext.obtainStyledAttributes(intArrayOf(
+ com.android.internal.R.attr.colorAccentPrimary))
+ val buttonColor = typedArray.getColor(0 /* index */, Color.TRANSPARENT)
typedArray.recycle()
- textColor = ContrastColorUtil.ensureTextContrast(textColor, bgColor, true)
- titleTextView.setTextColor(textColor)
- descTextView.setTextColor(textColor)
+
+ manageButton.setTextColor(mContext.getColor(system_neutral1_900))
+ manageButton.setBackgroundDrawable(ColorDrawable(buttonColor))
+ gotItButton.setBackgroundDrawable(ColorDrawable(buttonColor))
}
private fun setDrawableDirection() {
@@ -91,30 +92,39 @@ class ManageEducationView constructor(context: Context) : LinearLayout(context)
* If necessary, toggles the user education view for the manage button. This is shown when the
* bubble stack is expanded for the first time.
*
- * @param show whether the user education view should show or not.
+ * @param expandedView the expandedView the user education is shown on top of.
*/
- fun show(expandedView: BubbleExpandedView, rect: Rect) {
+ fun show(expandedView: BubbleExpandedView) {
+ setButtonColor()
if (visibility == VISIBLE) return
+ bubbleExpandedView = expandedView
+ expandedView.taskView?.setObscuredTouchRect(Rect(positioner.screenRect))
+
+ layoutParams.width = if (positioner.isLargeScreen)
+ context.resources.getDimensionPixelSize(
+ R.dimen.bubbles_user_education_width_large_screen)
+ else ViewGroup.LayoutParams.MATCH_PARENT
+
alpha = 0f
visibility = View.VISIBLE
+ expandedView.getManageButtonBoundsOnScreen(realManageButtonRect)
+ manageView.setPadding(realManageButtonRect.left - expandedView.manageButtonMargin,
+ manageView.paddingTop, manageView.paddingRight, manageView.paddingBottom)
post {
- expandedView.getManageButtonBoundsOnScreen(rect)
-
manageButton
.setOnClickListener {
- expandedView.findViewById<View>(R.id.settings_button).performClick()
- hide(true /* isStackExpanding */)
+ hide()
+ expandedView.findViewById<View>(R.id.manage_button).performClick()
}
- gotItButton.setOnClickListener { hide(true /* isStackExpanding */) }
- setOnClickListener { hide(true /* isStackExpanding */) }
-
- with(manageView) {
- translationX = 0f
- val inset = resources.getDimensionPixelSize(
- R.dimen.bubbles_manage_education_top_inset)
- translationY = (rect.top - manageView.height + inset).toFloat()
- }
+ gotItButton.setOnClickListener { hide() }
+ setOnClickListener { hide() }
+
+ val offsetViewBounds = Rect()
+ manageButton.getDrawingRect(offsetViewBounds)
+ manageView.offsetDescendantRectToMyCoords(manageButton, offsetViewBounds)
+ translationX = 0f
+ translationY = (realManageButtonRect.top - offsetViewBounds.top).toFloat()
bringToFront()
animate()
.setDuration(ANIMATE_DURATION)
@@ -124,13 +134,14 @@ class ManageEducationView constructor(context: Context) : LinearLayout(context)
setShouldShow(false)
}
- fun hide(isStackExpanding: Boolean) {
+ fun hide() {
+ bubbleExpandedView?.taskView?.setObscuredTouchRect(null)
if (visibility != VISIBLE || isHiding) return
animate()
.withStartAction { isHiding = true }
.alpha(0f)
- .setDuration(if (isStackExpanding) ANIMATE_DURATION_SHORT else ANIMATE_DURATION)
+ .setDuration(ANIMATE_DURATION)
.withEndAction {
isHiding = false
visibility = GONE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
index 0a2cfc4089ed..f6a90b7a76cd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
@@ -18,8 +18,11 @@ package com.android.wm.shell.bubbles
import android.content.Context
import android.graphics.Color
import android.graphics.PointF
+import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
+import android.view.View.OnKeyListener
+import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import com.android.internal.util.ContrastColorUtil
@@ -30,7 +33,12 @@ import com.android.wm.shell.animation.Interpolators
* User education view to highlight the collapsed stack of bubbles.
* Shown only the first time a user taps the stack.
*/
-class StackEducationView constructor(context: Context) : LinearLayout(context) {
+class StackEducationView constructor(
+ context: Context,
+ positioner: BubblePositioner,
+ controller: BubbleController
+)
+ : LinearLayout(context) {
private val TAG = if (BubbleDebugConfig.TAG_WITH_CLASS_NAME) "BubbleStackEducationView"
else BubbleDebugConfig.TAG_BUBBLES
@@ -38,6 +46,9 @@ class StackEducationView constructor(context: Context) : LinearLayout(context) {
private val ANIMATE_DURATION: Long = 200
private val ANIMATE_DURATION_SHORT: Long = 40
+ private val positioner: BubblePositioner = positioner
+ private val controller: BubbleController = controller
+
private val view by lazy { findViewById<View>(R.id.stack_education_layout) }
private val titleTextView by lazy { findViewById<TextView>(R.id.stack_education_title) }
private val descTextView by lazy { findViewById<TextView>(R.id.stack_education_description) }
@@ -67,6 +78,28 @@ class StackEducationView constructor(context: Context) : LinearLayout(context) {
setTextColor()
}
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ setFocusableInTouchMode(true)
+ setOnKeyListener(object : OnKeyListener {
+ override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean {
+ // if the event is a key down event on the enter button
+ if (event.action == KeyEvent.ACTION_UP &&
+ keyCode == KeyEvent.KEYCODE_BACK && !isHiding) {
+ hide(false)
+ return true
+ }
+ return false
+ }
+ })
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ setOnKeyListener(null)
+ controller.updateWindowFlagsForBackpress(false /* interceptBack */)
+ }
+
private fun setTextColor() {
val ta = mContext.obtainStyledAttributes(intArrayOf(android.R.attr.colorAccent,
android.R.attr.textColorPrimaryInverse))
@@ -94,13 +127,25 @@ class StackEducationView constructor(context: Context) : LinearLayout(context) {
fun show(stackPosition: PointF): Boolean {
if (visibility == VISIBLE) return false
+ controller.updateWindowFlagsForBackpress(true /* interceptBack */)
+ layoutParams.width = if (positioner.isLargeScreen)
+ context.resources.getDimensionPixelSize(
+ R.dimen.bubbles_user_education_width_large_screen)
+ else ViewGroup.LayoutParams.MATCH_PARENT
+
setAlpha(0f)
setVisibility(View.VISIBLE)
post {
+ requestFocus()
with(view) {
- val bubbleSize = context.resources.getDimensionPixelSize(
- R.dimen.bubble_size)
- translationY = stackPosition.y + bubbleSize / 2 - getHeight() / 2
+ if (resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR) {
+ setPadding(positioner.bubbleSize + paddingRight, paddingTop, paddingRight,
+ paddingBottom)
+ } else {
+ setPadding(paddingLeft, paddingTop, positioner.bubbleSize + paddingLeft,
+ paddingBottom)
+ }
+ translationY = stackPosition.y + positioner.bubbleSize / 2 - getHeight() / 2
}
animate()
.setDuration(ANIMATE_DURATION)
@@ -114,15 +159,16 @@ class StackEducationView constructor(context: Context) : LinearLayout(context) {
/**
* If necessary, hides the stack education view.
*
- * @param fromExpansion if true this indicates the hide is happening due to the bubble being
+ * @param isExpanding if true this indicates the hide is happening due to the bubble being
* expanded, false if due to a touch outside of the bubble stack.
*/
- fun hide(fromExpansion: Boolean) {
+ fun hide(isExpanding: Boolean) {
if (visibility != VISIBLE || isHiding) return
+ controller.updateWindowFlagsForBackpress(false /* interceptBack */)
animate()
.alpha(0f)
- .setDuration(if (fromExpansion) ANIMATE_DURATION_SHORT else ANIMATE_DURATION)
+ .setDuration(if (isExpanding) ANIMATE_DURATION_SHORT else ANIMATE_DURATION)
.withEndAction { visibility = GONE }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index efe07fbf108d..007ddbf63141 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -64,9 +64,6 @@ public class ExpandedAnimationController
/** Stiffness for the expand/collapse path-following animation. */
private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 1000;
- /** What percentage of the screen to use when centering the bubbles in landscape. */
- private static final float CENTER_BUBBLES_LANDSCAPE_PERCENT = 0.66f;
-
/**
* Velocity required to dismiss an individual bubble without dragging it into the dismiss
* target.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
index 3a7b534f3c17..ffda1f92ec90 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.common;
import android.os.RemoteException;
+import android.util.Slog;
import android.view.IDisplayWindowRotationCallback;
import android.view.IDisplayWindowRotationController;
import android.view.IWindowManager;
@@ -27,6 +28,7 @@ import androidx.annotation.BinderThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* This module deals with display rotations coming from WM. When WM starts a rotation: after it has
@@ -35,14 +37,14 @@ import java.util.ArrayList;
* rotation.
*/
public class DisplayChangeController {
+ private static final String TAG = DisplayChangeController.class.getSimpleName();
private final ShellExecutor mMainExecutor;
private final IWindowManager mWmService;
private final IDisplayWindowRotationController mControllerImpl;
- private final ArrayList<OnDisplayChangingListener> mRotationListener =
- new ArrayList<>();
- private final ArrayList<OnDisplayChangingListener> mTmpListeners = new ArrayList<>();
+ private final CopyOnWriteArrayList<OnDisplayChangingListener> mRotationListener =
+ new CopyOnWriteArrayList<>();
public DisplayChangeController(IWindowManager wmService, ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
@@ -59,34 +61,26 @@ public class DisplayChangeController {
* Adds a display rotation controller.
*/
public void addRotationListener(OnDisplayChangingListener listener) {
- synchronized (mRotationListener) {
- mRotationListener.add(listener);
- }
+ mRotationListener.add(listener);
}
/**
* Removes a display rotation controller.
*/
public void removeRotationListener(OnDisplayChangingListener listener) {
- synchronized (mRotationListener) {
- mRotationListener.remove(listener);
- }
+ mRotationListener.remove(listener);
}
private void onRotateDisplay(int displayId, final int fromRotation, final int toRotation,
IDisplayWindowRotationCallback callback) {
WindowContainerTransaction t = new WindowContainerTransaction();
- synchronized (mRotationListener) {
- mTmpListeners.clear();
- // Make a local copy in case the handlers add/remove themselves.
- mTmpListeners.addAll(mRotationListener);
- }
- for (OnDisplayChangingListener c : mTmpListeners) {
+ for (OnDisplayChangingListener c : mRotationListener) {
c.onRotateDisplay(displayId, fromRotation, toRotation, t);
}
try {
callback.continueRotateDisplay(toRotation, t);
} catch (RemoteException e) {
+ Slog.e(TAG, "Failed to continue rotation", e);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index ba9ba5e5883a..9a3bdab9f418 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -26,6 +26,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.IDisplayWindowListener;
import android.view.IWindowManager;
+import android.view.InsetsState;
import androidx.annotation.BinderThread;
@@ -52,14 +53,6 @@ public class DisplayController {
private final SparseArray<DisplayRecord> mDisplays = new SparseArray<>();
private final ArrayList<OnDisplaysChangedListener> mDisplayChangedListeners = new ArrayList<>();
- /**
- * Gets a display by id from DisplayManager.
- */
- public Display getDisplay(int displayId) {
- final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- return displayManager.getDisplay(displayId);
- }
-
public DisplayController(Context context, IWindowManager wmService,
ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
@@ -67,14 +60,28 @@ public class DisplayController {
mWmService = wmService;
mChangeController = new DisplayChangeController(mWmService, mainExecutor);
mDisplayContainerListener = new DisplayWindowListenerImpl();
+ }
+
+ /**
+ * Initializes the window listener.
+ */
+ public void initialize() {
try {
mWmService.registerDisplayWindowListener(mDisplayContainerListener);
} catch (RemoteException e) {
- throw new RuntimeException("Unable to register hierarchy listener");
+ throw new RuntimeException("Unable to register display controller");
}
}
/**
+ * Gets a display by id from DisplayManager.
+ */
+ public Display getDisplay(int displayId) {
+ final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ return displayManager.getDisplay(displayId);
+ }
+
+ /**
* Gets the DisplayLayout associated with a display.
*/
public @Nullable DisplayLayout getDisplayLayout(int displayId) {
@@ -91,6 +98,16 @@ public class DisplayController {
}
/**
+ * Updates the insets for a given display.
+ */
+ public void updateDisplayInsets(int displayId, InsetsState state) {
+ final DisplayRecord r = mDisplays.get(displayId);
+ if (r != null) {
+ r.setInsets(state);
+ }
+ }
+
+ /**
* Add a display window-container listener. It will get notified whenever a display's
* configuration changes or when displays are added/removed from the WM hierarchy.
*/
@@ -134,17 +151,18 @@ public class DisplayController {
if (mDisplays.get(displayId) != null) {
return;
}
- Display display = getDisplay(displayId);
+ final Display display = getDisplay(displayId);
if (display == null) {
// It's likely that the display is private to some app and thus not
// accessible by system-ui.
return;
}
- DisplayRecord record = new DisplayRecord();
- record.mDisplayId = displayId;
- record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
+
+ final Context context = (displayId == Display.DEFAULT_DISPLAY)
+ ? mContext
: mContext.createDisplayContext(display);
- record.mDisplayLayout = new DisplayLayout(record.mContext, display);
+ final DisplayRecord record = new DisplayRecord(displayId);
+ record.setDisplayLayout(context, new DisplayLayout(context, display));
mDisplays.put(displayId, record);
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
@@ -154,24 +172,23 @@ public class DisplayController {
private void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
synchronized (mDisplays) {
- DisplayRecord dr = mDisplays.get(displayId);
+ final DisplayRecord dr = mDisplays.get(displayId);
if (dr == null) {
Slog.w(TAG, "Skipping Display Configuration change on non-added"
+ " display.");
return;
}
- Display display = getDisplay(displayId);
+ final Display display = getDisplay(displayId);
if (display == null) {
Slog.w(TAG, "Skipping Display Configuration change on invalid"
+ " display. It may have been removed.");
return;
}
- Context perDisplayContext = mContext;
- if (displayId != Display.DEFAULT_DISPLAY) {
- perDisplayContext = mContext.createDisplayContext(display);
- }
- dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
- dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
+ final Context perDisplayContext = (displayId == Display.DEFAULT_DISPLAY)
+ ? mContext
+ : mContext.createDisplayContext(display);
+ final Context context = perDisplayContext.createConfigurationContext(newConfig);
+ dr.setDisplayLayout(context, new DisplayLayout(context, display));
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
displayId, newConfig);
@@ -219,9 +236,25 @@ public class DisplayController {
}
private static class DisplayRecord {
- int mDisplayId;
- Context mContext;
- DisplayLayout mDisplayLayout;
+ private int mDisplayId;
+ private Context mContext;
+ private DisplayLayout mDisplayLayout;
+ private InsetsState mInsetsState = new InsetsState();
+
+ private DisplayRecord(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ private void setDisplayLayout(Context context, DisplayLayout displayLayout) {
+ mContext = context;
+ mDisplayLayout = displayLayout;
+ mDisplayLayout.setInsets(mContext.getResources(), mInsetsState);
+ }
+
+ private void setInsets(InsetsState state) {
+ mInsetsState = state;
+ mDisplayLayout.setInsets(mContext.getResources(), state);
+ }
}
@BinderThread
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index ba59e072a126..a7052bc49699 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -69,14 +69,17 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
protected final Executor mMainExecutor;
private final TransactionPool mTransactionPool;
private final DisplayController mDisplayController;
+ private final DisplayInsetsController mDisplayInsetsController;
private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
public DisplayImeController(IWindowManager wmService, DisplayController displayController,
+ DisplayInsetsController displayInsetsController,
Executor mainExecutor, TransactionPool transactionPool) {
mWmService = wmService;
mDisplayController = displayController;
+ mDisplayInsetsController = displayInsetsController;
mMainExecutor = mainExecutor;
mTransactionPool = transactionPool;
}
@@ -110,11 +113,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
@Override
public void onDisplayRemoved(int displayId) {
- try {
- mWmService.setDisplayWindowInsetsController(displayId, null);
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to remove insets controller on display " + displayId);
+ PerDisplay pd = mImePerDisplay.get(displayId);
+ if (pd == null) {
+ return;
}
+ pd.unregister();
mImePerDisplay.remove(displayId);
}
@@ -196,12 +199,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
/** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */
- public class PerDisplay {
+ public class PerDisplay implements DisplayInsetsController.OnInsetsChangedListener {
final int mDisplayId;
final InsetsState mInsetsState = new InsetsState();
final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
- protected final DisplayWindowInsetsControllerImpl mInsetsControllerImpl =
- new DisplayWindowInsetsControllerImpl();
InsetsSourceControl mImeSourceControl = null;
int mAnimationDirection = DIRECTION_NONE;
ValueAnimator mAnimation = null;
@@ -216,14 +217,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
public void register() {
- try {
- mWmService.setDisplayWindowInsetsController(mDisplayId, mInsetsControllerImpl);
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to set insets controller on display " + mDisplayId);
- }
+ mDisplayInsetsController.addInsetsChangedListener(mDisplayId, this);
}
- protected void insetsChanged(InsetsState insetsState) {
+ public void unregister() {
+ mDisplayInsetsController.removeInsetsChangedListener(mDisplayId, this);
+ }
+
+ @Override
+ public void insetsChanged(InsetsState insetsState) {
if (mInsetsState.equals(insetsState)) {
return;
}
@@ -241,8 +243,9 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
+ @Override
@VisibleForTesting
- protected void insetsControlChanged(InsetsState insetsState,
+ public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
insetsChanged(insetsState);
InsetsSourceControl imeSourceControl = null;
@@ -303,7 +306,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
- protected void showInsets(int types, boolean fromIme) {
+ @Override
+ public void showInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) {
return;
}
@@ -311,8 +315,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
startAnimation(true /* show */, false /* forceRestart */);
}
-
- protected void hideInsets(int types, boolean fromIme) {
+ @Override
+ public void hideInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) {
return;
}
@@ -320,6 +324,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
startAnimation(false /* show */, false /* forceRestart */);
}
+ @Override
public void topFocusedWindowChanged(String packageName) {
// Do nothing
}
@@ -493,47 +498,6 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
dispatchVisibilityChanged(mDisplayId, isShowing);
}
}
-
- @VisibleForTesting
- @BinderThread
- public class DisplayWindowInsetsControllerImpl
- extends IDisplayWindowInsetsController.Stub {
- @Override
- public void topFocusedWindowChanged(String packageName) throws RemoteException {
- mMainExecutor.execute(() -> {
- PerDisplay.this.topFocusedWindowChanged(packageName);
- });
- }
-
- @Override
- public void insetsChanged(InsetsState insetsState) throws RemoteException {
- mMainExecutor.execute(() -> {
- PerDisplay.this.insetsChanged(insetsState);
- });
- }
-
- @Override
- public void insetsControlChanged(InsetsState insetsState,
- InsetsSourceControl[] activeControls) throws RemoteException {
- mMainExecutor.execute(() -> {
- PerDisplay.this.insetsControlChanged(insetsState, activeControls);
- });
- }
-
- @Override
- public void showInsets(int types, boolean fromIme) throws RemoteException {
- mMainExecutor.execute(() -> {
- PerDisplay.this.showInsets(types, fromIme);
- });
- }
-
- @Override
- public void hideInsets(int types, boolean fromIme) throws RemoteException {
- mMainExecutor.execute(() -> {
- PerDisplay.this.hideInsets(types, fromIme);
- });
- }
- }
}
void removeImeSurface() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
new file mode 100644
index 000000000000..5f3de7ec35c0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.os.RemoteException;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.IDisplayWindowInsetsController;
+import android.view.IWindowManager;
+import android.view.InsetsSourceControl;
+import android.view.InsetsState;
+
+import androidx.annotation.BinderThread;
+
+import com.android.wm.shell.common.annotations.ShellMainThread;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Manages insets from the core.
+ */
+public class DisplayInsetsController implements DisplayController.OnDisplaysChangedListener {
+ private static final String TAG = "DisplayInsetsController";
+
+ private final IWindowManager mWmService;
+ private final ShellExecutor mMainExecutor;
+ private final DisplayController mDisplayController;
+ private final SparseArray<PerDisplay> mInsetsPerDisplay = new SparseArray<>();
+ private final SparseArray<CopyOnWriteArrayList<OnInsetsChangedListener>> mListeners =
+ new SparseArray<>();
+
+ public DisplayInsetsController(IWindowManager wmService, DisplayController displayController,
+ ShellExecutor mainExecutor) {
+ mWmService = wmService;
+ mDisplayController = displayController;
+ mMainExecutor = mainExecutor;
+ }
+
+ /**
+ * Starts listening for insets for each display.
+ **/
+ public void initialize() {
+ mDisplayController.addDisplayWindowListener(this);
+ }
+
+ /**
+ * Adds a callback to listen for insets changes for a particular display. Note that the
+ * listener will not be updated with the existing state of the insets on that display.
+ */
+ public void addInsetsChangedListener(int displayId, OnInsetsChangedListener listener) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(displayId);
+ if (listeners == null) {
+ listeners = new CopyOnWriteArrayList<>();
+ mListeners.put(displayId, listeners);
+ }
+ if (!listeners.contains(listener)) {
+ listeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a callback listening for insets changes from a particular display.
+ */
+ public void removeInsetsChangedListener(int displayId, OnInsetsChangedListener listener) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(displayId);
+ if (listeners == null) {
+ return;
+ }
+ listeners.remove(listener);
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ PerDisplay pd = new PerDisplay(displayId);
+ pd.register();
+ mInsetsPerDisplay.put(displayId, pd);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ PerDisplay pd = mInsetsPerDisplay.get(displayId);
+ if (pd == null) {
+ return;
+ }
+ pd.unregister();
+ mInsetsPerDisplay.remove(displayId);
+ }
+
+ /**
+ * An implementation of {@link IDisplayWindowInsetsController} for a given display id.
+ **/
+ public class PerDisplay {
+ private final int mDisplayId;
+ private final DisplayWindowInsetsControllerImpl mInsetsControllerImpl =
+ new DisplayWindowInsetsControllerImpl();
+
+ public PerDisplay(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ public void register() {
+ try {
+ mWmService.setDisplayWindowInsetsController(mDisplayId, mInsetsControllerImpl);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to set insets controller on display " + mDisplayId);
+ }
+ }
+
+ public void unregister() {
+ try {
+ mWmService.setDisplayWindowInsetsController(mDisplayId, null);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to remove insets controller on display " + mDisplayId);
+ }
+ }
+
+ private void insetsChanged(InsetsState insetsState) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
+ if (listeners == null) {
+ return;
+ }
+ mDisplayController.updateDisplayInsets(mDisplayId, insetsState);
+ for (OnInsetsChangedListener listener : listeners) {
+ listener.insetsChanged(insetsState);
+ }
+ }
+
+ private void insetsControlChanged(InsetsState insetsState,
+ InsetsSourceControl[] activeControls) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
+ if (listeners == null) {
+ return;
+ }
+ for (OnInsetsChangedListener listener : listeners) {
+ listener.insetsControlChanged(insetsState, activeControls);
+ }
+ }
+
+ private void showInsets(int types, boolean fromIme) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
+ if (listeners == null) {
+ return;
+ }
+ for (OnInsetsChangedListener listener : listeners) {
+ listener.showInsets(types, fromIme);
+ }
+ }
+
+ private void hideInsets(int types, boolean fromIme) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
+ if (listeners == null) {
+ return;
+ }
+ for (OnInsetsChangedListener listener : listeners) {
+ listener.hideInsets(types, fromIme);
+ }
+ }
+
+ private void topFocusedWindowChanged(String packageName) {
+ CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
+ if (listeners == null) {
+ return;
+ }
+ for (OnInsetsChangedListener listener : listeners) {
+ listener.topFocusedWindowChanged(packageName);
+ }
+ }
+
+ @BinderThread
+ private class DisplayWindowInsetsControllerImpl
+ extends IDisplayWindowInsetsController.Stub {
+ @Override
+ public void topFocusedWindowChanged(String packageName) throws RemoteException {
+ mMainExecutor.execute(() -> {
+ PerDisplay.this.topFocusedWindowChanged(packageName);
+ });
+ }
+
+ @Override
+ public void insetsChanged(InsetsState insetsState) throws RemoteException {
+ mMainExecutor.execute(() -> {
+ PerDisplay.this.insetsChanged(insetsState);
+ });
+ }
+
+ @Override
+ public void insetsControlChanged(InsetsState insetsState,
+ InsetsSourceControl[] activeControls) throws RemoteException {
+ mMainExecutor.execute(() -> {
+ PerDisplay.this.insetsControlChanged(insetsState, activeControls);
+ });
+ }
+
+ @Override
+ public void showInsets(int types, boolean fromIme) throws RemoteException {
+ mMainExecutor.execute(() -> {
+ PerDisplay.this.showInsets(types, fromIme);
+ });
+ }
+
+ @Override
+ public void hideInsets(int types, boolean fromIme) throws RemoteException {
+ mMainExecutor.execute(() -> {
+ PerDisplay.this.hideInsets(types, fromIme);
+ });
+ }
+ }
+ }
+
+ /**
+ * Gets notified whenever the insets change.
+ *
+ * @see IDisplayWindowInsetsController
+ */
+ @ShellMainThread
+ public interface OnInsetsChangedListener {
+ /**
+ * Called when top focused window changes to determine whether or not to take over insets
+ * control. Won't be called if config_remoteInsetsControllerControlsSystemBars is false.
+ * @param packageName: Passes the top package name
+ */
+ void topFocusedWindowChanged(String packageName);
+
+ /**
+ * Called when the window insets configuration has changed.
+ */
+ void insetsChanged(InsetsState insetsState);
+
+ /**
+ * Called when this window retrieved control over a specified set of insets sources.
+ */
+ void insetsControlChanged(InsetsState insetsState,
+ InsetsSourceControl[] activeControls);
+
+ /**
+ * Called when a set of insets source window should be shown by policy.
+ *
+ * @param types internal insets types (WindowInsets.Type.InsetsType) to show
+ * @param fromIme true if this request originated from IME (InputMethodService).
+ */
+ void showInsets(int types, boolean fromIme);
+
+ /**
+ * Called when a set of insets source window should be hidden by policy.
+ *
+ * @param types internal insets types (WindowInsets.Type.InsetsType) to hide
+ * @param fromIme true if this request originated from IME (InputMethodService).
+ */
+ void hideInsets(int types, boolean fromIme);
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index b7235a31af03..962aca122b4d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -25,6 +25,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON
import static android.util.RotationUtils.rotateBounds;
import static android.util.RotationUtils.rotateInsets;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
@@ -44,7 +45,10 @@ import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
+import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.Surface;
+import android.view.WindowInsets;
import com.android.internal.R;
@@ -82,6 +86,10 @@ public class DisplayLayout {
private boolean mHasNavigationBar = false;
private boolean mHasStatusBar = false;
private int mNavBarFrameHeight = 0;
+ private boolean mAllowSeamlessRotationDespiteNavBarMoving = false;
+ private boolean mNavigationBarCanMove = false;
+ private boolean mReverseDefaultRotation = false;
+ private InsetsState mInsetsState = new InsetsState();
@Override
public boolean equals(Object o) {
@@ -98,14 +106,20 @@ public class DisplayLayout {
&& Objects.equals(mStableInsets, other.mStableInsets)
&& mHasNavigationBar == other.mHasNavigationBar
&& mHasStatusBar == other.mHasStatusBar
- && mNavBarFrameHeight == other.mNavBarFrameHeight;
+ && mAllowSeamlessRotationDespiteNavBarMoving
+ == other.mAllowSeamlessRotationDespiteNavBarMoving
+ && mNavigationBarCanMove == other.mNavigationBarCanMove
+ && mReverseDefaultRotation == other.mReverseDefaultRotation
+ && mNavBarFrameHeight == other.mNavBarFrameHeight
+ && Objects.equals(mInsetsState, other.mInsetsState);
}
@Override
public int hashCode() {
return Objects.hash(mUiMode, mWidth, mHeight, mCutout, mRotation, mDensityDpi,
mNonDecorInsets, mStableInsets, mHasNavigationBar, mHasStatusBar,
- mNavBarFrameHeight);
+ mNavBarFrameHeight, mAllowSeamlessRotationDespiteNavBarMoving,
+ mNavigationBarCanMove, mReverseDefaultRotation, mInsetsState);
}
/**
@@ -150,9 +164,13 @@ public class DisplayLayout {
mDensityDpi = dl.mDensityDpi;
mHasNavigationBar = dl.mHasNavigationBar;
mHasStatusBar = dl.mHasStatusBar;
+ mAllowSeamlessRotationDespiteNavBarMoving = dl.mAllowSeamlessRotationDespiteNavBarMoving;
+ mNavigationBarCanMove = dl.mNavigationBarCanMove;
+ mReverseDefaultRotation = dl.mReverseDefaultRotation;
mNavBarFrameHeight = dl.mNavBarFrameHeight;
mNonDecorInsets.set(dl.mNonDecorInsets);
mStableInsets.set(dl.mStableInsets);
+ mInsetsState.set(dl.mInsetsState, true /* copySources */);
}
private void init(DisplayInfo info, Resources res, boolean hasNavigationBar,
@@ -165,12 +183,24 @@ public class DisplayLayout {
mDensityDpi = info.logicalDensityDpi;
mHasNavigationBar = hasNavigationBar;
mHasStatusBar = hasStatusBar;
+ mAllowSeamlessRotationDespiteNavBarMoving = res.getBoolean(
+ R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
+ mNavigationBarCanMove = res.getBoolean(R.bool.config_navBarCanMove);
+ mReverseDefaultRotation = res.getBoolean(R.bool.config_reverseDefaultRotation);
+ recalcInsets(res);
+ }
+
+ /**
+ * Updates the current insets.
+ */
+ public void setInsets(Resources res, InsetsState state) {
+ mInsetsState = state;
recalcInsets(res);
}
private void recalcInsets(Resources res) {
- computeNonDecorInsets(res, mRotation, mWidth, mHeight, mCutout, mUiMode, mNonDecorInsets,
- mHasNavigationBar);
+ computeNonDecorInsets(res, mRotation, mWidth, mHeight, mCutout, mInsetsState, mUiMode,
+ mNonDecorInsets, mHasNavigationBar);
mStableInsets.set(mNonDecorInsets);
if (mHasStatusBar) {
convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
@@ -244,11 +274,33 @@ public class DisplayLayout {
return mWidth > mHeight;
}
- /** Get the navbar frame height (used by ime). */
+ /** Get the navbar frame (or window) height (used by ime). */
public int navBarFrameHeight() {
return mNavBarFrameHeight;
}
+ /** @return whether we can seamlessly rotate even if nav-bar can change sides. */
+ public boolean allowSeamlessRotationDespiteNavBarMoving() {
+ return mAllowSeamlessRotationDespiteNavBarMoving;
+ }
+
+ /** @return whether the navigation bar will change sides during rotation. */
+ public boolean navigationBarCanMove() {
+ return mNavigationBarCanMove;
+ }
+
+ /** @return the rotation that would make the physical display "upside down". */
+ public int getUpsideDownRotation() {
+ boolean displayHardwareIsLandscape = mWidth > mHeight;
+ if ((mRotation % 2) != 0) {
+ displayHardwareIsLandscape = !displayHardwareIsLandscape;
+ }
+ if (displayHardwareIsLandscape) {
+ return mReverseDefaultRotation ? Surface.ROTATION_270 : Surface.ROTATION_90;
+ }
+ return Surface.ROTATION_180;
+ }
+
/** Gets the orientation of this layout */
public int getOrientation() {
return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
@@ -291,21 +343,29 @@ public class DisplayLayout {
* @param outInsets the insets to return
*/
static void computeNonDecorInsets(Resources res, int displayRotation, int displayWidth,
- int displayHeight, DisplayCutout displayCutout, int uiMode, Rect outInsets,
- boolean hasNavigationBar) {
+ int displayHeight, DisplayCutout displayCutout, InsetsState insetsState, int uiMode,
+ Rect outInsets, boolean hasNavigationBar) {
outInsets.setEmpty();
// Only navigation bar
if (hasNavigationBar) {
+ final InsetsSource extraNavBar = insetsState.getSource(ITYPE_EXTRA_NAVIGATION_BAR);
+ final boolean hasExtraNav = extraNavBar != null && extraNavBar.isVisible();
int position = navigationBarPosition(res, displayWidth, displayHeight, displayRotation);
int navBarSize =
getNavigationBarSize(res, position, displayWidth > displayHeight, uiMode);
if (position == NAV_BAR_BOTTOM) {
- outInsets.bottom = navBarSize;
+ outInsets.bottom = hasExtraNav
+ ? Math.max(navBarSize, extraNavBar.getFrame().height())
+ : navBarSize;
} else if (position == NAV_BAR_RIGHT) {
- outInsets.right = navBarSize;
+ outInsets.right = hasExtraNav
+ ? Math.max(navBarSize, extraNavBar.getFrame().width())
+ : navBarSize;
} else if (position == NAV_BAR_LEFT) {
- outInsets.left = navBarSize;
+ outInsets.left = hasExtraNav
+ ? Math.max(navBarSize, extraNavBar.getFrame().width())
+ : navBarSize;
}
}
@@ -327,13 +387,13 @@ public class DisplayLayout {
* @param outInsets the insets to return
*/
static void computeStableInsets(Resources res, int displayRotation, int displayWidth,
- int displayHeight, DisplayCutout displayCutout, int uiMode, Rect outInsets,
- boolean hasNavigationBar, boolean hasStatusBar) {
+ int displayHeight, DisplayCutout displayCutout, InsetsState insetsState, int uiMode,
+ Rect outInsets, boolean hasNavigationBar, boolean hasStatusBar) {
outInsets.setEmpty();
// Navigation bar and status bar.
computeNonDecorInsets(res, displayRotation, displayWidth, displayHeight, displayCutout,
- uiMode, outInsets, hasNavigationBar);
+ insetsState, uiMode, outInsets, hasNavigationBar);
convertNonDecorInsetsToStableInsets(res, outInsets, displayWidth, displayHeight,
hasStatusBar);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b9ccd69fe707..bb40f679b272 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -18,11 +18,16 @@ package com.android.wm.shell.common.split;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END;
import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START;
+import static com.android.wm.shell.animation.Interpolators.DIM_INTERPOLATOR;
+import static com.android.wm.shell.animation.Interpolators.SLOWDOWN_INTERPOLATOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -32,6 +37,7 @@ import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.view.WindowInsets;
@@ -41,6 +47,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.Nullable;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
@@ -80,6 +87,7 @@ public final class SplitLayout {
private final int mDividerInsets;
private final int mDividerSize;
+ private final Rect mTempRect = new Rect();
private final Rect mRootBounds = new Rect();
private final Rect mDividerBounds = new Rect();
private final Rect mBounds1 = new Rect();
@@ -88,6 +96,7 @@ public final class SplitLayout {
private final SplitWindowManager mSplitWindowManager;
private final DisplayImeController mDisplayImeController;
private final ImePositionProcessor mImePositionProcessor;
+ private final DismissingParallaxPolicy mDismissingParallaxPolicy;
private final ShellTaskOrganizer mTaskOrganizer;
private Context mContext;
@@ -110,6 +119,7 @@ public final class SplitLayout {
windowName, mContext, configuration, parentContainerCallbacks);
mTaskOrganizer = taskOrganizer;
mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
+ mDismissingParallaxPolicy = new DismissingParallaxPolicy();
final Resources resources = context.getResources();
mDividerWindowWidth = resources.getDimensionPixelSize(
@@ -187,7 +197,8 @@ public final class SplitLayout {
mDividerBounds.set(mRootBounds);
mBounds1.set(mRootBounds);
mBounds2.set(mRootBounds);
- if (isLandscape(mRootBounds)) {
+ final boolean isLandscape = isLandscape(mRootBounds);
+ if (isLandscape) {
position += mRootBounds.left;
mDividerBounds.left = position - mDividerInsets;
mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth;
@@ -200,6 +211,7 @@ public final class SplitLayout {
mBounds1.bottom = position;
mBounds2.top = mBounds1.bottom + mDividerSize;
}
+ mDismissingParallaxPolicy.applyDividerPosition(position, isLandscape);
}
/** Inflates {@link DividerView} on the root surface. */
@@ -239,6 +251,7 @@ public final class SplitLayout {
/** Resets divider position. */
public void resetDividerPosition() {
mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
+ mSplitWindowManager.setResizingSplits(false);
updateBounds(mDividePosition);
}
@@ -249,15 +262,15 @@ public final class SplitLayout {
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
switch (snapTarget.flag) {
case FLAG_DISMISS_START:
- mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */);
- mSplitWindowManager.setResizingSplits(false);
+ flingDividePosition(currentPosition, snapTarget.position,
+ () -> mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */));
break;
case FLAG_DISMISS_END:
- mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */);
- mSplitWindowManager.setResizingSplits(false);
+ flingDividePosition(currentPosition, snapTarget.position,
+ () -> mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */));
break;
default:
- flingDividePosition(currentPosition, snapTarget.position);
+ flingDividePosition(currentPosition, snapTarget.position, null);
break;
}
}
@@ -287,7 +300,8 @@ public final class SplitLayout {
isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
}
- private void flingDividePosition(int from, int to) {
+ @VisibleForTesting
+ void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) {
if (from == to) {
// No animation run, it should stop resizing here.
mSplitWindowManager.setResizingSplits(false);
@@ -303,6 +317,9 @@ public final class SplitLayout {
@Override
public void onAnimationEnd(Animator animation) {
setDividePosition(to);
+ if (flingFinishedCallback != null) {
+ flingFinishedCallback.run();
+ }
}
@Override
@@ -328,30 +345,34 @@ public final class SplitLayout {
/** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
- final Rect dividerBounds = mImePositionProcessor.adjustForIme(mDividerBounds);
- final Rect bounds1 = mImePositionProcessor.adjustForIme(mBounds1);
- final Rect bounds2 = mImePositionProcessor.adjustForIme(mBounds2);
final SurfaceControl dividerLeash = getDividerLeash();
if (dividerLeash != null) {
- t.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
- // Resets layer of divider bar to make sure it is always on top.
- .setLayer(dividerLeash, Integer.MAX_VALUE);
+ t.setPosition(dividerLeash, mDividerBounds.left, mDividerBounds.top);
+ // Resets layer of divider bar to make sure it is always on top.
+ t.setLayer(dividerLeash, Integer.MAX_VALUE);
}
+ t.setPosition(leash1, mBounds1.left, mBounds1.top)
+ .setWindowCrop(leash1, mBounds1.width(), mBounds1.height());
+ t.setPosition(leash2, mBounds2.left, mBounds2.top)
+ .setWindowCrop(leash2, mBounds2.width(), mBounds2.height());
- t.setPosition(leash1, bounds1.left, bounds1.top)
- .setWindowCrop(leash1, bounds1.width(), bounds1.height());
-
- t.setPosition(leash2, bounds2.left, bounds2.top)
- .setWindowCrop(leash2, bounds2.width(), bounds2.height());
+ if (mImePositionProcessor.adjustSurfaceLayoutForIme(
+ t, dividerLeash, leash1, leash2, dimLayer1, dimLayer2)) {
+ return;
+ }
- mImePositionProcessor.applySurfaceDimValues(t, dimLayer1, dimLayer2);
+ mDismissingParallaxPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
}
/** Apply recorded task layout to the {@link WindowContainerTransaction}. */
public void applyTaskChanges(WindowContainerTransaction wct,
ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
- wct.setBounds(task1.token, mImePositionProcessor.adjustForIme(mBounds1))
- .setBounds(task2.token, mImePositionProcessor.adjustForIme(mBounds2));
+ if (mImePositionProcessor.applyTaskLayoutForIme(wct, task1.token, task2.token)) {
+ return;
+ }
+
+ wct.setBounds(task1.token, mBounds1)
+ .setBounds(task2.token, mBounds2);
}
/**
@@ -371,23 +392,22 @@ public final class SplitLayout {
wct.setScreenSizeDp(taskInfo2.token,
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
} else {
- final Rect bounds = new Rect();
- bounds.set(taskInfo1.configuration.windowConfiguration.getBounds());
- bounds.offset(offsetX, offsetY);
- wct.setBounds(taskInfo1.token, bounds);
- bounds.set(taskInfo1.configuration.windowConfiguration.getAppBounds());
- bounds.offset(offsetX, offsetY);
- wct.setAppBounds(taskInfo1.token, bounds);
+ mTempRect.set(taskInfo1.configuration.windowConfiguration.getBounds());
+ mTempRect.offset(offsetX, offsetY);
+ wct.setBounds(taskInfo1.token, mTempRect);
+ mTempRect.set(taskInfo1.configuration.windowConfiguration.getAppBounds());
+ mTempRect.offset(offsetX, offsetY);
+ wct.setAppBounds(taskInfo1.token, mTempRect);
wct.setScreenSizeDp(taskInfo1.token,
taskInfo1.configuration.screenWidthDp,
taskInfo1.configuration.screenHeightDp);
- bounds.set(taskInfo2.configuration.windowConfiguration.getBounds());
- bounds.offset(offsetX, offsetY);
- wct.setBounds(taskInfo2.token, bounds);
- bounds.set(taskInfo2.configuration.windowConfiguration.getAppBounds());
- bounds.offset(offsetX, offsetY);
- wct.setAppBounds(taskInfo2.token, bounds);
+ mTempRect.set(taskInfo2.configuration.windowConfiguration.getBounds());
+ mTempRect.offset(offsetX, offsetY);
+ wct.setBounds(taskInfo2.token, mTempRect);
+ mTempRect.set(taskInfo2.configuration.windowConfiguration.getAppBounds());
+ mTempRect.offset(offsetX, offsetY);
+ wct.setAppBounds(taskInfo2.token, mTempRect);
wct.setScreenSizeDp(taskInfo2.token,
taskInfo2.configuration.screenWidthDp,
taskInfo2.configuration.screenHeightDp);
@@ -423,6 +443,106 @@ public final class SplitLayout {
int getSplitItemPosition(WindowContainerToken token);
}
+ /**
+ * Calculates and applies proper dismissing parallax offset and dimming value to hint users
+ * dismissing gesture.
+ */
+ private class DismissingParallaxPolicy {
+ // The current dismissing side.
+ int mDismissingSide = DOCKED_INVALID;
+
+ // The parallax offset to hint the dismissing side and progress.
+ final Point mDismissingParallaxOffset = new Point();
+
+ // The dimming value to hint the dismissing side and progress.
+ float mDismissingDimValue = 0.0f;
+
+ /**
+ * Applies a parallax to the task to hint dismissing progress.
+ *
+ * @param position the split position to apply dismissing parallax effect
+ * @param isLandscape indicates whether it's splitting horizontally or vertically
+ */
+ void applyDividerPosition(int position, boolean isLandscape) {
+ mDismissingSide = DOCKED_INVALID;
+ mDismissingParallaxOffset.set(0, 0);
+ mDismissingDimValue = 0;
+
+ int totalDismissingDistance = 0;
+ if (position <= mDividerSnapAlgorithm.getFirstSplitTarget().position) {
+ mDismissingSide = isLandscape ? DOCKED_LEFT : DOCKED_TOP;
+ totalDismissingDistance = mDividerSnapAlgorithm.getDismissStartTarget().position
+ - mDividerSnapAlgorithm.getFirstSplitTarget().position;
+ } else if (position >= mDividerSnapAlgorithm.getLastSplitTarget().position) {
+ mDismissingSide = isLandscape ? DOCKED_RIGHT : DOCKED_BOTTOM;
+ totalDismissingDistance = mDividerSnapAlgorithm.getLastSplitTarget().position
+ - mDividerSnapAlgorithm.getDismissEndTarget().position;
+ }
+
+ if (mDismissingSide != DOCKED_INVALID) {
+ float fraction = Math.max(0,
+ Math.min(mDividerSnapAlgorithm.calculateDismissingFraction(position), 1f));
+ mDismissingDimValue = DIM_INTERPOLATOR.getInterpolation(fraction);
+ fraction = calculateParallaxDismissingFraction(fraction, mDismissingSide);
+ if (isLandscape) {
+ mDismissingParallaxOffset.x = (int) (fraction * totalDismissingDistance);
+ } else {
+ mDismissingParallaxOffset.y = (int) (fraction * totalDismissingDistance);
+ }
+ }
+ }
+
+ /**
+ * @return for a specified {@code fraction}, this returns an adjusted value that simulates a
+ * slowing down parallax effect
+ */
+ private float calculateParallaxDismissingFraction(float fraction, int dockSide) {
+ float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+
+ // Less parallax at the top, just because.
+ if (dockSide == WindowManager.DOCKED_TOP) {
+ result /= 2f;
+ }
+ return result;
+ }
+
+ /** Applies parallax offset and dimming value to the root surface at the dismissing side. */
+ boolean adjustDismissingSurface(SurfaceControl.Transaction t,
+ SurfaceControl leash1, SurfaceControl leash2,
+ SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
+ SurfaceControl targetLeash, targetDimLayer;
+ switch (mDismissingSide) {
+ case DOCKED_TOP:
+ case DOCKED_LEFT:
+ targetLeash = leash1;
+ targetDimLayer = dimLayer1;
+ mTempRect.set(mBounds1);
+ break;
+ case DOCKED_BOTTOM:
+ case DOCKED_RIGHT:
+ targetLeash = leash2;
+ targetDimLayer = dimLayer2;
+ mTempRect.set(mBounds2);
+ break;
+ case DOCKED_INVALID:
+ default:
+ t.setAlpha(dimLayer1, 0).hide(dimLayer1);
+ t.setAlpha(dimLayer2, 0).hide(dimLayer2);
+ return false;
+ }
+
+ t.setPosition(targetLeash,
+ mTempRect.left + mDismissingParallaxOffset.x,
+ mTempRect.top + mDismissingParallaxOffset.y);
+ // Transform the screen-based split bounds to surface-based crop bounds.
+ mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
+ t.setWindowCrop(targetLeash, mTempRect);
+ t.setAlpha(targetDimLayer, mDismissingDimValue)
+ .setVisibility(targetDimLayer, mDismissingDimValue > 0.001f);
+ return true;
+ }
+ }
+
/** Records IME top offset changes and updates SplitLayout correspondingly. */
private class ImePositionProcessor implements DisplayImeController.ImePositionProcessor {
/**
@@ -553,24 +673,61 @@ public final class SplitLayout {
return start + (end - start) * progress;
}
- private void reset() {
+ void reset() {
mImeShown = false;
mYOffsetForIme = mLastYOffset = mTargetYOffset = 0;
mDimValue1 = mLastDim1 = mTargetDim1 = 0.0f;
mDimValue2 = mLastDim2 = mTargetDim2 = 0.0f;
}
- /* Adjust bounds with IME offset. */
- private Rect adjustForIme(Rect bounds) {
- final Rect temp = new Rect(bounds);
- if (mYOffsetForIme != 0) temp.offset(0, mYOffsetForIme);
- return temp;
+ /**
+ * Applies adjusted task layout for showing IME.
+ *
+ * @return {@code false} if there's no need to adjust, otherwise {@code true}
+ */
+ boolean applyTaskLayoutForIme(WindowContainerTransaction wct,
+ WindowContainerToken token1, WindowContainerToken token2) {
+ if (mYOffsetForIme == 0) return false;
+
+ mTempRect.set(mBounds1);
+ mTempRect.offset(0, mYOffsetForIme);
+ wct.setBounds(token1, mTempRect);
+
+ mTempRect.set(mBounds2);
+ mTempRect.offset(0, mYOffsetForIme);
+ wct.setBounds(token2, mTempRect);
+
+ return true;
}
- private void applySurfaceDimValues(SurfaceControl.Transaction t, SurfaceControl dimLayer1,
- SurfaceControl dimLayer2) {
+ /**
+ * Adjusts surface layout while showing IME.
+ *
+ * @return {@code false} if there's no need to adjust, otherwise {@code true}
+ */
+ boolean adjustSurfaceLayoutForIme(SurfaceControl.Transaction t,
+ SurfaceControl dividerLeash, SurfaceControl leash1, SurfaceControl leash2,
+ SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
+ if (mYOffsetForIme == 0) return false;
+
+ if (dividerLeash != null) {
+ mTempRect.set(mDividerBounds);
+ mTempRect.offset(0, mYOffsetForIme);
+ t.setPosition(dividerLeash, mTempRect.left, mTempRect.top);
+ }
+
+ mTempRect.set(mBounds1);
+ mTempRect.offset(0, mYOffsetForIme);
+ t.setPosition(leash1, mTempRect.left, mTempRect.top);
+
+ mTempRect.set(mBounds2);
+ mTempRect.offset(0, mYOffsetForIme);
+ t.setPosition(leash2, mTempRect.left, mTempRect.top);
+
t.setAlpha(dimLayer1, mDimValue1).setVisibility(dimLayer1, mDimValue1 > 0.001f);
t.setAlpha(dimLayer2, mDimValue2).setVisibility(dimLayer2, mDimValue2 > 0.001f);
+
+ return true;
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
new file mode 100644
index 000000000000..5fb3297aa6d3
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.freeform;
+
+import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+import java.io.PrintWriter;
+
+/**
+ * {@link ShellTaskOrganizer.TaskListener} for {@link
+ * ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
+ */
+public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = "FreeformTaskListener";
+
+ private final SyncTransactionQueue mSyncQueue;
+
+ private final SparseArray<State> mTasks = new SparseArray<>();
+
+ private static class State {
+ RunningTaskInfo mTaskInfo;
+ SurfaceControl mLeash;
+ }
+
+ public FreeformTaskListener(SyncTransactionQueue syncQueue) {
+ mSyncQueue = syncQueue;
+ }
+
+ @Override
+ public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+ if (mTasks.get(taskInfo.taskId) != null) {
+ throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
+ taskInfo.taskId);
+ final State state = new State();
+ state.mTaskInfo = taskInfo;
+ state.mLeash = leash;
+ mTasks.put(taskInfo.taskId, state);
+
+ final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+ mSyncQueue.runInSync(t -> {
+ Point taskPosition = taskInfo.positionInParent;
+ t.setPosition(leash, taskPosition.x, taskPosition.y)
+ .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+ .show(leash);
+ });
+ }
+
+ @Override
+ public void onTaskVanished(RunningTaskInfo taskInfo) {
+ State state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
+ taskInfo.taskId);
+ mTasks.remove(taskInfo.taskId);
+ }
+
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+ State state = mTasks.get(taskInfo.taskId);
+ if (state == null) {
+ throw new RuntimeException(
+ "Task info changed before appearing: #" + taskInfo.taskId);
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
+ taskInfo.taskId);
+ state.mTaskInfo = taskInfo;
+
+ final Rect taskBounds = taskInfo.configuration.windowConfiguration.getBounds();
+ final SurfaceControl leash = state.mLeash;
+ mSyncQueue.runInSync(t -> {
+ Point taskPosition = taskInfo.positionInParent;
+ t.setPosition(leash, taskPosition.x, taskPosition.y)
+ .setWindowCrop(leash, taskBounds.width(), taskBounds.height())
+ .show(leash);
+ });
+ }
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + this);
+ pw.println(innerPrefix + mTasks.size() + " tasks");
+ }
+
+ @Override
+ public String toString() {
+ return TAG;
+ }
+
+ /**
+ * Checks if freeform support is enabled in system.
+ *
+ * @param context context used to check settings and package manager.
+ * @return {@code true} if freeform is enabled, {@code false} if not.
+ */
+ public static boolean isFreeformEnabled(Context context) {
+ return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
+ || Settings.Global.getInt(context.getContentResolver(),
+ DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
+ }
+
+ /**
+ * Creates {@link FreeformTaskListener} if freeform is enabled.
+ */
+ public static FreeformTaskListener create(Context context,
+ SyncTransactionQueue syncQueue) {
+ if (!isFreeformEnabled(context)) {
+ return null;
+ }
+
+ return new FreeformTaskListener(syncQueue);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index 9bed40d67335..067f80800ed5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -20,6 +20,8 @@ import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
import static android.view.WindowManager.DOCKED_RIGHT;
+import static com.android.wm.shell.animation.Interpolators.DIM_INTERPOLATOR;
+import static com.android.wm.shell.animation.Interpolators.SLOWDOWN_INTERPOLATOR;
import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION;
import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION;
@@ -100,10 +102,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private static final float MINIMIZE_DOCK_SCALE = 0f;
private static final float ADJUSTED_FOR_IME_SCALE = 0.5f;
- private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
- new PathInterpolator(0.5f, 1f, 0.5f, 1f);
- private static final PathInterpolator DIM_INTERPOLATOR =
- new PathInterpolator(.23f, .87f, .52f, -0.11f);
private static final Interpolator IME_ADJUST_INTERPOLATOR =
new PathInterpolator(0.2f, 0f, 0.1f, 1f);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
index 97461e607e66..d0491e95ec01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.view.ContextThemeWrapper;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.animation.LinearInterpolator;
@@ -31,7 +32,6 @@ import android.window.DisplayAreaOrganizer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.view.ContextThemeWrapper;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 21bc889a7d83..ff333c8c659d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -130,7 +130,7 @@ public final class OneHandedSettingsUtil {
*/
public boolean getSettingsTapsAppToExit(ContentResolver resolver, int userId) {
return Settings.Secure.getIntForUser(resolver,
- Settings.Secure.TAPS_APP_TO_EXIT, 0, userId) == 1;
+ Settings.Secure.TAPS_APP_TO_EXIT, 1, userId) == 1;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index ae17a93ef1dc..ea587c69c0c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.pip;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.util.RotationUtils.deltaRotation;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_PIP;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -126,6 +127,12 @@ public class PipTransition extends PipTransitionController {
return true;
}
+ // We only support TRANSIT_PIP type (from RootWindowContainer) or TRANSIT_OPEN (from apps
+ // that enter PiP instantly on opening, mostly from CTS/Flicker tests)
+ if (info.getType() != TRANSIT_PIP && info.getType() != TRANSIT_OPEN) {
+ return false;
+ }
+
// Search for an Enter PiP transition (along with a show wallpaper one)
TransitionInfo.Change enterPip = null;
TransitionInfo.Change wallpaper = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 29326ec90e31..22865988e880 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -360,7 +360,7 @@ public class SplashscreenContentDrawer {
createIconDrawable(iconDrawable, false);
} else {
final float iconScale = (float) mIconSize / (float) mDefaultIconSize;
- final int densityDpi = mContext.getResources().getDisplayMetrics().densityDpi;
+ final int densityDpi = mContext.getResources().getConfiguration().densityDpi;
final int scaledIconDpi =
(int) (0.5f + iconScale * densityDpi * NO_BACKGROUND_SCALE);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "getIcon");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index fc7c86d669cb..52a3ac585aff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -52,6 +52,7 @@ import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
@@ -115,6 +116,7 @@ public class StartingSurfaceDrawer {
@VisibleForTesting
final SplashscreenContentDrawer mSplashscreenContentDrawer;
private Choreographer mChoreographer;
+ private final WindowManagerGlobal mWindowManagerGlobal;
/**
* @param splashScreenExecutor The thread used to control add and remove starting window.
@@ -126,6 +128,8 @@ public class StartingSurfaceDrawer {
mSplashScreenExecutor = splashScreenExecutor;
mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, pool);
mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
+ mWindowManagerGlobal = WindowManagerGlobal.getInstance();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY);
}
private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
@@ -137,21 +141,8 @@ public class StartingSurfaceDrawer {
private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
new SparseArray<>(1);
- /** Obtain proper context for showing splash screen on the provided display. */
- private Context getDisplayContext(Context context, int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- // The default context fits.
- return context;
- }
-
- final Display targetDisplay = mDisplayManager.getDisplay(displayId);
- if (targetDisplay == null) {
- // Failed to obtain the non-default display where splash screen should be shown,
- // lets not show at all.
- return null;
- }
-
- return context.createDisplayContext(targetDisplay);
+ private Display getDisplay(int displayId) {
+ return mDisplayManager.getDisplay(displayId);
}
private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
@@ -186,13 +177,11 @@ public class StartingSurfaceDrawer {
+ " suggestType=" + suggestType);
}
- // Obtain proper context to launch on the right display.
- final Context displayContext = getDisplayContext(context, displayId);
- if (displayContext == null) {
+ final Display display = getDisplay(displayId);
+ if (display == null) {
// Can't show splash screen on requested display, so skip showing at all.
return;
}
- context = displayContext;
if (theme != context.getThemeResId()) {
try {
context = context.createPackageContextAsUser(activityInfo.packageName,
@@ -330,10 +319,8 @@ public class StartingSurfaceDrawer {
};
mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
viewSupplier::setView);
-
try {
- final WindowManager wm = context.getSystemService(WindowManager.class);
- if (addWindow(taskId, appToken, rootLayout, wm, params, suggestType)) {
+ if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
// We use the splash screen worker thread to create SplashScreenView while adding
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
// And since Choreographer#doFrame won't happen immediately after adding the window,
@@ -508,12 +495,14 @@ public class StartingSurfaceDrawer {
viewHost.getView().post(viewHost::release);
}
- protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
+ protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
boolean shouldSaveView = true;
+ final Context context = view.getContext();
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
- wm.addView(view, params);
+ mWindowManagerGlobal.addView(view, params, display,
+ null /* parentWindow */, context.getUserId());
} catch (WindowManager.BadTokenException e) {
// ignore
Slog.w(TAG, appToken + " already running, starting window not displayed. "
@@ -521,9 +510,9 @@ public class StartingSurfaceDrawer {
shouldSaveView = false;
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if (view != null && view.getParent() == null) {
+ if (view.getParent() == null) {
Slog.w(TAG, "view not successfully added to wm, removing view");
- wm.removeViewImmediate(view);
+ mWindowManagerGlobal.removeView(view, true /* immediate */);
shouldSaveView = false;
}
}
@@ -587,10 +576,7 @@ public class StartingSurfaceDrawer {
if (hideView) {
decorView.setVisibility(View.GONE);
}
- final WindowManager wm = decorView.getContext().getSystemService(WindowManager.class);
- if (wm != null) {
- wm.removeView(decorView);
- }
+ mWindowManagerGlobal.removeView(decorView, false /* immediate */);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 01134a7c74f7..b584038bf0e5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -23,6 +23,10 @@ import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.ActivityOptions.ANIM_SCALE_UP;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
+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 android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
@@ -31,8 +35,10 @@ import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
@@ -68,9 +74,12 @@ import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.AttributeCache;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -97,6 +106,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, true);
private final TransactionPool mTransactionPool;
+ private final DisplayController mDisplayController;
private final Context mContext;
private final ShellExecutor mMainExecutor;
private final ShellExecutor mAnimExecutor;
@@ -114,8 +124,10 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
private ScreenRotationAnimation mRotationAnimation;
- DefaultTransitionHandler(@NonNull TransactionPool transactionPool, Context context,
+ DefaultTransitionHandler(@NonNull DisplayController displayController,
+ @NonNull TransactionPool transactionPool, Context context,
@NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+ mDisplayController = displayController;
mTransactionPool = transactionPool;
mContext = context;
mMainExecutor = mainExecutor;
@@ -126,6 +138,110 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
AttributeCache.init(context);
}
+ @VisibleForTesting
+ static boolean isRotationSeamless(@NonNull TransitionInfo info,
+ DisplayController displayController) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "Display is rotating, check if it should be seamless.");
+ boolean checkedDisplayLayout = false;
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+
+ // Only look at changing things. showing/hiding don't need to rotate.
+ if (change.getMode() != TRANSIT_CHANGE) continue;
+
+ // This container isn't rotating, so we can ignore it.
+ if (change.getEndRotation() == change.getStartRotation()) continue;
+
+ if ((change.getFlags() & FLAG_IS_DISPLAY) != 0) {
+ // In the presence of System Alert windows we can not seamlessly rotate.
+ if ((change.getFlags() & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " display has system alert windows, so not seamless.");
+ return false;
+ }
+ } else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+ if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " wallpaper is participating but isn't seamless.");
+ return false;
+ }
+ } else if (change.getTaskInfo() != null) {
+ // We only enable seamless rotation if all the visible task windows requested it.
+ if (change.getRotationAnimation() != ROTATION_ANIMATION_SEAMLESS) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " task %s isn't requesting seamless, so not seamless.",
+ change.getTaskInfo().taskId);
+ return false;
+ }
+
+ // This is the only way to get display-id currently, so we will check display
+ // capabilities here
+ if (!checkedDisplayLayout) {
+ // only need to check display once.
+ checkedDisplayLayout = true;
+ final DisplayLayout displayLayout = displayController.getDisplayLayout(
+ change.getTaskInfo().displayId);
+ // For the upside down rotation we don't rotate seamlessly as the navigation
+ // bar moves position. Note most apps (using orientation:sensor or user as
+ // opposed to fullSensor) will not enter the reverse portrait orientation, so
+ // actually the orientation won't change at all.
+ int upsideDownRotation = displayLayout.getUpsideDownRotation();
+ if (change.getStartRotation() == upsideDownRotation
+ || change.getEndRotation() == upsideDownRotation) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " rotation involves upside-down portrait, so not seamless.");
+ return false;
+ }
+
+ // If the navigation bar can't change sides, then it will jump when we change
+ // orientations and we don't rotate seamlessly - unless that is allowed, eg.
+ // with gesture navigation where the navbar is low-profile enough that this
+ // isn't very noticeable.
+ if (!displayLayout.allowSeamlessRotationDespiteNavBarMoving()
+ && (!(displayLayout.navigationBarCanMove()
+ && (change.getStartAbsBounds().width()
+ != change.getStartAbsBounds().height())))) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ " nav bar changes sides, so not seamless.");
+ return false;
+ }
+ }
+ }
+ }
+
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Rotation IS seamless.");
+ return true;
+ }
+
+ /**
+ * Gets the rotation animation for the topmost task. Assumes that seamless is checked
+ * elsewhere, so it will default SEAMLESS to ROTATE.
+ */
+ private int getRotationAnimation(@NonNull TransitionInfo info) {
+ // Traverse in top-to-bottom order so that the first task is top-most
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+
+ // Only look at changing things. showing/hiding don't need to rotate.
+ if (change.getMode() != TRANSIT_CHANGE) continue;
+
+ // This container isn't rotating, so we can ignore it.
+ if (change.getEndRotation() == change.getStartRotation()) continue;
+
+ if (change.getTaskInfo() != null) {
+ final int anim = change.getRotationAnimation();
+ if (anim == ROTATION_ANIMATION_UNSPECIFIED
+ // Fallback animation for seamless should also be default.
+ || anim == ROTATION_ANIMATION_SEAMLESS) {
+ return ROTATION_ANIMATION_ROTATE;
+ }
+ return anim;
+ }
+ }
+ return ROTATION_ANIMATION_ROTATE;
+ }
+
@Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@@ -168,11 +284,15 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
if (info.getType() == TRANSIT_CHANGE && change.getMode() == TRANSIT_CHANGE
&& (change.getEndRotation() != change.getStartRotation())
&& (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
- mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
- mTransactionPool, startTransaction, change, info.getRootLeash());
- mRotationAnimation.startAnimation(animations, onAnimFinish,
- mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
- continue;
+ boolean isSeamless = isRotationSeamless(info, mDisplayController);
+ final int anim = getRotationAnimation(info);
+ if (!(isSeamless || anim == ROTATION_ANIMATION_JUMPCUT)) {
+ mRotationAnimation = new ScreenRotationAnimation(mContext, mSurfaceSession,
+ mTransactionPool, startTransaction, change, info.getRootLeash());
+ mRotationAnimation.startAnimation(animations, onAnimFinish,
+ mTransitionAnimationScaleSetting, mMainExecutor, mAnimExecutor);
+ continue;
+ }
}
if (change.getMode() == TRANSIT_CHANGE) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 01ef2a6d5111..09dfabf9bfdf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -54,6 +54,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
@@ -113,15 +114,16 @@ public class Transitions implements RemoteCallable<Transitions> {
private final ArrayList<ActiveTransition> mActiveTransitions = new ArrayList<>();
public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
- @NonNull Context context, @NonNull ShellExecutor mainExecutor,
- @NonNull ShellExecutor animExecutor) {
+ @NonNull DisplayController displayController, @NonNull Context context,
+ @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
mOrganizer = organizer;
mContext = context;
mMainExecutor = mainExecutor;
mAnimExecutor = animExecutor;
mPlayerImpl = new TransitionPlayerImpl();
// The very last handler (0 in the list) should be the default one.
- mHandlers.add(new DefaultTransitionHandler(pool, context, mainExecutor, animExecutor));
+ mHandlers.add(new DefaultTransitionHandler(displayController, pool, context, mainExecutor,
+ animExecutor));
// Next lowest priority is remote transitions.
mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
mHandlers.add(mRemoteTransitionHandler);
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index d4b4e5daf7cb..3f860b5cc2d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -17,11 +17,14 @@
package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
+import android.graphics.Rect
import android.media.session.MediaController
import android.media.session.MediaSessionManager
import android.os.SystemClock
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.helpers.FIND_TIMEOUT
import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
@@ -113,25 +116,25 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
}
}
+ private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect {
+ val windowRegion = wmHelper.getWindowRegion(component)
+ require(!windowRegion.isEmpty) {
+ "Unable to find a PIP window in the current state"
+ }
+ return windowRegion.bounds
+ }
+
/**
* Expands the pip window and dismisses it by clicking on the X button.
- *
- * Note, currently the View coordinates reported by the accessibility are relative to
- * the window, so the correct coordinates need to be calculated
- *
- * For example, in a PIP window located at Rect(508, 1444 - 1036, 1741), the
- * dismiss button coordinates are shown as Rect(650, 0 - 782, 132), with center in
- * Point(716, 66), instead of Point(970, 1403)
- *
- * See b/179337864
*/
fun closePipWindow(wmHelper: WindowManagerStateHelper) {
if (isTelevision) {
uiDevice.closeTvPipWindow()
} else {
- expandPipWindow(wmHelper)
+ val windowRect = getWindowRect(wmHelper)
+ uiDevice.click(windowRect.centerX(), windowRect.centerY())
val exitPipObject = uiDevice.findObject(By.res(SYSTEMUI_PACKAGE, "dismiss"))
- requireNotNull(exitPipObject) { "PIP window dismiss button not found" }
+ ?: error("PIP window dismiss button not found")
val dismissButtonBounds = exitPipObject.visibleBounds
uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY())
}
@@ -142,32 +145,28 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
}
/**
- * Click once on the PIP window to expand it
+ * Close the pip window by pressing the expand button
*/
- fun expandPipWindow(wmHelper: WindowManagerStateHelper) {
- val windowRegion = wmHelper.getWindowRegion(component)
- require(!windowRegion.isEmpty) {
- "Unable to find a PIP window in the current state"
- }
- val windowRect = windowRegion.bounds
+ fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) {
+ val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
- // Ensure WindowManagerService wait until all animations have completed
- wmHelper.waitForAppTransitionIdle()
- mInstrumentation.uiAutomation.syncInputTransactions()
+ // search and interact with the expand button
+ val expandSelector = By.res(SYSTEMUI_PACKAGE, "expand_button")
+ uiDevice.wait(Until.hasObject(expandSelector), FIND_TIMEOUT)
+ val expandPipObject = uiDevice.findObject(expandSelector)
+ ?: error("PIP window expand button not found")
+ val expandButtonBounds = expandPipObject.visibleBounds
+ uiDevice.click(expandButtonBounds.centerX(), expandButtonBounds.centerY())
+ wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() }
}
/**
- * Double click on the PIP window to reopen to app
+ * Double click on the PIP window to expand it
*/
- fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) {
- val windowRegion = wmHelper.getWindowRegion(component)
- require(!windowRegion.isEmpty) {
- "Unable to find a PIP window in the current state"
- }
- val windowRect = windowRegion.bounds
+ fun doubleClickPipWindow(wmHelper: WindowManagerStateHelper) {
+ val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
uiDevice.click(windowRect.centerX(), windowRect.centerY())
- wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() }
wmHelper.waitForAppTransitionIdle()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 0f0a4abe30ef..20d58f4873a8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -23,8 +24,10 @@ import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.traces.parser.toLayerName
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -32,8 +35,21 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test Pip launch.
+ * Test entering pip from an app by interacting with the app UI
+ *
* To run this test: `atest WMShellFlickerTests:EnterPipTest`
+ *
+ * Actions:
+ * Launch an app in full screen
+ * Press an "enter pip" button to put [pipApp] in pip mode
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -41,14 +57,19 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group3
class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+ /**
+ * Defines the transition used to run the test
+ */
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true, stringExtras = emptyMap()) {
transitions {
pipApp.clickEnterPipButton(wmHelper)
- pipApp.expandPipWindow(wmHelper)
}
}
+ /**
+ * Checks [pipApp] window remains visible throughout the animation
+ */
@Presubmit
@Test
fun pipAppWindowAlwaysVisible() {
@@ -57,6 +78,9 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
}
}
+ /**
+ * Checks [pipApp] layer remains visible throughout the animation
+ */
@Presubmit
@Test
fun pipAppLayerAlwaysVisible() {
@@ -65,19 +89,89 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
}
}
- @FlakyTest
+ /**
+ * Checks that the pip app window remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Postsubmit
@Test
- fun pipWindowBecomesVisible() {
+ fun pipWindowRemainInsideVisibleBounds() {
testSpec.assertWm {
- invoke("pipWindowIsNotVisible") {
- verify("Has no pip window").that(it.wmState.hasPipWindow()).isTrue()
- }.then().invoke("pipWindowIsVisible") {
- verify("Has pip window").that(it.wmState.hasPipWindow()).isTrue()
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the pip app layer remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Postsubmit
+ @Test
+ fun pipLayerRemainInsideVisibleBounds() {
+ testSpec.assertLayers {
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [pipApp] always reduces during the animation
+ */
+ @Postsubmit
+ @Test
+ fun pipLayerReduces() {
+ val layerName = pipApp.component.toLayerName()
+ testSpec.assertLayers {
+ val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
+ pipLayerList.zipWithNext { previous, current ->
+ current.visibleRegion.coversAtMost(previous.visibleRegion.region)
}
}
}
+ /**
+ * Checks that [pipApp] window becomes pinned
+ */
+ @Postsubmit
+ @Test
+ fun pipWindowBecomesPinned() {
+ testSpec.assertWm {
+ invoke("pipWindowIsNotPinned") { it.isNotPinned(pipApp.component) }
+ .then()
+ .invoke("pipWindowIsPinned") { it.isPinned(pipApp.component) }
+ }
+ }
+
+ /**
+ * Checks [LAUNCHER_COMPONENT] layer remains visible throughout the animation
+ */
+ @Postsubmit
+ @Test
+ fun launcherLayerBecomesVisible() {
+ testSpec.assertLayers {
+ isInvisible(LAUNCHER_COMPONENT)
+ .then()
+ .isVisible(LAUNCHER_COMPONENT)
+ }
+ }
+
+ /**
+ * Checks the focus doesn't change during the animation
+ */
+ @FlakyTest
+ @Test
+ fun focusDoesNotChange() {
+ testSpec.assertEventLog {
+ this.focusDoesNotChange()
+ }
+ }
+
companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 67ad322f19f6..36ab8014ced3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -25,7 +26,11 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
@@ -38,8 +43,22 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test Pip with orientation changes.
- * To run this test: `atest WMShellFlickerTests:PipOrientationTest`
+ * Test entering pip while changing orientation (from app in landscape to pip window in portrait)
+ *
+ * To run this test: `atest EnterPipToOtherOrientationTest:EnterPipToOtherOrientationTest`
+ *
+ * Actions:
+ * Launch [testApp] on a fixed portrait orientation
+ * Launch [pipApp] on a fixed landscape orientation
+ * Broadcast action [ACTION_ENTER_PIP] to enter pip mode
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -53,6 +72,9 @@ class EnterPipToOtherOrientationTest(
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
+ /**
+ * Defines the transition used to run the test
+ */
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setupAndTeardown(this, configuration)
@@ -82,18 +104,32 @@ class EnterPipToOtherOrientationTest(
}
}
+ /**
+ * Checks that the [WindowManagerStateHelper.NAV_BAR_COMPONENT] has the correct position at
+ * the start and end of the transition
+ */
@FlakyTest
@Test
- override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+ override fun navBarLayerRotatesAndScales() =
+ testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_90, Surface.ROTATION_0)
- @FlakyTest
+ /**
+ * Checks that the [WindowManagerStateHelper.STATUS_BAR_COMPONENT] has the correct position at
+ * the start and end of the transition
+ */
+ @Postsubmit
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() =
+ testSpec.statusBarLayerRotatesScales(Surface.ROTATION_90, Surface.ROTATION_0)
- @FlakyTest
+ @Postsubmit
@Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ override fun entireScreenCovered() =
+ testSpec.entireScreenCovered(Surface.ROTATION_90, Surface.ROTATION_0, allStates = false)
+ /**
+ * Checks [pipApp] window remains visible and on top throughout the transition
+ */
@Presubmit
@Test
fun pipAppWindowIsAlwaysOnTop() {
@@ -102,40 +138,84 @@ class EnterPipToOtherOrientationTest(
}
}
+ /**
+ * Checks that [testApp] window is not visible at the start
+ */
@Presubmit
@Test
- fun pipAppHidesTestApp() {
+ fun testAppWindowInvisibleOnStart() {
testSpec.assertWmStart {
isInvisible(testApp.component)
}
}
+ /**
+ * Checks that [testApp] window is visible at the end
+ */
@Presubmit
@Test
- fun testAppWindowIsVisible() {
+ fun testAppWindowVisibleOnEnd() {
testSpec.assertWmEnd {
isVisible(testApp.component)
}
}
+ /**
+ * Checks that [testApp] layer is not visible at the start
+ */
@Presubmit
@Test
- fun pipAppLayerHidesTestApp() {
+ fun testAppLayerInvisibleOnStart() {
testSpec.assertLayersStart {
- visibleRegion(pipApp.component).coversExactly(startingBounds)
isInvisible(testApp.component)
}
}
+ /**
+ * Checks that [testApp] layer is visible at the end
+ */
+ @Presubmit
+ @Test
+ fun testAppLayerVisibleOnEnd() {
+ testSpec.assertLayersEnd {
+ isVisible(testApp.component)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [pipApp] covers the full display area at the start of
+ * the transition
+ */
+ @Presubmit
+ @Test
+ fun pipAppLayerCoversFullScreenOnStart() {
+ testSpec.assertLayersStart {
+ visibleRegion(pipApp.component).coversExactly(startingBounds)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [testApp] plus the visible region of [pipApp]
+ * cover the full display area at the end of the transition
+ */
@Presubmit
@Test
- fun testAppLayerCoversFullScreen() {
+ fun testAppPlusPipLayerCoversFullScreenOnEnd() {
testSpec.assertLayersEnd {
- visibleRegion(testApp.component).coversExactly(endingBounds)
+ val pipRegion = visibleRegion(pipApp.component).region
+ visibleRegion(testApp.component)
+ .plus(pipRegion)
+ .coversExactly(endingBounds)
}
}
companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
new file mode 100644
index 000000000000..faaaecb8da46
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Presubmit
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.traces.parser.toLayerName
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import org.junit.Test
+
+/**
+ * Base class for pip expand tests
+ */
+abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+ protected val testApp = FixedAppHelper(instrumentation)
+
+ /**
+ * Checks that the pip app window remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Presubmit
+ @Test
+ open fun pipAppWindowRemainInsideVisibleBounds() {
+ testSpec.assertWm {
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the pip app layer remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Presubmit
+ @Test
+ open fun pipAppLayerRemainInsideVisibleBounds() {
+ testSpec.assertLayers {
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks both app windows are visible at the start of the transition (with [pipApp] on top).
+ * Then, during the transition, [testApp] becomes invisible and [pipApp] remains visible
+ */
+ @Presubmit
+ @Test
+ open fun showBothAppWindowsThenHidePip() {
+ testSpec.assertWm {
+ // when the activity is STOPPING, sometimes it becomes invisible in an entry before
+ // the window, sometimes in the same entry. This occurs because we log 1x per frame
+ // thus we ignore activity here
+ isAppWindowVisible(testApp.component, ignoreActivity = true)
+ .isAppWindowOnTop(pipApp.component)
+ .then()
+ .isAppWindowInvisible(testApp.component)
+ .isAppWindowVisible(pipApp.component)
+ }
+ }
+
+ /**
+ * Checks both app layers are visible at the start of the transition. Then, during the
+ * transition, [testApp] becomes invisible and [pipApp] remains visible
+ */
+ @Presubmit
+ @Test
+ open fun showBothAppLayersThenHidePip() {
+ testSpec.assertLayers {
+ isVisible(testApp.component)
+ .isVisible(pipApp.component)
+ .then()
+ .isInvisible(testApp.component)
+ .isVisible(pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [testApp] plus the visible region of [pipApp]
+ * cover the full display area at the start of the transition
+ */
+ @Presubmit
+ @Test
+ open fun testPlusPipAppsCoverFullScreenAtStart() {
+ testSpec.assertLayersStart {
+ val pipRegion = visibleRegion(pipApp.component).region
+ visibleRegion(testApp.component)
+ .plus(pipRegion)
+ .coversExactly(displayBounds)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [pipApp] covers the full display area at the end of
+ * the transition
+ */
+ @Presubmit
+ @Test
+ open fun pipAppCoversFullScreenAtEnd() {
+ testSpec.assertLayersEnd {
+ visibleRegion(pipApp.component).coversExactly(displayBounds)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [pipApp] always expands during the animation
+ */
+ @Presubmit
+ @Test
+ open fun pipLayerExpands() {
+ val layerName = pipApp.component.toLayerName()
+ testSpec.assertLayers {
+ val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
+ pipLayerList.zipWithNext { previous, current ->
+ current.visibleRegion.coversAtLeast(previous.visibleRegion.region)
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 28b1028d41ca..3414031d3532 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -20,15 +20,16 @@ import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.startRotation
import org.junit.Test
-import org.junit.runners.Parameterized
-abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+/**
+ * Base class for exiting pip (closing pip window) without returning to the app
+ */
+abstract class ExitPipTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) { configuration ->
setup {
@@ -43,16 +44,28 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
}
}
+ /**
+ * Checks that [pipApp] window is pinned and visible at the start and then becomes
+ * unpinned and invisible at the same moment, and remains unpinned and invisible
+ * until the end of the transition
+ */
@Presubmit
@Test
open fun pipWindowBecomesInvisible() {
testSpec.assertWm {
- this.invoke("hasPipWindow") { it.isPinned(pipApp.component) }
- .then()
- .isAppWindowInvisible(pipApp.component)
+ this.invoke("hasPipWindow") {
+ it.isPinned(pipApp.component).isVisible(pipApp.component)
+ }.then().invoke("!hasPipWindow") {
+ it.isNotPinned(pipApp.component).isInvisible(pipApp.component)
+ }
}
}
+ /**
+ * Checks that [pipApp] and [LAUNCHER_COMPONENT] layers are visible at the start
+ * of the transition. Then [pipApp] layer becomes invisible, and remains invisible
+ * until the end of the transition
+ */
@Presubmit
@Test
open fun pipLayerBecomesInvisible() {
@@ -65,6 +78,10 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
}
}
+ /**
+ * Checks that the focus changes between the [pipApp] window and the launcher when
+ * closing the pip window
+ */
@FlakyTest(bugId = 151179149)
@Test
open fun focusChanges() {
@@ -72,14 +89,4 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
this.focusChanges(pipApp.launcherName, "NexusLauncherActivity")
}
}
-
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
- repetitions = 5)
- }
- }
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
new file mode 100644
index 000000000000..1ece34eba3ec
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.annotation.Group3
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test expanding a pip window back to full screen via the expand button
+ *
+ * To run this test: `atest WMShellFlickerTests:ExitPipViaExpandButtonClickTest`
+ *
+ * Actions:
+ * Launch an app in pip mode [pipApp],
+ * Launch another full screen mode [testApp]
+ * Expand [pipApp] app to full screen by clicking on the pip window and
+ * then on the expand button
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Group3
+@Postsubmit
+class ExitPipViaExpandButtonClickTest(
+ testSpec: FlickerTestParameter
+) : ExitPipToAppTransition(testSpec) {
+
+ /**
+ * Defines the transition used to run the test
+ */
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = buildTransition(eachRun = true) {
+ setup {
+ eachRun {
+ // launch an app behind the pip one
+ testApp.launchViaIntent(wmHelper)
+ }
+ }
+ transitions {
+ // This will bring PipApp to fullscreen
+ pipApp.expandPipWindowToApp(wmHelper)
+ }
+ }
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+ supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 39e89fbd9b71..fbfa448cb877 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -25,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -33,23 +31,38 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test Pip launch and exit.
- * To run this test: `atest WMShellFlickerTests:EnterExitPipTest`
+ * Test expanding a pip window back to full screen via an intent
+ *
+ * To run this test: `atest WMShellFlickerTests:ExitPipViaIntentTest`
+ *
+ * Actions:
+ * Launch an app in pip mode [pipApp],
+ * Launch another full screen mode [testApp]
+ * Expand [pipApp] app to full screen via an intent
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited from [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group3
-class EnterExitPipTest(
- testSpec: FlickerTestParameter
-) : PipTransition(testSpec) {
- private val testApp = FixedAppHelper(instrumentation)
+class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) {
+ /**
+ * Defines the transition used to run the test
+ */
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) {
setup {
eachRun {
+ // launch an app behind the pip one
testApp.launchViaIntent(wmHelper)
}
}
@@ -59,57 +72,17 @@ class EnterExitPipTest(
}
}
- @Presubmit
- @Test
- fun pipAppRemainInsideVisibleBounds() {
- testSpec.assertWm {
- coversAtMost(displayBounds, pipApp.component)
- }
- }
-
@Postsubmit
@Test
- fun showBothAppWindowsThenHidePip() {
- testSpec.assertWm {
- // when the activity is STOPPING, sometimes it becomes invisible in an entry before
- // the window, sometimes in the same entry. This occurs because we log 1x per frame
- // thus we ignore activity here
- isAppWindowVisible(testApp.component, ignoreActivity = true)
- .isAppWindowOnTop(pipApp.component)
- .then()
- .isAppWindowInvisible(testApp.component)
- }
- }
-
- @Presubmit
- @Test
- fun showBothAppLayersThenHidePip() {
- testSpec.assertLayers {
- isVisible(testApp.component)
- .isVisible(pipApp.component)
- .then()
- .isInvisible(testApp.component)
- }
- }
-
- @Presubmit
- @Test
- fun testAppCoversFullScreenWithPipOnDisplay() {
- testSpec.assertLayersStart {
- visibleRegion(testApp.component).coversExactly(displayBounds)
- visibleRegion(pipApp.component).coversAtMost(displayBounds)
- }
- }
-
- @Presubmit
- @Test
- fun pipAppCoversFullScreen() {
- testSpec.assertLayersEnd {
- visibleRegion(pipApp.component).coversExactly(displayBounds)
- }
- }
+ override fun pipLayerExpands() = super.pipLayerExpands()
companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index 1c5d77f68f43..e3d099f6fdb5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -16,10 +16,12 @@
package com.android.wm.shell.flicker.pip
-import androidx.test.filters.FlakyTest
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import org.junit.FixMethodOrder
@@ -29,15 +31,29 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipCloseWithDismissButton`
+ * Test closing a pip window via the dismiss button
+ *
+ * To run this test: `atest WMShellFlickerTests:ExitPipWithDismissButtonTest`
+ *
+ * Actions:
+ * Launch an app in pip mode [pipApp],
+ * Click on the pip window
+ * Click on dismiss button and wait window disappear
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group3
-class PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) {
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
@@ -46,11 +62,27 @@ class PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTr
}
}
- @FlakyTest
+ @Postsubmit
@Test
override fun pipLayerBecomesInvisible() = super.pipLayerBecomesInvisible()
- @FlakyTest
+ @Postsubmit
@Test
override fun pipWindowBecomesInvisible() = super.pipWindowBecomesInvisible()
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5)
+ }
+ }
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index 356ec94b97e3..2cdfc2bf0654 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -22,6 +22,7 @@ import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.startRotation
@@ -33,24 +34,40 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipCloseWithSwipe`
+ * Test closing a pip window by swiping it to the bottom-center of the screen
+ *
+ * To run this test: `atest WMShellFlickerTests:ExitPipWithSwipeDownTest`
+ *
+ * Actions:
+ * Launch an app in pip mode [pipApp],
+ * Swipe the pip window to the bottom-center of the screen and wait it disappear
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group3
-class PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+class ExitPipWithSwipeDownTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) {
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
- get() = {
- super.transition(this, it)
+ get() = { args ->
+ super.transition(this, args)
transitions {
val pipRegion = wmHelper.getWindowRegion(pipApp.component).bounds
val pipCenterX = pipRegion.centerX()
val pipCenterY = pipRegion.centerY()
val displayCenterX = device.displayWidth / 2
- device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 5)
+ device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 10)
+ wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() }
+ wmHelper.waitForWindowSurfaceDisappeared(pipApp.component)
+ wmHelper.waitForAppTransitionIdle()
}
}
@@ -90,4 +107,20 @@ class PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition
@Presubmit
@Test
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 20)
+ }
+ }
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
new file mode 100644
index 000000000000..649d4168c9e4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.LAUNCHER_COMPONENT
+import com.android.server.wm.flicker.annotation.Group3
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.traces.parser.toLayerName
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test expanding a pip window by double clicking it
+ *
+ * To run this test: `atest WMShellFlickerTests:ExpandPipOnDoubleClickTest`
+ *
+ * Actions:
+ * Launch an app in pip mode [pipApp],
+ * Expand [pipApp] app to its maximum pip size by double clicking on it
+ *
+ * Notes:
+ * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ * are inherited [PipTransition]
+ * 2. Part of the test setup occurs automatically via
+ * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Group3
+@Postsubmit
+class ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = buildTransition(eachRun = true) {
+ transitions {
+ pipApp.doubleClickPipWindow(wmHelper)
+ }
+ }
+
+ /**
+ * Checks that the pip app window remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Test
+ fun pipWindowRemainInsideVisibleBounds() {
+ testSpec.assertWm {
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the pip app layer remains inside the display bounds throughout the whole
+ * animation
+ */
+ @Test
+ fun pipLayerRemainInsideVisibleBounds() {
+ testSpec.assertLayers {
+ coversAtMost(displayBounds, pipApp.component)
+ }
+ }
+
+ /**
+ * Checks [pipApp] window remains visible throughout the animation
+ */
+ @Test
+ fun pipWindowIsAlwaysVisible() {
+ testSpec.assertWm {
+ isAppWindowVisible(pipApp.component)
+ }
+ }
+
+ /**
+ * Checks [pipApp] layer remains visible throughout the animation
+ */
+ @Test
+ fun pipLayerIsAlwaysVisible() {
+ testSpec.assertLayers {
+ isVisible(pipApp.component)
+ }
+ }
+
+ /**
+ * Checks that the visible region of [pipApp] always expands during the animation
+ */
+ @Test
+ fun pipLayerExpands() {
+ val layerName = pipApp.component.toLayerName()
+ testSpec.assertLayers {
+ val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
+ pipLayerList.zipWithNext { previous, current ->
+ current.visibleRegion.coversAtLeast(previous.visibleRegion.region)
+ }
+ }
+ }
+
+ @Test
+ fun windowIsAlwaysPinned() {
+ testSpec.assertWm {
+ this.invoke("hasPipWindow") { it.isPinned(pipApp.component) }
+ }
+ }
+
+ /**
+ * Checks [pipApp] layer remains visible throughout the animation
+ */
+ @Test
+ fun launcherIsAlwaysVisible() {
+ testSpec.assertLayers {
+ isVisible(LAUNCHER_COMPONENT)
+ }
+ }
+
+ /**
+ * Checks that the focus doesn't change between windows during the transition
+ */
+ @FlakyTest
+ @Test
+ fun focusDoesNotChange() {
+ testSpec.assertEventLog {
+ this.focusDoesNotChange()
+ }
+ }
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
+ * repetitions, screen orientation and navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5)
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
deleted file mode 100644
index 5abcf39f3fbd..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.pip
-
-import android.view.Surface
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.FlickerTestParameterFactory
-import com.android.server.wm.flicker.LAUNCHER_COMPONENT
-import com.android.server.wm.flicker.annotation.Group3
-import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.startRotation
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipToAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group3
-class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
- get() = buildTransition(eachRun = true) { configuration ->
- setup {
- eachRun {
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- this.setRotation(Surface.ROTATION_0)
- }
- }
- transitions {
- pipApp.expandPipWindowToApp(wmHelper)
- }
- }
-
- @FlakyTest
- @Test
- fun appReplacesPipWindow() {
- testSpec.assertWm {
- this.invoke("hasPipWindow") { it.isPinned(pipApp.component) }
- .isAppWindowOnTop(pipApp.component)
- .then()
- .invoke("hasNotPipWindow") { it.isNotPinned(pipApp.component) }
- .isAppWindowOnTop(pipApp.component)
- }
- }
-
- @FlakyTest
- @Test
- fun appReplacesPipLayer() {
- testSpec.assertLayers {
- this.isVisible(pipApp.component)
- .isVisible(LAUNCHER_COMPONENT)
- .then()
- .isVisible(pipApp.component)
- .isInvisible(LAUNCHER_COMPONENT)
- }
- }
-
- @FlakyTest
- @Test
- fun testAppCoversFullScreen() {
- testSpec.assertLayersStart {
- visibleRegion(pipApp.component).coversExactly(displayBounds)
- }
- }
-
- @FlakyTest(bugId = 151179149)
- @Test
- fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges("NexusLauncherActivity",
- pipApp.launcherName, "NexusLauncherActivity")
- }
- }
-
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
- repetitions = 5)
- }
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
index ef046d48e1cf..b88845044263 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java
@@ -58,7 +58,7 @@ public class DisplayImeControllerTest {
mT = mock(SurfaceControl.Transaction.class);
mMock = mock(IInputMethodManager.class);
mExecutor = spy(Runnable::run);
- mPerDisplay = new DisplayImeController(null, null, mExecutor, new TransactionPool() {
+ mPerDisplay = new DisplayImeController(null, null, null, mExecutor, new TransactionPool() {
@Override
public SurfaceControl.Transaction acquire() {
return mT;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java
new file mode 100644
index 000000000000..b66c2b4aee9b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayInsetsControllerTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.RemoteException;
+import android.util.SparseArray;
+import android.view.IDisplayWindowInsetsController;
+import android.view.IWindowManager;
+import android.view.InsetsSourceControl;
+import android.view.InsetsState;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.TestShellExecutor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+@SmallTest
+public class DisplayInsetsControllerTest {
+
+ private static final int SECOND_DISPLAY = DEFAULT_DISPLAY + 10;
+
+ @Mock
+ private IWindowManager mWm;
+ @Mock
+ private DisplayController mDisplayController;
+ private DisplayInsetsController mController;
+ private SparseArray<IDisplayWindowInsetsController> mInsetsControllersByDisplayId;
+ private TestShellExecutor mExecutor;
+
+ private ArgumentCaptor<Integer> mDisplayIdCaptor;
+ private ArgumentCaptor<IDisplayWindowInsetsController> mInsetsControllerCaptor;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mExecutor = new TestShellExecutor();
+ mInsetsControllersByDisplayId = new SparseArray<>();
+ mDisplayIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ mInsetsControllerCaptor = ArgumentCaptor.forClass(IDisplayWindowInsetsController.class);
+ mController = new DisplayInsetsController(mWm, mDisplayController, mExecutor);
+ addDisplay(DEFAULT_DISPLAY);
+ }
+
+ @Test
+ public void testOnDisplayAdded_setsDisplayWindowInsetsControllerOnWMService()
+ throws RemoteException {
+ addDisplay(SECOND_DISPLAY);
+
+ verify(mWm).setDisplayWindowInsetsController(eq(SECOND_DISPLAY), notNull());
+ }
+
+ @Test
+ public void testOnDisplayRemoved_unsetsDisplayWindowInsetsControllerInWMService()
+ throws RemoteException {
+ addDisplay(SECOND_DISPLAY);
+ removeDisplay(SECOND_DISPLAY);
+
+ verify(mWm).setDisplayWindowInsetsController(SECOND_DISPLAY, null);
+ }
+
+ @Test
+ public void testPerDisplayListenerCallback() throws RemoteException {
+ TrackedListener defaultListener = new TrackedListener();
+ TrackedListener secondListener = new TrackedListener();
+ addDisplay(SECOND_DISPLAY);
+ mController.addInsetsChangedListener(DEFAULT_DISPLAY, defaultListener);
+ mController.addInsetsChangedListener(SECOND_DISPLAY, secondListener);
+
+ mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).topFocusedWindowChanged(null);
+ mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).insetsChanged(null);
+ mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).insetsControlChanged(null, null);
+ mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).showInsets(0, false);
+ mInsetsControllersByDisplayId.get(DEFAULT_DISPLAY).hideInsets(0, false);
+ mExecutor.flushAll();
+
+ assertTrue(defaultListener.topFocusedWindowChangedCount == 1);
+ assertTrue(defaultListener.insetsChangedCount == 1);
+ assertTrue(defaultListener.insetsControlChangedCount == 1);
+ assertTrue(defaultListener.showInsetsCount == 1);
+ assertTrue(defaultListener.hideInsetsCount == 1);
+
+ assertTrue(secondListener.topFocusedWindowChangedCount == 0);
+ assertTrue(secondListener.insetsChangedCount == 0);
+ assertTrue(secondListener.insetsControlChangedCount == 0);
+ assertTrue(secondListener.showInsetsCount == 0);
+ assertTrue(secondListener.hideInsetsCount == 0);
+
+ mInsetsControllersByDisplayId.get(SECOND_DISPLAY).topFocusedWindowChanged(null);
+ mInsetsControllersByDisplayId.get(SECOND_DISPLAY).insetsChanged(null);
+ mInsetsControllersByDisplayId.get(SECOND_DISPLAY).insetsControlChanged(null, null);
+ mInsetsControllersByDisplayId.get(SECOND_DISPLAY).showInsets(0, false);
+ mInsetsControllersByDisplayId.get(SECOND_DISPLAY).hideInsets(0, false);
+ mExecutor.flushAll();
+
+ assertTrue(defaultListener.topFocusedWindowChangedCount == 1);
+ assertTrue(defaultListener.insetsChangedCount == 1);
+ assertTrue(defaultListener.insetsControlChangedCount == 1);
+ assertTrue(defaultListener.showInsetsCount == 1);
+ assertTrue(defaultListener.hideInsetsCount == 1);
+
+ assertTrue(secondListener.topFocusedWindowChangedCount == 1);
+ assertTrue(secondListener.insetsChangedCount == 1);
+ assertTrue(secondListener.insetsControlChangedCount == 1);
+ assertTrue(secondListener.showInsetsCount == 1);
+ assertTrue(secondListener.hideInsetsCount == 1);
+ }
+
+ private void addDisplay(int displayId) throws RemoteException {
+ mController.onDisplayAdded(displayId);
+ verify(mWm, times(mInsetsControllersByDisplayId.size() + 1))
+ .setDisplayWindowInsetsController(mDisplayIdCaptor.capture(),
+ mInsetsControllerCaptor.capture());
+ List<Integer> displayIds = mDisplayIdCaptor.getAllValues();
+ List<IDisplayWindowInsetsController> insetsControllers =
+ mInsetsControllerCaptor.getAllValues();
+ for (int i = 0; i < displayIds.size(); i++) {
+ mInsetsControllersByDisplayId.put(displayIds.get(i), insetsControllers.get(i));
+ }
+ }
+
+ private void removeDisplay(int displayId) {
+ mController.onDisplayRemoved(displayId);
+ mInsetsControllersByDisplayId.remove(displayId);
+ }
+
+ private static class TrackedListener implements
+ DisplayInsetsController.OnInsetsChangedListener {
+ int topFocusedWindowChangedCount = 0;
+ int insetsChangedCount = 0;
+ int insetsControlChangedCount = 0;
+ int showInsetsCount = 0;
+ int hideInsetsCount = 0;
+
+ @Override
+ public void topFocusedWindowChanged(String packageName) {
+ topFocusedWindowChangedCount++;
+ }
+
+ @Override
+ public void insetsChanged(InsetsState insetsState) {
+ insetsChangedCount++;
+ }
+
+ @Override
+ public void insetsControlChanged(InsetsState insetsState,
+ InsetsSourceControl[] activeControls) {
+ insetsControlChangedCount++;
+ }
+
+ @Override
+ public void showInsets(int types, boolean fromIme) {
+ showInsetsCount++;
+ }
+
+ @Override
+ public void hideInsets(int types, boolean fromIme) {
+ hideInsetsCount++;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 3dc0465fbbb4..3557906531b2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
@@ -42,6 +43,8 @@ import com.android.wm.shell.common.DisplayImeController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -53,19 +56,20 @@ public class SplitLayoutTests extends ShellTestCase {
@Mock SurfaceControl mRootLeash;
@Mock DisplayImeController mDisplayImeController;
@Mock ShellTaskOrganizer mTaskOrganizer;
+ @Captor ArgumentCaptor<Runnable> mRunnableCaptor;
private SplitLayout mSplitLayout;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mSplitLayout = new SplitLayout(
+ mSplitLayout = spy(new SplitLayout(
"TestSplitLayout",
mContext,
getConfiguration(),
mSplitLayoutHandler,
b -> b.setParent(mRootLeash),
mDisplayImeController,
- mTaskOrganizer);
+ mTaskOrganizer));
}
@Test
@@ -109,18 +113,33 @@ public class SplitLayoutTests extends ShellTestCase {
@Test
@UiThreadTest
- public void testSnapToDismissTarget() {
+ public void testSnapToDismissStart() {
// verify it callbacks properly when the snap target indicates dismissing split.
DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
+
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
+ waitDividerFlingFinished();
verify(mSplitLayoutHandler).onSnappedToDismiss(eq(false));
- snapTarget = getSnapTarget(0 /* position */,
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSnapToDismissEnd() {
+ // verify it callbacks properly when the snap target indicates dismissing split.
+ DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END);
+
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
+ waitDividerFlingFinished();
verify(mSplitLayoutHandler).onSnappedToDismiss(eq(true));
}
+ private void waitDividerFlingFinished() {
+ verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), mRunnableCaptor.capture());
+ mRunnableCaptor.getValue().run();
+ }
+
private static Configuration getConfiguration() {
final Configuration configuration = new Configuration();
configuration.unset();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index d536adb9f8ae..160b3673aa8a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -42,6 +42,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.TestableContext;
+import android.view.Display;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
@@ -92,8 +93,8 @@ public class StartingSurfaceDrawerTests {
}
@Override
- protected boolean addWindow(int taskId, IBinder appToken,
- View view, WindowManager wm, WindowManager.LayoutParams params, int suggestType) {
+ protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
+ WindowManager.LayoutParams params, int suggestType) {
// listen for addView
mAddWindowForTask = taskId;
mViewThemeResId = view.getContext().getThemeResId();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 21329c75ebb0..376245609c19 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -20,12 +20,18 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -49,6 +55,9 @@ import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.view.IDisplayWindowListener;
+import android.view.IWindowManager;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.IRemoteTransition;
@@ -66,12 +75,15 @@ import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.wm.shell.TestShellExecutor;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
@@ -98,8 +110,7 @@ public class ShellTransitionTests {
@Test
public void testBasicTransitionFlow() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
IBinder transitToken = new Binder();
@@ -118,8 +129,7 @@ public class ShellTransitionTests {
@Test
public void testNonDefaultHandler() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final WindowContainerTransaction handlerWCT = new WindowContainerTransaction();
@@ -202,8 +212,7 @@ public class ShellTransitionTests {
@Test
public void testRequestRemoteTransition() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -297,8 +306,7 @@ public class ShellTransitionTests {
@Test
public void testRegisteredRemoteTransition() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -343,8 +351,7 @@ public class ShellTransitionTests {
@Test
public void testOneShotRemoteHandler() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
final boolean[] remoteCalled = new boolean[]{false};
@@ -390,8 +397,7 @@ public class ShellTransitionTests {
@Test
public void testTransitionQueueing() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
IBinder transitToken1 = new Binder();
@@ -431,8 +437,7 @@ public class ShellTransitionTests {
@Test
public void testTransitionMerging() {
- Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mContext,
- mMainExecutor, mAnimExecutor);
+ Transitions transitions = createTestTransitions();
mDefaultHandler.setSimulateMerge(true);
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
@@ -468,6 +473,63 @@ public class ShellTransitionTests {
assertEquals(0, mDefaultHandler.activeCount());
}
+ @Test
+ public void testShouldRotateSeamlessly() throws Exception {
+ final RunningTaskInfo taskInfo =
+ createTaskInfo(1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final RunningTaskInfo taskInfoPip =
+ createTaskInfo(1, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+
+ final DisplayController displays = createTestDisplayController();
+ final @Surface.Rotation int upsideDown = displays
+ .getDisplayLayout(DEFAULT_DISPLAY).getUpsideDownRotation();
+
+ final TransitionInfo normalDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo).setRotate().build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(normalDispRotate, displays));
+
+ // Seamless if all tasks are seamless
+ final TransitionInfo rotateSeamless = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertTrue(DefaultTransitionHandler.isRotationSeamless(rotateSeamless, displays));
+
+ // Not seamless if there is PiP (or any other non-seamless task)
+ final TransitionInfo pipDispRotate = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY).setRotate()
+ .build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfoPip)
+ .setRotate().build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(pipDispRotate, displays));
+
+ // Not seamless if one of rotations is upside-down
+ final TransitionInfo seamlessUpsideDown = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
+ .setRotate(upsideDown, ROTATION_ANIMATION_UNSPECIFIED).build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(upsideDown, ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessUpsideDown, displays));
+
+ // Not seamless if system alert windows
+ final TransitionInfo seamlessButAlert = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setFlags(
+ FLAG_IS_DISPLAY | FLAG_DISPLAY_HAS_ALERT_WINDOWS).setRotate().build())
+ .addChange(new ChangeBuilder(TRANSIT_CHANGE).setTask(taskInfo)
+ .setRotate(ROTATION_ANIMATION_SEAMLESS).build())
+ .build();
+ assertFalse(DefaultTransitionHandler.isRotationSeamless(seamlessButAlert, displays));
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
@@ -490,11 +552,53 @@ public class ShellTransitionTests {
return addChange(mode, null /* taskInfo */);
}
+ TransitionInfoBuilder addChange(TransitionInfo.Change change) {
+ mInfo.addChange(change);
+ return this;
+ }
+
TransitionInfo build() {
return mInfo;
}
}
+ class ChangeBuilder {
+ final TransitionInfo.Change mChange;
+
+ ChangeBuilder(@WindowManager.TransitionType int mode) {
+ mChange = new TransitionInfo.Change(null /* token */, null /* leash */);
+ mChange.setMode(mode);
+ }
+
+ ChangeBuilder setFlags(@TransitionInfo.ChangeFlags int flags) {
+ mChange.setFlags(flags);
+ return this;
+ }
+
+ ChangeBuilder setTask(RunningTaskInfo taskInfo) {
+ mChange.setTaskInfo(taskInfo);
+ return this;
+ }
+
+ ChangeBuilder setRotate(int anim) {
+ return setRotate(Surface.ROTATION_90, anim);
+ }
+
+ ChangeBuilder setRotate() {
+ return setRotate(ROTATION_ANIMATION_UNSPECIFIED);
+ }
+
+ ChangeBuilder setRotate(@Surface.Rotation int target, int anim) {
+ mChange.setRotation(Surface.ROTATION_0, target);
+ mChange.setRotationAnimation(anim);
+ return this;
+ }
+
+ TransitionInfo.Change build() {
+ return mChange;
+ }
+ }
+
class TestTransitionHandler implements Transitions.TransitionHandler {
ArrayList<Transitions.TransitionFinishCallback> mFinishes = new ArrayList<>();
final ArrayList<IBinder> mMerged = new ArrayList<>();
@@ -566,4 +670,46 @@ public class ShellTransitionTests {
return taskInfo;
}
+ private DisplayController createTestDisplayController() {
+ IWindowManager mockWM = mock(IWindowManager.class);
+ final IDisplayWindowListener[] displayListener = new IDisplayWindowListener[1];
+ try {
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) {
+ displayListener[0] = invocation.getArgument(0);
+ return null;
+ }
+ }).when(mockWM).registerDisplayWindowListener(any());
+ } catch (RemoteException e) {
+ // No remote stuff happening, so this can't be hit
+ }
+ DisplayController out = new DisplayController(mContext, mockWM, mMainExecutor);
+ out.initialize();
+ try {
+ displayListener[0].onDisplayAdded(DEFAULT_DISPLAY);
+ mMainExecutor.flushAll();
+ } catch (RemoteException e) {
+ // Again, no remote stuff
+ }
+ return out;
+ }
+
+ private Transitions createTestTransitions() {
+ return new Transitions(mOrganizer, mTransactionPool, createTestDisplayController(),
+ mContext, mMainExecutor, mAnimExecutor);
+ }
+//
+// private class TestDisplayController extends DisplayController {
+// private final DisplayLayout mTestDisplayLayout;
+// TestDisplayController() {
+// super(mContext, mock(IWindowManager.class), mMainExecutor);
+// mTestDisplayLayout = new DisplayLayout();
+// mTestDisplayLayout.
+// }
+//
+// @Override
+// DisplayLayout
+// }
+
}
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 8d112d1c64bf..2b86b1eb7542 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -149,12 +149,14 @@ void DeferredLayerUpdater::apply() {
android_dataspace dataspace;
int slot;
bool newContent = false;
+ ARect currentCrop;
+ uint32_t outTransform;
// Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
// is necessary if the SurfaceTexture queue is in synchronous mode, and we
// cannot tell which mode it is in.
AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
- mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
- createReleaseFence, fenceWait, this);
+ mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &outTransform,
+ &newContent, createReleaseFence, fenceWait, this, &currentCrop);
if (hardwareBuffer) {
mCurrentSlot = slot;
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index fb3e21fc1571..4ec782f6fec0 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -27,6 +27,7 @@ X(ClipPath)
X(ClipRect)
X(ClipRRect)
X(ClipRegion)
+X(ResetClip)
X(DrawPaint)
X(DrawBehind)
X(DrawPath)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index c945f274bbf4..a285462eef74 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -187,6 +187,11 @@ struct ClipRegion final : Op {
SkClipOp op;
void draw(SkCanvas* c, const SkMatrix&) const { c->clipRegion(region, op); }
};
+struct ResetClip final : Op {
+ static const auto kType = Type::ResetClip;
+ ResetClip() {}
+ void draw(SkCanvas* c, const SkMatrix&) const { SkAndroidFrameworkUtils::ResetClip(c); }
+};
struct DrawPaint final : Op {
static const auto kType = Type::DrawPaint;
@@ -662,6 +667,9 @@ void DisplayListData::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
void DisplayListData::clipRegion(const SkRegion& region, SkClipOp op) {
this->push<ClipRegion>(0, region, op);
}
+void DisplayListData::resetClip() {
+ this->push<ResetClip>(0);
+}
void DisplayListData::drawPaint(const SkPaint& paint) {
this->push<DrawPaint>(0, paint);
@@ -969,6 +977,14 @@ void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
fDL->clipRegion(region, op);
this->INHERITED::onClipRegion(region, op);
}
+void RecordingCanvas::onResetClip() {
+ // This is part of "replace op" emulation, but rely on the following intersection
+ // clip to potentially mark the clip as complex. If we are already complex, we do
+ // not reset the complexity so that we don't break the contract that no higher
+ // save point has a complex clip when "not complex".
+ fDL->resetClip();
+ this->INHERITED::onResetClip();
+}
void RecordingCanvas::onDrawPaint(const SkPaint& paint) {
fDL->drawPaint(paint);
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 4fae6a13a25a..212b4e72dcb2 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -97,6 +97,7 @@ private:
void clipRect(const SkRect&, SkClipOp, bool aa);
void clipRRect(const SkRRect&, SkClipOp, bool aa);
void clipRegion(const SkRegion&, SkClipOp);
+ void resetClip();
void drawPaint(const SkPaint&);
void drawBehind(const SkPaint&);
@@ -169,6 +170,7 @@ public:
void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
void onClipRegion(const SkRegion&, SkClipOp) override;
+ void onResetClip() override;
void onDrawPaint(const SkPaint&) override;
void onDrawBehind(const SkPaint&) override;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index d6b6e162757c..53c6db0cdf3a 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -396,6 +396,22 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
return !mCanvas->isClipEmpty();
}
+bool SkiaCanvas::replaceClipRect_deprecated(float left, float top, float right, float bottom) {
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+
+ // Emulated clip rects are not recorded for partial saves, since
+ // partial saves have been removed from the public API.
+ SkAndroidFrameworkUtils::ResetClip(mCanvas);
+ mCanvas->clipRect(rect, SkClipOp::kIntersect);
+ return !mCanvas->isClipEmpty();
+}
+
+bool SkiaCanvas::replaceClipPath_deprecated(const SkPath* path) {
+ SkAndroidFrameworkUtils::ResetClip(mCanvas);
+ mCanvas->clipPath(*path, SkClipOp::kIntersect, true);
+ return !mCanvas->isClipEmpty();
+}
+
// ----------------------------------------------------------------------------
// Canvas state operations: Filters
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index f2d7bda36499..715007cdcd3b 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -94,6 +94,9 @@ public:
virtual bool quickRejectPath(const SkPath& path) const override;
virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
+ virtual bool replaceClipRect_deprecated(float left, float top, float right,
+ float bottom) override;
+ virtual bool replaceClipPath_deprecated(const SkPath* path) override;
virtual PaintFilter* getPaintFilter() override;
virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override;
diff --git a/libs/hwui/canvas/CanvasFrontend.cpp b/libs/hwui/canvas/CanvasFrontend.cpp
index 8f261c83b8d3..dd01a5b15da5 100644
--- a/libs/hwui/canvas/CanvasFrontend.cpp
+++ b/libs/hwui/canvas/CanvasFrontend.cpp
@@ -54,13 +54,10 @@ bool CanvasStateHelper::internalSave(SaveEntry saveEntry) {
return false;
}
-// Assert that the cast from SkClipOp to SkRegion::Op is valid
+// Assert that the cast from SkClipOp to SkRegion::Op is valid.
+// SkClipOp is a subset of SkRegion::Op and only supports difference and intersect.
static_assert(static_cast<int>(SkClipOp::kDifference) == SkRegion::Op::kDifference_Op);
static_assert(static_cast<int>(SkClipOp::kIntersect) == SkRegion::Op::kIntersect_Op);
-static_assert(static_cast<int>(SkClipOp::kUnion_deprecated) == SkRegion::Op::kUnion_Op);
-static_assert(static_cast<int>(SkClipOp::kXOR_deprecated) == SkRegion::Op::kXOR_Op);
-static_assert(static_cast<int>(SkClipOp::kReverseDifference_deprecated) == SkRegion::Op::kReverseDifference_Op);
-static_assert(static_cast<int>(SkClipOp::kReplace_deprecated) == SkRegion::Op::kReplace_Op);
void CanvasStateHelper::internalClipRect(const SkRect& rect, SkClipOp op) {
clip().opRect(rect, transform(), mInitialBounds, (SkRegion::Op)op, false);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 70a558b3d69d..82777646f3a2 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -185,6 +185,12 @@ public:
virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) = 0;
virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
+ // Resets clip to wide open, used to emulate the now-removed SkClipOp::kReplace on
+ // apps with compatibility < P. Canvases for version P and later are restricted to
+ // intersect and difference at the Java level, matching SkClipOp's definition.
+ // NOTE: These functions are deprecated and will be removed in a future release
+ virtual bool replaceClipRect_deprecated(float left, float top, float right, float bottom) = 0;
+ virtual bool replaceClipPath_deprecated(const SkPath* path) = 0;
// filters
virtual PaintFilter* getPaintFilter() = 0;
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index a4cf02812553..0ef80ee10708 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -188,14 +188,10 @@ static jboolean quickRejectPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jl
return result ? JNI_TRUE : JNI_FALSE;
}
-// SkRegion::Op and SkClipOp are numerically identical, so we can freely cast
-// from one to the other (though SkClipOp is destined to become a strict subset)
+// SkClipOp is a strict subset of SkRegion::Op and is castable back and forth for their
+// shared operations (intersect and difference).
static_assert(SkRegion::kDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kDifference), "");
static_assert(SkRegion::kIntersect_Op == static_cast<SkRegion::Op>(SkClipOp::kIntersect), "");
-static_assert(SkRegion::kUnion_Op == static_cast<SkRegion::Op>(SkClipOp::kUnion_deprecated), "");
-static_assert(SkRegion::kXOR_Op == static_cast<SkRegion::Op>(SkClipOp::kXOR_deprecated), "");
-static_assert(SkRegion::kReverseDifference_Op == static_cast<SkRegion::Op>(SkClipOp::kReverseDifference_deprecated), "");
-static_assert(SkRegion::kReplace_Op == static_cast<SkRegion::Op>(SkClipOp::kReplace_deprecated), "");
static jboolean clipRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l, jfloat t,
jfloat r, jfloat b, jint opHandle) {
@@ -203,16 +199,16 @@ static jboolean clipRect(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jfloat l,
SkRegion::Op rgnOp = static_cast<SkRegion::Op>(opHandle);
bool nonEmptyClip;
switch (rgnOp) {
- case SkRegion::Op::kReplace_Op:
- // For now replace can still be handled as an SkClipOp but will be emulated in the
- // future
- [[fallthrough]];
case SkRegion::Op::kIntersect_Op:
case SkRegion::Op::kDifference_Op:
// Intersect and difference are supported clip operations
nonEmptyClip =
get_canvas(canvasHandle)->clipRect(l, t, r, b, static_cast<SkClipOp>(rgnOp));
break;
+ case SkRegion::Op::kReplace_Op:
+ // Replace is emulated to support legacy apps older than P
+ nonEmptyClip = get_canvas(canvasHandle)->replaceClipRect_deprecated(l, t, r, b);
+ break;
default:
// All other operations would expand the clip and are no longer supported,
// so log and skip (to avoid breaking legacy apps).
@@ -230,14 +226,13 @@ static jboolean clipPath(CRITICAL_JNI_PARAMS_COMMA jlong canvasHandle, jlong pat
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
bool nonEmptyClip;
switch (rgnOp) {
- case SkRegion::Op::kReplace_Op:
- // For now replace can still be handled as an SkClipOp but will be emulated in the
- // future
- [[fallthrough]];
case SkRegion::Op::kIntersect_Op:
case SkRegion::Op::kDifference_Op:
nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, static_cast<SkClipOp>(rgnOp));
break;
+ case SkRegion::Op::kReplace_Op:
+ nonEmptyClip = get_canvas(canvasHandle)->replaceClipPath_deprecated(path);
+ break;
default:
ALOGW("Ignoring unsupported clip operation %d", opHandle);
SkRect clipBounds; // ignored
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
index e5d5e75d0f3b..6cae5ffa397f 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.cpp
@@ -24,6 +24,7 @@
namespace android {
struct {
+ jclass clazz;
jmethodID callback;
} gHardwareRendererObserverClassInfo;
@@ -38,14 +39,13 @@ static JNIEnv* getenv(JavaVM* vm) {
HardwareRendererObserver::HardwareRendererObserver(JavaVM* vm, jobject observer,
bool waitForPresentTime)
: uirenderer::FrameMetricsObserver(waitForPresentTime), mVm(vm) {
- mObserverWeak = getenv(mVm)->NewWeakGlobalRef(observer);
- LOG_ALWAYS_FATAL_IF(mObserverWeak == nullptr,
- "unable to create frame stats observer reference");
+ mObserver = getenv(mVm)->NewGlobalRef(observer);
+ LOG_ALWAYS_FATAL_IF(mObserver == nullptr, "unable to create frame stats observer reference");
}
HardwareRendererObserver::~HardwareRendererObserver() {
JNIEnv* env = getenv(mVm);
- env->DeleteWeakGlobalRef(mObserverWeak);
+ env->DeleteGlobalRef(mObserver);
}
bool HardwareRendererObserver::getNextBuffer(JNIEnv* env, jlongArray metrics, int* dropCount) {
@@ -66,6 +66,8 @@ bool HardwareRendererObserver::getNextBuffer(JNIEnv* env, jlongArray metrics, in
}
void HardwareRendererObserver::notify(const int64_t* stats) {
+ if (!mKeepListening) return;
+
FrameMetricsNotification& elem = mRingBuffer[mNextFree];
if (!elem.hasData.load()) {
@@ -77,18 +79,17 @@ void HardwareRendererObserver::notify(const int64_t* stats) {
elem.hasData = true;
JNIEnv* env = getenv(mVm);
- jobject target = env->NewLocalRef(mObserverWeak);
- if (target != nullptr) {
- env->CallVoidMethod(target, gHardwareRendererObserverClassInfo.callback);
- env->DeleteLocalRef(target);
- }
+ mKeepListening = env->CallStaticBooleanMethod(gHardwareRendererObserverClassInfo.clazz,
+ gHardwareRendererObserverClassInfo.callback,
+ mObserver);
} else {
mDroppedReports++;
}
}
static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* env,
- jobject observerObj,
+ jobject /*clazz*/,
+ jobject weakRefThis,
jboolean waitForPresentTime) {
JavaVM* vm = nullptr;
if (env->GetJavaVM(&vm) != JNI_OK) {
@@ -97,7 +98,7 @@ static jlong android_graphics_HardwareRendererObserver_createObserver(JNIEnv* en
}
HardwareRendererObserver* observer =
- new HardwareRendererObserver(vm, observerObj, waitForPresentTime);
+ new HardwareRendererObserver(vm, weakRefThis, waitForPresentTime);
return reinterpret_cast<jlong>(observer);
}
@@ -114,7 +115,7 @@ static jint android_graphics_HardwareRendererObserver_getNextBuffer(JNIEnv* env,
}
static const std::array gMethods = {
- MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Z)J",
+ MAKE_JNI_NATIVE_METHOD("nCreateObserver", "(Ljava/lang/ref/WeakReference;Z)J",
android_graphics_HardwareRendererObserver_createObserver),
MAKE_JNI_NATIVE_METHOD("nGetNextBuffer", "(J[J)I",
android_graphics_HardwareRendererObserver_getNextBuffer),
@@ -123,8 +124,10 @@ static const std::array gMethods = {
int register_android_graphics_HardwareRendererObserver(JNIEnv* env) {
jclass observerClass = FindClassOrDie(env, "android/graphics/HardwareRendererObserver");
- gHardwareRendererObserverClassInfo.callback = GetMethodIDOrDie(env, observerClass,
- "notifyDataAvailable", "()V");
+ gHardwareRendererObserverClassInfo.clazz =
+ reinterpret_cast<jclass>(env->NewGlobalRef(observerClass));
+ gHardwareRendererObserverClassInfo.callback = GetStaticMethodIDOrDie(
+ env, observerClass, "invokeDataAvailable", "(Ljava/lang/ref/WeakReference;)Z");
return RegisterMethodsOrDie(env, "android/graphics/HardwareRendererObserver",
gMethods.data(), gMethods.size());
diff --git a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
index d3076140541b..5ee3e1669502 100644
--- a/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
+++ b/libs/hwui/jni/android_graphics_HardwareRendererObserver.h
@@ -63,7 +63,8 @@ private:
};
JavaVM* const mVm;
- jweak mObserverWeak;
+ jobject mObserver;
+ bool mKeepListening = true;
int mNextFree = 0;
int mNextInQueue = 0;
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index e1da1690518a..944393c63ad6 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -547,9 +547,12 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
// SurfaceView position callback
// ----------------------------------------------------------------------------
-jmethodID gPositionListener_PositionChangedMethod;
-jmethodID gPositionListener_ApplyStretchMethod;
-jmethodID gPositionListener_PositionLostMethod;
+struct {
+ jclass clazz;
+ jmethodID callPositionChanged;
+ jmethodID callApplyStretch;
+ jmethodID callPositionLost;
+} gPositionListener;
static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
jlong renderNodePtr, jobject listener) {
@@ -557,16 +560,16 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
public:
PositionListenerTrampoline(JNIEnv* env, jobject listener) {
env->GetJavaVM(&mVm);
- mWeakRef = env->NewWeakGlobalRef(listener);
+ mListener = env->NewGlobalRef(listener);
}
virtual ~PositionListenerTrampoline() {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
+ jnienv()->DeleteGlobalRef(mListener);
+ mListener = nullptr;
}
virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
- if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
+ if (CC_UNLIKELY(!mListener || !info.updateWindowPositions)) return;
Matrix4 transform;
info.damageAccumulator->computeCurrentTransform(&transform);
@@ -609,7 +612,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
}
virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
- if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
+ if (CC_UNLIKELY(!mListener || (info && !info->updateWindowPositions))) return;
if (mPreviousPosition.isEmpty()) {
return;
@@ -618,18 +621,16 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
ATRACE_NAME("SurfaceView position lost");
JNIEnv* env = jnienv();
- jobject localref = env->NewLocalRef(mWeakRef);
- if (CC_UNLIKELY(!localref)) {
- env->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
- return;
- }
#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
// TODO: Remember why this is synchronous and then make a comment
- env->CallVoidMethod(localref, gPositionListener_PositionLostMethod,
+ jboolean keepListening = env->CallStaticBooleanMethod(
+ gPositionListener.clazz, gPositionListener.callPositionLost, mListener,
info ? info->canvasContext.getFrameNumber() : 0);
+ if (!keepListening) {
+ env->DeleteGlobalRef(mListener);
+ mListener = nullptr;
+ }
#endif
- env->DeleteLocalRef(localref);
}
private:
@@ -684,28 +685,20 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
StretchEffectBehavior::Shader) {
JNIEnv* env = jnienv();
- jobject localref = env->NewLocalRef(mWeakRef);
- if (CC_UNLIKELY(!localref)) {
- env->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
- return;
- }
#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
SkVector stretchDirection = effect->getStretchDirection();
- env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod,
- info.canvasContext.getFrameNumber(),
- result.width,
- result.height,
- stretchDirection.fX,
- stretchDirection.fY,
- effect->maxStretchAmountX,
- effect->maxStretchAmountY,
- childRelativeBounds.left(),
- childRelativeBounds.top(),
- childRelativeBounds.right(),
- childRelativeBounds.bottom());
+ jboolean keepListening = env->CallStaticBooleanMethod(
+ gPositionListener.clazz, gPositionListener.callApplyStretch, mListener,
+ info.canvasContext.getFrameNumber(), result.width, result.height,
+ stretchDirection.fX, stretchDirection.fY, effect->maxStretchAmountX,
+ effect->maxStretchAmountY, childRelativeBounds.left(),
+ childRelativeBounds.top(), childRelativeBounds.right(),
+ childRelativeBounds.bottom());
+ if (!keepListening) {
+ env->DeleteGlobalRef(mListener);
+ mListener = nullptr;
+ }
#endif
- env->DeleteLocalRef(localref);
}
}
@@ -714,14 +707,12 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
ATRACE_NAME("Update SurfaceView position");
JNIEnv* env = jnienv();
- jobject localref = env->NewLocalRef(mWeakRef);
- if (CC_UNLIKELY(!localref)) {
- env->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
- } else {
- env->CallVoidMethod(localref, gPositionListener_PositionChangedMethod,
- frameNumber, left, top, right, bottom);
- env->DeleteLocalRef(localref);
+ jboolean keepListening = env->CallStaticBooleanMethod(
+ gPositionListener.clazz, gPositionListener.callPositionChanged, mListener,
+ frameNumber, left, top, right, bottom);
+ if (!keepListening) {
+ env->DeleteGlobalRef(mListener);
+ mListener = nullptr;
}
// We need to release ourselves here
@@ -729,7 +720,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
}
JavaVM* mVm;
- jobject mWeakRef;
+ jobject mListener;
uirenderer::Rect mPreviousPosition;
};
@@ -754,7 +745,7 @@ static const JNINativeMethod gMethods[] = {
{"nGetAllocatedSize", "(J)I", (void*)android_view_RenderNode_getAllocatedSize},
{"nAddAnimator", "(JJ)V", (void*)android_view_RenderNode_addAnimator},
{"nEndAllAnimators", "(J)V", (void*)android_view_RenderNode_endAllAnimators},
- {"nRequestPositionUpdates", "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V",
+ {"nRequestPositionUpdates", "(JLjava/lang/ref/WeakReference;)V",
(void*)android_view_RenderNode_requestPositionUpdates},
// ----------------------------------------------------------------------------
@@ -852,12 +843,13 @@ static const JNINativeMethod gMethods[] = {
int register_android_view_RenderNode(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
- gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
- "positionChanged", "(JIIII)V");
- gPositionListener_ApplyStretchMethod =
- GetMethodIDOrDie(env, clazz, "applyStretch", "(JFFFFFFFFFF)V");
- gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
- "positionLost", "(J)V");
+ gPositionListener.clazz = MakeGlobalRefOrDie(env, clazz);
+ gPositionListener.callPositionChanged = GetStaticMethodIDOrDie(
+ env, clazz, "callPositionChanged", "(Ljava/lang/ref/WeakReference;JIIII)Z");
+ gPositionListener.callApplyStretch = GetStaticMethodIDOrDie(
+ env, clazz, "callApplyStretch", "(Ljava/lang/ref/WeakReference;JFFFFFFFFFF)Z");
+ gPositionListener.callPositionLost = GetStaticMethodIDOrDie(
+ env, clazz, "callPositionLost", "(Ljava/lang/ref/WeakReference;J)Z");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
index 3580bed45a1f..3f89c0712407 100644
--- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h
+++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
@@ -52,6 +52,8 @@ protected:
mOutput << mIdent << "clipRegion" << std::endl;
}
+ void onResetClip() override { mOutput << mIdent << "resetClip" << std::endl; }
+
void onDrawPaint(const SkPaint&) override { mOutput << mIdent << "drawPaint" << std::endl; }
void onDrawPath(const SkPath&, const SkPaint&) override {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ab9d0b2244e2..bb0b1352c360 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -483,6 +483,12 @@ nsecs_t CanvasContext::draw() {
if (!Properties::isDrawingEnabled() ||
(dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
+ if (auto grContext = getGrContext()) {
+ // Submit to ensure that any texture uploads complete and Skia can
+ // free its staging buffers.
+ grContext->flushAndSubmit();
+ }
+
// Notify the callbacks, even if there's nothing to draw so they aren't waiting
// indefinitely
waitOnFences();
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 8c999c41bf7b..57a7fe3fd466 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -382,7 +382,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
std::vector<sp<RenderNode>> nodes;
nodes.push_back(TestUtils::createSkiaNode(
20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
- canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
+ canvas.replaceClipRect_deprecated(0, -20, 10, 30);
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
}));
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index acd8bced0612..d10e68816d28 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -153,8 +153,7 @@ void SpriteController::doUpdateSprites() {
|| update.state.surfaceHeight < desiredHeight) {
needApplyTransaction = true;
- t.setSize(update.state.surfaceControl,
- desiredWidth, desiredHeight);
+ update.state.surfaceControl->updateDefaultBufferSize(desiredWidth, desiredHeight);
update.state.surfaceWidth = desiredWidth;
update.state.surfaceHeight = desiredHeight;
update.state.surfaceDrawn = false;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 1e8b9521e41e..209903c57d90 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -1084,6 +1084,12 @@ public class Location implements Parcelable {
mExtras = (extras == null) ? null : new Bundle(extras);
}
+ /**
+ * Location equality is provided primarily for test purposes. Comparing locations for equality
+ * in production may indicate incorrect assumptions, and should be avoided whenever possible.
+ *
+ * <p>{@inheritDoc}
+ */
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -1121,7 +1127,17 @@ public class Location implements Parcelable {
&& (!hasBearingAccuracy() || Float.compare(location.mBearingAccuracyDegrees,
mBearingAccuracyDegrees) == 0)
&& Objects.equals(mProvider, location.mProvider)
- && Objects.equals(mExtras, location.mExtras);
+ && areExtrasEqual(mExtras, location.mExtras);
+ }
+
+ private static boolean areExtrasEqual(@Nullable Bundle extras1, @Nullable Bundle extras2) {
+ if ((extras1 == null || extras1.isEmpty()) && (extras2 == null || extras2.isEmpty())) {
+ return true;
+ } else if (extras1 == null || extras2 == null) {
+ return false;
+ } else {
+ return extras1.kindofEquals(extras2);
+ }
}
@Override
diff --git a/location/java/android/location/LocationListener.java b/location/java/android/location/LocationListener.java
index 35a40910e373..031642b752e5 100644
--- a/location/java/android/location/LocationListener.java
+++ b/location/java/android/location/LocationListener.java
@@ -38,9 +38,9 @@ import java.util.concurrent.Executor;
public interface LocationListener {
/**
- * Called when the location has changed. A wakelock is held on behalf on the listener for some
- * brief amount of time as this callback executes. If this callback performs long running
- * operations, it is the client's responsibility to obtain their own wakelock.
+ * Called when the location has changed. A wakelock may be held on behalf on the listener for
+ * some brief amount of time as this callback executes. If this callback performs long running
+ * operations, it is the client's responsibility to obtain their own wakelock if necessary.
*
* @param location the updated location
*/
@@ -48,7 +48,7 @@ public interface LocationListener {
/**
* Called when the location has changed and locations are being delivered in batches. The
- * default implementation calls through to ({@link #onLocationChanged(Location)} with all
+ * default implementation calls through to {@link #onLocationChanged(Location)} with all
* locations in the batch. The list of locations is always guaranteed to be non-empty, and is
* always guaranteed to be ordered from earliest location to latest location (so that the
* earliest location in the batch is at index 0 in the list, and the latest location in the
@@ -76,6 +76,11 @@ public interface LocationListener {
* This callback will never be invoked on Android Q and above, and providers can be considered
* as always in the {@link LocationProvider#AVAILABLE} state.
*
+ * <p class="note">Note that this method only has a default implementation on Android R and
+ * above, and this method must still be overridden in order to run successfully on Android
+ * versions below R. LocationListenerCompat from the compat libraries may be used to avoid the
+ * need to override for older platforms.
+ *
* @deprecated This callback will never be invoked on Android Q and above.
*/
@Deprecated
@@ -84,6 +89,11 @@ public interface LocationListener {
/**
* Called when a provider this listener is registered with becomes enabled.
*
+ * <p class="note">Note that this method only has a default implementation on Android R and
+ * above, and this method must still be overridden in order to run successfully on Android
+ * versions below R. LocationListenerCompat from the compat libraries may be used to avoid the
+ * need to override for older platforms.
+ *
* @param provider the name of the location provider
*/
default void onProviderEnabled(@NonNull String provider) {}
@@ -92,6 +102,11 @@ public interface LocationListener {
* Called when the provider this listener is registered with becomes disabled. If a provider is
* disabled when this listener is registered, this callback will be invoked immediately.
*
+ * <p class="note">Note that this method only has a default implementation on Android R and
+ * above, and this method must still be overridden in order to run successfully on Android
+ * versions below R. LocationListenerCompat from the compat libraries may be used to avoid the
+ * need to override for older platforms.
+ *
* @param provider the name of the location provider
*/
default void onProviderDisabled(@NonNull String provider) {}
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index c827932194ae..cb887f2d523d 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -38,6 +38,17 @@ public abstract class AudioManagerInternal {
public abstract void updateRingerModeAffectedStreamsInternal();
+ /**
+ * Notify the UID of the currently active {@link android.service.voice.HotwordDetectionService}.
+ *
+ * <p>The caller is expected to take care of any performance implications, e.g. by using a
+ * background thread to call this method.</p>
+ *
+ * @param uid UID of the currently active service or {@link android.os.Process#INVALID_UID} if
+ * none.
+ */
+ public abstract void setHotwordDetectionServiceUid(int uid);
+
public abstract void setAccessibilityServiceUids(IntArray uids);
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 321db4e2f050..5bd6891cb035 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1769,6 +1769,13 @@ public class AudioSystem
public static native int setAssistantUid(int uid);
/**
+ * Communicate UID of the current {@link android.service.voice.HotwordDetectionService} to audio
+ * policy service.
+ * @hide
+ */
+ public static native int setHotwordDetectionServiceUid(int uid);
+
+ /**
* @hide
* Communicate UIDs of active accessibility services to audio policy service.
*/
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 37e141537c79..72cddc91f436 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -16,14 +16,14 @@
package android.media.projection;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.hardware.display.VirtualDisplayConfig;
-import android.media.projection.IMediaProjection;
-import android.media.projection.IMediaProjectionCallback;
import android.os.Handler;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -106,7 +106,7 @@ public final class MediaProjection {
if (isSecure) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
}
- final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width,
height, dpi);
builder.setFlags(flags);
if (surface != null) {
@@ -141,7 +141,7 @@ public final class MediaProjection {
public VirtualDisplay createVirtualDisplay(@NonNull String name,
int width, int height, int dpi, int flags, @Nullable Surface surface,
@Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
- final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width,
height, dpi);
builder.setFlags(flags);
if (surface != null) {
@@ -151,6 +151,26 @@ public final class MediaProjection {
}
/**
+ * Constructs a {@link VirtualDisplayConfig.Builder}, which will mirror the contents of a
+ * DisplayArea. The DisplayArea to mirror is from the DisplayArea the caller is launched on.
+ *
+ * @param name The name of the virtual display, must be non-empty.
+ * @param width The width of the virtual display in pixels. Must be greater than 0.
+ * @param height The height of the virtual display in pixels. Must be greater than 0.
+ * @param dpi The density of the virtual display in dpi. Must be greater than 0.
+ * @return a config representing a VirtualDisplay
+ */
+ private VirtualDisplayConfig.Builder buildMirroredVirtualDisplay(@NonNull String name,
+ int width, int height, int dpi) {
+ Context windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(),
+ TYPE_APPLICATION, null /* options */);
+ final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
+ height, dpi);
+ builder.setWindowTokenClientToMirror(windowContext.getWindowContextToken());
+ return builder;
+ }
+
+ /**
* Creates a {@link android.hardware.display.VirtualDisplay} to capture the
* contents of the screen.
*
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 3b0f577d84cb..207ccbee0b50 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -39,8 +39,8 @@ interface ISessionManager {
ISession createSession(String packageName, in ISessionCallback sessionCb, String tag,
in Bundle sessionInfo, int userId);
List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
- MediaSession.Token getMediaKeyEventSession();
- String getMediaKeyEventSessionPackageName();
+ MediaSession.Token getMediaKeyEventSession(String packageName);
+ String getMediaKeyEventSessionPackageName(String packageName);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
@@ -66,7 +66,8 @@ interface ISessionManager {
void addOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
void removeOnMediaKeyEventDispatchedListener(in IOnMediaKeyEventDispatchedListener listener);
void addOnMediaKeyEventSessionChangedListener(
- in IOnMediaKeyEventSessionChangedListener listener);
+ in IOnMediaKeyEventSessionChangedListener listener,
+ String packageName);
void removeOnMediaKeyEventSessionChangedListener(
in IOnMediaKeyEventSessionChangedListener listener);
void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 269b70b667a0..6a50a98018d0 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -196,16 +196,19 @@ public final class MediaSessionManager {
/**
* Gets the media key event session, which would receive a media key event unless specified.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
+ * permission be held by the calling app, or the app has an enabled notification listener
+ * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
+ * a {@link SecurityException}.
+ *
* @return The media key event session, which would receive key events by default, unless
* the caller has specified the target. Can be {@code null}.
- * @hide
*/
- @SystemApi
- @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
@Nullable
public MediaSession.Token getMediaKeyEventSession() {
try {
- return mService.getMediaKeyEventSession();
+ return mService.getMediaKeyEventSession(mContext.getPackageName());
} catch (RemoteException ex) {
Log.e(TAG, "Failed to get media key event session", ex);
}
@@ -214,20 +217,25 @@ public final class MediaSessionManager {
/**
* Gets the package name of the media key event session.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
+ * permission be held by the calling app, or the app has an enabled notification listener
+ * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
+ * a {@link SecurityException}.
+ *
* @return The package name of the media key event session or the last session's media button
- * receiver if the media key event session is {@code null}.
+ * receiver if the media key event session is {@code null}. Returns an empty string
+ * if neither of them exists.
* @see #getMediaKeyEventSession()
- * @hide
*/
- @SystemApi
- @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
@NonNull
public String getMediaKeyEventSessionPackageName() {
try {
- String packageName = mService.getMediaKeyEventSessionPackageName();
+ String packageName = mService.getMediaKeyEventSessionPackageName(
+ mContext.getPackageName());
return (packageName != null) ? packageName : "";
} catch (RemoteException ex) {
- Log.e(TAG, "Failed to get media key event session", ex);
+ Log.e(TAG, "Failed to get media key event session package name", ex);
}
return "";
}
@@ -894,14 +902,16 @@ public final class MediaSessionManager {
}
/**
- * Add a {@link OnMediaKeyEventSessionChangedListener}.
+ * Add a listener to be notified when the media key session is changed.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
+ * permission be held by the calling app, or the app has an enabled notification listener
+ * using the {@link NotificationListenerService} APIs. If none of them applies, it will throw
+ * a {@link SecurityException}.
*
- * @param executor The executor on which the listener should be invoked
+ * @param executor The executor on which the listener should be invoked.
* @param listener A {@link OnMediaKeyEventSessionChangedListener}.
- * @hide
*/
- @SystemApi
- @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
public void addOnMediaKeyEventSessionChangedListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull OnMediaKeyEventSessionChangedListener listener) {
@@ -909,40 +919,37 @@ public final class MediaSessionManager {
Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
+ if (mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
+ mService.addOnMediaKeyEventSessionChangedListener(
+ mOnMediaKeyEventSessionChangedListenerStub, mContext.getPackageName());
+ }
mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
executor.execute(
() -> listener.onMediaKeyEventSessionChanged(
mCurMediaKeyEventSessionPackage, mCurMediaKeyEventSession));
- if (mMediaKeyEventSessionChangedCallbacks.size() == 1) {
- mService.addOnMediaKeyEventSessionChangedListener(
- mOnMediaKeyEventSessionChangedListenerStub);
- }
} catch (RemoteException e) {
- Log.e(TAG, "Failed to set media key listener", e);
+ Log.e(TAG, "Failed to add MediaKeyEventSessionChangedListener", e);
}
}
}
/**
- * Remove a {@link OnMediaKeyEventSessionChangedListener}.
+ * Stop receiving updates on media key event session change on the specified listener.
*
* @param listener A {@link OnMediaKeyEventSessionChangedListener}.
- * @hide
*/
- @SystemApi
- @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
public void removeOnMediaKeyEventSessionChangedListener(
@NonNull OnMediaKeyEventSessionChangedListener listener) {
Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
- mMediaKeyEventSessionChangedCallbacks.remove(listener);
- if (mMediaKeyEventSessionChangedCallbacks.size() == 0) {
+ if (mMediaKeyEventSessionChangedCallbacks.remove(listener) != null
+ && mMediaKeyEventSessionChangedCallbacks.isEmpty()) {
mService.removeOnMediaKeyEventSessionChangedListener(
mOnMediaKeyEventSessionChangedListenerStub);
}
} catch (RemoteException e) {
- Log.e(TAG, "Failed to set media key listener", e);
+ Log.e(TAG, "Failed to remove MediaKeyEventSessionChangedListener", e);
}
}
}
@@ -1124,16 +1131,14 @@ public final class MediaSessionManager {
/**
* Listener to receive changes in the media key event session, which would receive a media key
* event unless specified.
- * @hide
*/
- @SystemApi
public interface OnMediaKeyEventSessionChangedListener {
/**
* Called when the media key session is changed to the given media session. The key event
* session is the media session which would receive key event by default, unless the caller
* has specified the target.
* <p>
- * The session token can be {@link null} if the media button session is unset. In that case,
+ * The session token can be {@code null} if the media button session is unset. In that case,
* packageName will return the package name of the last session's media button receiver, or
* an empty string if the last session didn't set a media button receiver.
*
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 0037b53e541a..6a6a22c1fc0e 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -20,7 +20,10 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.LnbEventType;
+import android.hardware.tv.tuner.LnbPosition;
+import android.hardware.tv.tuner.LnbTone;
+import android.hardware.tv.tuner.LnbVoltage;
import android.media.tv.tuner.Tuner.Result;
import java.lang.annotation.Retention;
@@ -48,39 +51,39 @@ public class Lnb implements AutoCloseable {
/**
* LNB power voltage not set.
*/
- public static final int VOLTAGE_NONE = Constants.LnbVoltage.NONE;
+ public static final int VOLTAGE_NONE = LnbVoltage.NONE;
/**
* LNB power voltage 5V.
*/
- public static final int VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V;
+ public static final int VOLTAGE_5V = LnbVoltage.VOLTAGE_5V;
/**
* LNB power voltage 11V.
*/
- public static final int VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V;
+ public static final int VOLTAGE_11V = LnbVoltage.VOLTAGE_11V;
/**
* LNB power voltage 12V.
*/
- public static final int VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V;
+ public static final int VOLTAGE_12V = LnbVoltage.VOLTAGE_12V;
/**
* LNB power voltage 13V.
*/
- public static final int VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V;
+ public static final int VOLTAGE_13V = LnbVoltage.VOLTAGE_13V;
/**
* LNB power voltage 14V.
*/
- public static final int VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V;
+ public static final int VOLTAGE_14V = LnbVoltage.VOLTAGE_14V;
/**
* LNB power voltage 15V.
*/
- public static final int VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V;
+ public static final int VOLTAGE_15V = LnbVoltage.VOLTAGE_15V;
/**
* LNB power voltage 18V.
*/
- public static final int VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V;
+ public static final int VOLTAGE_18V = LnbVoltage.VOLTAGE_18V;
/**
* LNB power voltage 19V.
*/
- public static final int VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V;
+ public static final int VOLTAGE_19V = LnbVoltage.VOLTAGE_19V;
/** @hide */
@IntDef(prefix = "TONE_",
@@ -91,11 +94,11 @@ public class Lnb implements AutoCloseable {
/**
* LNB tone mode not set.
*/
- public static final int TONE_NONE = Constants.LnbTone.NONE;
+ public static final int TONE_NONE = LnbTone.NONE;
/**
* LNB continuous tone mode.
*/
- public static final int TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS;
+ public static final int TONE_CONTINUOUS = LnbTone.CONTINUOUS;
/** @hide */
@IntDef(prefix = "POSITION_",
@@ -106,15 +109,15 @@ public class Lnb implements AutoCloseable {
/**
* LNB position is not defined.
*/
- public static final int POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED;
+ public static final int POSITION_UNDEFINED = LnbPosition.UNDEFINED;
/**
* Position A of two-band LNBs
*/
- public static final int POSITION_A = Constants.LnbPosition.POSITION_A;
+ public static final int POSITION_A = LnbPosition.POSITION_A;
/**
* Position B of two-band LNBs
*/
- public static final int POSITION_B = Constants.LnbPosition.POSITION_B;
+ public static final int POSITION_B = LnbPosition.POSITION_B;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -126,22 +129,19 @@ public class Lnb implements AutoCloseable {
/**
* Outgoing Diseqc message overflow.
*/
- public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW =
- Constants.LnbEventType.DISEQC_RX_OVERFLOW;
+ public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = LnbEventType.DISEQC_RX_OVERFLOW;
/**
* Outgoing Diseqc message isn't delivered on time.
*/
- public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT =
- Constants.LnbEventType.DISEQC_RX_TIMEOUT;
+ public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = LnbEventType.DISEQC_RX_TIMEOUT;
/**
* Incoming Diseqc message has parity error.
*/
- public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR =
- Constants.LnbEventType.DISEQC_RX_PARITY_ERROR;
+ public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = LnbEventType.DISEQC_RX_PARITY_ERROR;
/**
* LNB is overload.
*/
- public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD;
+ public static final int EVENT_TYPE_LNB_OVERLOAD = LnbEventType.LNB_OVERLOAD;
private static final String TAG = "Lnb";
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 088b3b6d2949..ed5e6eeca34f 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -25,7 +25,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.Context;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.Constant;
+import android.hardware.tv.tuner.Constant64Bit;
+import android.hardware.tv.tuner.FrontendScanType;
import android.media.tv.TvInputService;
import android.media.tv.tuner.dvr.DvrPlayback;
import android.media.tv.tuner.dvr.DvrRecorder;
@@ -85,19 +87,19 @@ public class Tuner implements AutoCloseable {
/**
* Invalid TS packet ID.
*/
- public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+ public static final int INVALID_TS_PID = Constant.INVALID_TS_PID;
/**
* Invalid stream ID.
*/
- public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+ public static final int INVALID_STREAM_ID = Constant.INVALID_STREAM_ID;
/**
* Invalid filter ID.
*/
- public static final int INVALID_FILTER_ID = Constants.Constant.INVALID_FILTER_ID;
+ public static final int INVALID_FILTER_ID = Constant.INVALID_FILTER_ID;
/**
* Invalid AV Sync ID.
*/
- public static final int INVALID_AV_SYNC_ID = Constants.Constant.INVALID_AV_SYNC_ID;
+ public static final int INVALID_AV_SYNC_ID = Constant.INVALID_AV_SYNC_ID;
/**
* Invalid timestamp.
*
@@ -113,7 +115,7 @@ public class Tuner implements AutoCloseable {
* @see android.media.tv.tuner.filter.MmtpRecordEvent#getPts()
*/
public static final long INVALID_TIMESTAMP =
- android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
+ Constant64Bit.INVALID_PRESENTATION_TIME_STAMP;
/**
* Invalid mpu sequence number in MmtpRecordEvent.
*
@@ -123,8 +125,7 @@ public class Tuner implements AutoCloseable {
* @see android.media.tv.tuner.filter.MmtpRecordEvent#getMpuSequenceNumber()
*/
public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM =
- android.hardware.tv.tuner.V1_1.Constants.Constant
- .INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
+ Constant.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM;
/**
* Invalid first macroblock address in MmtpRecordEvent and TsRecordEvent.
*
@@ -135,7 +136,7 @@ public class Tuner implements AutoCloseable {
* @see android.media.tv.tuner.filter.TsRecordEvent#getMbInSlice()
*/
public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
+ Constant.INVALID_FIRST_MACROBLOCK_IN_SLICE;
/**
* Invalid local transport stream id.
*
@@ -144,30 +145,26 @@ public class Tuner implements AutoCloseable {
*
* @see #linkFrontendToCiCam(int)
*/
- public static final int INVALID_LTS_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LTS_ID;
+ public static final int INVALID_LTS_ID = Constant.INVALID_LTS_ID;
/**
* Invalid 64-bit filter ID.
*/
- public static final long INVALID_FILTER_ID_LONG =
- android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
+ public static final long INVALID_FILTER_ID_LONG = Constant64Bit.INVALID_FILTER_ID_64BIT;
/**
* Invalid frequency that is used as the default frontend frequency setting.
*/
public static final int INVALID_FRONTEND_SETTING_FREQUENCY =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
+ Constant.INVALID_FRONTEND_SETTING_FREQUENCY;
/**
* Invalid frontend id.
*/
- public static final int INVALID_FRONTEND_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_ID;
+ public static final int INVALID_FRONTEND_ID = Constant.INVALID_FRONTEND_ID;
/**
* Invalid LNB id.
*
* @hide
*/
- public static final int INVALID_LNB_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LNB_ID;
+ public static final int INVALID_LNB_ID = Constant.INVALID_LNB_ID;
/**
* A void key token. It is used to remove the current key from descrambler.
*
@@ -175,8 +172,7 @@ public class Tuner implements AutoCloseable {
* to use this constant to remove current key before closing MediaCas session.
*/
@NonNull
- public static final byte[] VOID_KEYTOKEN =
- {android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_KEYTOKEN};
+ public static final byte[] VOID_KEYTOKEN = {Constant.INVALID_KEYTOKEN};
/** @hide */
@IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
@@ -185,20 +181,20 @@ public class Tuner implements AutoCloseable {
/**
* Scan type undefined.
*/
- public static final int SCAN_TYPE_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+ public static final int SCAN_TYPE_UNDEFINED = FrontendScanType.SCAN_UNDEFINED;
/**
* Scan type auto.
*
* <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
*/
- public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+ public static final int SCAN_TYPE_AUTO = FrontendScanType.SCAN_AUTO;
/**
* Blind scan.
*
* <p>Frequency range is not specified. The {@link android.media.tv.tuner.Tuner} will scan an
* implementation specific range.
*/
- public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+ public static final int SCAN_TYPE_BLIND = FrontendScanType.SCAN_BLIND;
/** @hide */
@@ -210,31 +206,33 @@ public class Tuner implements AutoCloseable {
/**
* Operation succeeded.
*/
- public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+ public static final int RESULT_SUCCESS = android.hardware.tv.tuner.Result.SUCCESS;
/**
* Operation failed because the corresponding resources are not available.
*/
- public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+ public static final int RESULT_UNAVAILABLE = android.hardware.tv.tuner.Result.UNAVAILABLE;
/**
* Operation failed because the corresponding resources are not initialized.
*/
- public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+ public static final int RESULT_NOT_INITIALIZED =
+ android.hardware.tv.tuner.Result.NOT_INITIALIZED;
/**
* Operation failed because it's not in a valid state.
*/
- public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+ public static final int RESULT_INVALID_STATE = android.hardware.tv.tuner.Result.INVALID_STATE;
/**
* Operation failed because there are invalid arguments.
*/
- public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+ public static final int RESULT_INVALID_ARGUMENT =
+ android.hardware.tv.tuner.Result.INVALID_ARGUMENT;
/**
* Memory allocation failed.
*/
- public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+ public static final int RESULT_OUT_OF_MEMORY = android.hardware.tv.tuner.Result.OUT_OF_MEMORY;
/**
* Operation failed due to unknown errors.
*/
- public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
+ public static final int RESULT_UNKNOWN_ERROR = android.hardware.tv.tuner.Result.UNKNOWN_ERROR;
@@ -257,12 +255,12 @@ public class Tuner implements AutoCloseable {
* DVR for recording.
* @hide
*/
- public static final int DVR_TYPE_RECORD = Constants.DvrType.RECORD;
+ public static final int DVR_TYPE_RECORD = android.hardware.tv.tuner.DvrType.RECORD;
/**
* DVR for playback of recorded programs.
* @hide
*/
- public static final int DVR_TYPE_PLAYBACK = Constants.DvrType.PLAYBACK;
+ public static final int DVR_TYPE_PLAYBACK = android.hardware.tv.tuner.DvrType.PLAYBACK;
static {
try {
@@ -432,6 +430,7 @@ public class Tuner implements AutoCloseable {
mFrontend = tuner.mFrontend;
mIsSharedFrontend = true;
}
+ nativeShareFrontend(mFrontend.mId);
}
/**
@@ -551,6 +550,7 @@ public class Tuner implements AutoCloseable {
* Native method to open frontend of the given ID.
*/
private native Frontend nativeOpenFrontendByHandle(int handle);
+ private native int nativeShareFrontend(int id);
@Result
private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune();
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index a13077c77ced..3a15daf74232 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -17,7 +17,11 @@
package android.media.tv.tuner;
import android.annotation.Nullable;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpFilterType;
+import android.hardware.tv.tuner.DemuxIpFilterType;
+import android.hardware.tv.tuner.DemuxMmtpFilterType;
+import android.hardware.tv.tuner.DemuxTlvFilterType;
+import android.hardware.tv.tuner.DemuxTsFilterType;
import android.media.tv.tuner.filter.Filter;
/**
@@ -37,44 +41,44 @@ public final class TunerUtils {
if (mainType == Filter.TYPE_TS) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxTsFilterType.UNDEFINED;
+ return DemuxTsFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxTsFilterType.SECTION;
+ return DemuxTsFilterType.SECTION;
case Filter.SUBTYPE_PES:
- return Constants.DemuxTsFilterType.PES;
+ return DemuxTsFilterType.PES;
case Filter.SUBTYPE_TS:
- return Constants.DemuxTsFilterType.TS;
+ return DemuxTsFilterType.TS;
case Filter.SUBTYPE_AUDIO:
- return Constants.DemuxTsFilterType.AUDIO;
+ return DemuxTsFilterType.AUDIO;
case Filter.SUBTYPE_VIDEO:
- return Constants.DemuxTsFilterType.VIDEO;
+ return DemuxTsFilterType.VIDEO;
case Filter.SUBTYPE_PCR:
- return Constants.DemuxTsFilterType.PCR;
+ return DemuxTsFilterType.PCR;
case Filter.SUBTYPE_RECORD:
- return Constants.DemuxTsFilterType.RECORD;
+ return DemuxTsFilterType.RECORD;
case Filter.SUBTYPE_TEMI:
- return Constants.DemuxTsFilterType.TEMI;
+ return DemuxTsFilterType.TEMI;
default:
break;
}
} else if (mainType == Filter.TYPE_MMTP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxMmtpFilterType.UNDEFINED;
+ return DemuxMmtpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxMmtpFilterType.SECTION;
+ return DemuxMmtpFilterType.SECTION;
case Filter.SUBTYPE_PES:
- return Constants.DemuxMmtpFilterType.PES;
+ return DemuxMmtpFilterType.PES;
case Filter.SUBTYPE_MMTP:
- return Constants.DemuxMmtpFilterType.MMTP;
+ return DemuxMmtpFilterType.MMTP;
case Filter.SUBTYPE_AUDIO:
- return Constants.DemuxMmtpFilterType.AUDIO;
+ return DemuxMmtpFilterType.AUDIO;
case Filter.SUBTYPE_VIDEO:
- return Constants.DemuxMmtpFilterType.VIDEO;
+ return DemuxMmtpFilterType.VIDEO;
case Filter.SUBTYPE_RECORD:
- return Constants.DemuxMmtpFilterType.RECORD;
+ return DemuxMmtpFilterType.RECORD;
case Filter.SUBTYPE_DOWNLOAD:
- return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ return DemuxMmtpFilterType.DOWNLOAD;
default:
break;
}
@@ -82,43 +86,43 @@ public final class TunerUtils {
} else if (mainType == Filter.TYPE_IP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxIpFilterType.UNDEFINED;
+ return DemuxIpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxIpFilterType.SECTION;
+ return DemuxIpFilterType.SECTION;
case Filter.SUBTYPE_NTP:
- return Constants.DemuxIpFilterType.NTP;
+ return DemuxIpFilterType.NTP;
case Filter.SUBTYPE_IP_PAYLOAD:
- return Constants.DemuxIpFilterType.IP_PAYLOAD;
+ return DemuxIpFilterType.IP_PAYLOAD;
case Filter.SUBTYPE_IP:
- return Constants.DemuxIpFilterType.IP;
+ return DemuxIpFilterType.IP;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
+ return DemuxIpFilterType.PAYLOAD_THROUGH;
default:
break;
}
} else if (mainType == Filter.TYPE_TLV) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxTlvFilterType.UNDEFINED;
+ return DemuxTlvFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxTlvFilterType.SECTION;
+ return DemuxTlvFilterType.SECTION;
case Filter.SUBTYPE_TLV:
- return Constants.DemuxTlvFilterType.TLV;
+ return DemuxTlvFilterType.TLV;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
+ return DemuxTlvFilterType.PAYLOAD_THROUGH;
default:
break;
}
} else if (mainType == Filter.TYPE_ALP) {
switch (subtype) {
case Filter.SUBTYPE_UNDEFINED:
- return Constants.DemuxAlpFilterType.UNDEFINED;
+ return DemuxAlpFilterType.UNDEFINED;
case Filter.SUBTYPE_SECTION:
- return Constants.DemuxAlpFilterType.SECTION;
+ return DemuxAlpFilterType.SECTION;
case Filter.SUBTYPE_PTP:
- return Constants.DemuxAlpFilterType.PTP;
+ return DemuxAlpFilterType.PTP;
case Filter.SUBTYPE_PAYLOAD_THROUGH:
- return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
+ return DemuxAlpFilterType.PAYLOAD_THROUGH;
default:
break;
}
diff --git a/media/java/android/media/tv/tuner/TunerVersionChecker.java b/media/java/android/media/tv/tuner/TunerVersionChecker.java
index b40ba1e763c1..3e13bed0afbd 100644
--- a/media/java/android/media/tv/tuner/TunerVersionChecker.java
+++ b/media/java/android/media/tv/tuner/TunerVersionChecker.java
@@ -38,8 +38,9 @@ public final class TunerVersionChecker {
private TunerVersionChecker() {}
/** @hide */
- @IntDef(prefix = "TUNER_VERSION_", value = {TUNER_VERSION_UNKNOWN, TUNER_VERSION_1_0,
- TUNER_VERSION_1_1})
+ @IntDef(prefix = "TUNER_VERSION_",
+ value = {TUNER_VERSION_UNKNOWN, TUNER_VERSION_1_0, TUNER_VERSION_1_1,
+ TUNER_VERSION_2_0})
@Retention(RetentionPolicy.SOURCE)
public @interface TunerVersion {}
/**
@@ -54,6 +55,10 @@ public final class TunerVersionChecker {
* Tuner version 1.1.
*/
public static final int TUNER_VERSION_1_1 = ((1 << 16) | 1);
+ /**
+ * Tuner version 2.0.
+ */
+ public static final int TUNER_VERSION_2_0 = (2 << 16);
/**
* Get the current running Tuner version.
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 6c2b9e3b99f5..cfd85834048c 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -20,7 +20,6 @@ import android.annotation.BytesLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
@@ -56,25 +55,27 @@ public class DvrPlayback implements AutoCloseable {
/**
* The space of the playback is empty.
*/
- public static final int PLAYBACK_STATUS_EMPTY = Constants.PlaybackStatus.SPACE_EMPTY;
+ public static final int PLAYBACK_STATUS_EMPTY =
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_EMPTY;
/**
* The space of the playback is almost empty.
*
* <p> the threshold is set in {@link DvrSettings}.
*/
public static final int PLAYBACK_STATUS_ALMOST_EMPTY =
- Constants.PlaybackStatus.SPACE_ALMOST_EMPTY;
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_ALMOST_EMPTY;
/**
* The space of the playback is almost full.
*
* <p> the threshold is set in {@link DvrSettings}.
*/
public static final int PLAYBACK_STATUS_ALMOST_FULL =
- Constants.PlaybackStatus.SPACE_ALMOST_FULL;
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_ALMOST_FULL;
/**
* The space of the playback is full.
*/
- public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
+ public static final int PLAYBACK_STATUS_FULL =
+ android.hardware.tv.tuner.PlaybackStatus.SPACE_FULL;
private static final String TAG = "TvTunerPlayback";
diff --git a/media/java/android/media/tv/tuner/dvr/DvrSettings.java b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
index 60f0d1686ea7..0c4af4b6da07 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrSettings.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrSettings.java
@@ -20,7 +20,7 @@ import android.annotation.BytesLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DataFormat;
import android.media.tv.tuner.filter.Filter;
import java.lang.annotation.Retention;
@@ -43,19 +43,19 @@ public class DvrSettings {
/**
* Transport Stream.
*/
- public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+ public static final int DATA_FORMAT_TS = android.hardware.tv.tuner.DataFormat.TS;
/**
* Packetized Elementary Stream.
*/
- public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+ public static final int DATA_FORMAT_PES = android.hardware.tv.tuner.DataFormat.PES;
/**
* Elementary Stream.
*/
- public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+ public static final int DATA_FORMAT_ES = android.hardware.tv.tuner.DataFormat.ES;
/**
* TLV (type-length-value) Stream for SHV
*/
- public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
+ public static final int DATA_FORMAT_SHV_TLV = android.hardware.tv.tuner.DataFormat.SHV_TLV;
@Filter.Status
diff --git a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
index 29bc2c9bd9c1..bac3b5674eab 100644
--- a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxAlpLengthType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -63,17 +63,17 @@ public final class AlpFilterConfiguration extends FilterConfiguration {
/**
* Length type not defined.
*/
- public static final int LENGTH_TYPE_UNDEFINED = Constants.DemuxAlpLengthType.UNDEFINED;
+ public static final int LENGTH_TYPE_UNDEFINED = DemuxAlpLengthType.UNDEFINED;
/**
* Length does NOT include additional header.
*/
public static final int LENGTH_TYPE_WITHOUT_ADDITIONAL_HEADER =
- Constants.DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
+ DemuxAlpLengthType.WITHOUT_ADDITIONAL_HEADER;
/**
* Length includes additional header.
*/
public static final int LENGTH_TYPE_WITH_ADDITIONAL_HEADER =
- Constants.DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
+ DemuxAlpLengthType.WITH_ADDITIONAL_HEADER;
private final int mPacketType;
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index 25457a7bd437..8bcf3d268c3f 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -19,7 +19,6 @@ package android.media.tv.tuner.filter;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_1.Constants;
import android.media.tv.tuner.TunerUtils;
import android.media.tv.tuner.TunerVersionChecker;
@@ -46,55 +45,60 @@ public class AvSettings extends Settings {
/*
* Undefined Video stream type
*/
- public static final int VIDEO_STREAM_TYPE_UNDEFINED = Constants.VideoStreamType.UNDEFINED;
+ public static final int VIDEO_STREAM_TYPE_UNDEFINED =
+ android.hardware.tv.tuner.VideoStreamType.UNDEFINED;
/*
* ITU-T | ISO/IEC Reserved
*/
- public static final int VIDEO_STREAM_TYPE_RESERVED = Constants.VideoStreamType.RESERVED;
+ public static final int VIDEO_STREAM_TYPE_RESERVED =
+ android.hardware.tv.tuner.VideoStreamType.RESERVED;
/*
* ISO/IEC 11172
*/
- public static final int VIDEO_STREAM_TYPE_MPEG1 = Constants.VideoStreamType.MPEG1;
+ public static final int VIDEO_STREAM_TYPE_MPEG1 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG1;
/*
* ITU-T Rec.H.262 and ISO/IEC 13818-2
*/
- public static final int VIDEO_STREAM_TYPE_MPEG2 = Constants.VideoStreamType.MPEG2;
+ public static final int VIDEO_STREAM_TYPE_MPEG2 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG2;
/*
* ISO/IEC 14496-2 (MPEG-4 H.263 based video)
*/
- public static final int VIDEO_STREAM_TYPE_MPEG4P2 = Constants.VideoStreamType.MPEG4P2;
+ public static final int VIDEO_STREAM_TYPE_MPEG4P2 =
+ android.hardware.tv.tuner.VideoStreamType.MPEG4P2;
/*
* ITU-T Rec.H.264 and ISO/IEC 14496-10
*/
- public static final int VIDEO_STREAM_TYPE_AVC = Constants.VideoStreamType.AVC;
+ public static final int VIDEO_STREAM_TYPE_AVC = android.hardware.tv.tuner.VideoStreamType.AVC;
/*
* ITU-T Rec. H.265 and ISO/IEC 23008-2
*/
- public static final int VIDEO_STREAM_TYPE_HEVC = Constants.VideoStreamType.HEVC;
+ public static final int VIDEO_STREAM_TYPE_HEVC = android.hardware.tv.tuner.VideoStreamType.HEVC;
/*
* Microsoft VC.1
*/
- public static final int VIDEO_STREAM_TYPE_VC1 = Constants.VideoStreamType.VC1;
+ public static final int VIDEO_STREAM_TYPE_VC1 = android.hardware.tv.tuner.VideoStreamType.VC1;
/*
* Google VP8
*/
- public static final int VIDEO_STREAM_TYPE_VP8 = Constants.VideoStreamType.VP8;
+ public static final int VIDEO_STREAM_TYPE_VP8 = android.hardware.tv.tuner.VideoStreamType.VP8;
/*
* Google VP9
*/
- public static final int VIDEO_STREAM_TYPE_VP9 = Constants.VideoStreamType.VP9;
+ public static final int VIDEO_STREAM_TYPE_VP9 = android.hardware.tv.tuner.VideoStreamType.VP9;
/*
* AOMedia Video 1
*/
- public static final int VIDEO_STREAM_TYPE_AV1 = Constants.VideoStreamType.AV1;
+ public static final int VIDEO_STREAM_TYPE_AV1 = android.hardware.tv.tuner.VideoStreamType.AV1;
/*
* Chinese Standard
*/
- public static final int VIDEO_STREAM_TYPE_AVS = Constants.VideoStreamType.AVS;
+ public static final int VIDEO_STREAM_TYPE_AVS = android.hardware.tv.tuner.VideoStreamType.AVS;
/*
* New Chinese Standard
*/
- public static final int VIDEO_STREAM_TYPE_AVS2 = Constants.VideoStreamType.AVS2;
+ public static final int VIDEO_STREAM_TYPE_AVS2 = android.hardware.tv.tuner.VideoStreamType.AVS2;
/** @hide */
@IntDef(prefix = "AUDIO_STREAM_TYPE_",
@@ -110,67 +114,73 @@ public class AvSettings extends Settings {
/*
* Undefined Audio stream type
*/
- public static final int AUDIO_STREAM_TYPE_UNDEFINED = Constants.AudioStreamType.UNDEFINED;
+ public static final int AUDIO_STREAM_TYPE_UNDEFINED =
+ android.hardware.tv.tuner.AudioStreamType.UNDEFINED;
/*
* Uncompressed Audio
*/
- public static final int AUDIO_STREAM_TYPE_PCM = Constants.AudioStreamType.PCM;
+ public static final int AUDIO_STREAM_TYPE_PCM = android.hardware.tv.tuner.AudioStreamType.PCM;
/*
* MPEG Audio Layer III versions
*/
- public static final int AUDIO_STREAM_TYPE_MP3 = Constants.AudioStreamType.MP3;
+ public static final int AUDIO_STREAM_TYPE_MP3 = android.hardware.tv.tuner.AudioStreamType.MP3;
/*
* ISO/IEC 11172 Audio
*/
- public static final int AUDIO_STREAM_TYPE_MPEG1 = Constants.AudioStreamType.MPEG1;
+ public static final int AUDIO_STREAM_TYPE_MPEG1 =
+ android.hardware.tv.tuner.AudioStreamType.MPEG1;
/*
* ISO/IEC 13818-3
*/
- public static final int AUDIO_STREAM_TYPE_MPEG2 = Constants.AudioStreamType.MPEG2;
+ public static final int AUDIO_STREAM_TYPE_MPEG2 =
+ android.hardware.tv.tuner.AudioStreamType.MPEG2;
/*
* ISO/IEC 23008-3 (MPEG-H Part 3)
*/
- public static final int AUDIO_STREAM_TYPE_MPEGH = Constants.AudioStreamType.MPEGH;
+ public static final int AUDIO_STREAM_TYPE_MPEGH =
+ android.hardware.tv.tuner.AudioStreamType.MPEGH;
/*
* ISO/IEC 14496-3
*/
- public static final int AUDIO_STREAM_TYPE_AAC = Constants.AudioStreamType.AAC;
+ public static final int AUDIO_STREAM_TYPE_AAC = android.hardware.tv.tuner.AudioStreamType.AAC;
/*
* Dolby Digital
*/
- public static final int AUDIO_STREAM_TYPE_AC3 = Constants.AudioStreamType.AC3;
+ public static final int AUDIO_STREAM_TYPE_AC3 = android.hardware.tv.tuner.AudioStreamType.AC3;
/*
* Dolby Digital Plus
*/
- public static final int AUDIO_STREAM_TYPE_EAC3 = Constants.AudioStreamType.EAC3;
+ public static final int AUDIO_STREAM_TYPE_EAC3 = android.hardware.tv.tuner.AudioStreamType.EAC3;
/*
* Dolby AC-4
*/
- public static final int AUDIO_STREAM_TYPE_AC4 = Constants.AudioStreamType.AC4;
+ public static final int AUDIO_STREAM_TYPE_AC4 = android.hardware.tv.tuner.AudioStreamType.AC4;
/*
* Basic DTS
*/
- public static final int AUDIO_STREAM_TYPE_DTS = Constants.AudioStreamType.DTS;
+ public static final int AUDIO_STREAM_TYPE_DTS = android.hardware.tv.tuner.AudioStreamType.DTS;
/*
* High Resolution DTS
*/
- public static final int AUDIO_STREAM_TYPE_DTS_HD = Constants.AudioStreamType.DTS_HD;
+ public static final int AUDIO_STREAM_TYPE_DTS_HD =
+ android.hardware.tv.tuner.AudioStreamType.DTS_HD;
/*
* Windows Media Audio
*/
- public static final int AUDIO_STREAM_TYPE_WMA = Constants.AudioStreamType.WMA;
+ public static final int AUDIO_STREAM_TYPE_WMA = android.hardware.tv.tuner.AudioStreamType.WMA;
/*
* Opus Interactive Audio Codec
*/
- public static final int AUDIO_STREAM_TYPE_OPUS = Constants.AudioStreamType.OPUS;
+ public static final int AUDIO_STREAM_TYPE_OPUS = android.hardware.tv.tuner.AudioStreamType.OPUS;
/*
* VORBIS Interactive Audio Codec
*/
- public static final int AUDIO_STREAM_TYPE_VORBIS = Constants.AudioStreamType.VORBIS;
+ public static final int AUDIO_STREAM_TYPE_VORBIS =
+ android.hardware.tv.tuner.AudioStreamType.VORBIS;
/*
* SJ/T 11368-2006
*/
- public static final int AUDIO_STREAM_TYPE_DRA = Constants.AudioStreamType.DRA;
+ public static final int AUDIO_STREAM_TYPE_DRA = android.hardware.tv.tuner.AudioStreamType.DRA;
private final boolean mIsPassthrough;
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 3db7047518b8..e7612bc08e50 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -21,7 +21,9 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxFilterMainType;
+import android.hardware.tv.tuner.DemuxFilterMonitorEventType;
+import android.hardware.tv.tuner.DemuxFilterStatus;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
@@ -53,23 +55,23 @@ public class Filter implements AutoCloseable {
/**
* TS filter type.
*/
- public static final int TYPE_TS = Constants.DemuxFilterMainType.TS;
+ public static final int TYPE_TS = DemuxFilterMainType.TS;
/**
* MMTP filter type.
*/
- public static final int TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int TYPE_MMTP = DemuxFilterMainType.MMTP;
/**
* IP filter type.
*/
- public static final int TYPE_IP = Constants.DemuxFilterMainType.IP;
+ public static final int TYPE_IP = DemuxFilterMainType.IP;
/**
* TLV filter type.
*/
- public static final int TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int TYPE_TLV = DemuxFilterMainType.TLV;
/**
* ALP filter type.
*/
- public static final int TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+ public static final int TYPE_ALP = DemuxFilterMainType.ALP;
/** @hide */
@IntDef(prefix = "SUBTYPE_",
@@ -158,7 +160,7 @@ public class Filter implements AutoCloseable {
/**
* The status of a filter that the data in the filter buffer is ready to be read.
*/
- public static final int STATUS_DATA_READY = Constants.DemuxFilterStatus.DATA_READY;
+ public static final int STATUS_DATA_READY = DemuxFilterStatus.DATA_READY;
/**
* The status of a filter that the amount of available data in the filter buffer is at low
* level.
@@ -166,19 +168,19 @@ public class Filter implements AutoCloseable {
* The value is set to 25 percent of the buffer size by default. It can be changed when
* configuring the filter.
*/
- public static final int STATUS_LOW_WATER = Constants.DemuxFilterStatus.LOW_WATER;
+ public static final int STATUS_LOW_WATER = DemuxFilterStatus.LOW_WATER;
/**
* The status of a filter that the amount of available data in the filter buffer is at high
* level.
* The value is set to 75 percent of the buffer size by default. It can be changed when
* configuring the filter.
*/
- public static final int STATUS_HIGH_WATER = Constants.DemuxFilterStatus.HIGH_WATER;
+ public static final int STATUS_HIGH_WATER = DemuxFilterStatus.HIGH_WATER;
/**
* The status of a filter that the filter buffer is full and newly filtered data is being
* discarded.
*/
- public static final int STATUS_OVERFLOW = Constants.DemuxFilterStatus.OVERFLOW;
+ public static final int STATUS_OVERFLOW = DemuxFilterStatus.OVERFLOW;
/** @hide */
@IntDef(flag = true,
@@ -192,17 +194,17 @@ public class Filter implements AutoCloseable {
* Content’s scrambling status is unknown
*/
public static final int SCRAMBLING_STATUS_UNKNOWN =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.UNKNOWN;
+ android.hardware.tv.tuner.ScramblingStatus.UNKNOWN;
/**
* Content is not scrambled.
*/
public static final int SCRAMBLING_STATUS_NOT_SCRAMBLED =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.NOT_SCRAMBLED;
+ android.hardware.tv.tuner.ScramblingStatus.NOT_SCRAMBLED;
/**
* Content is scrambled.
*/
public static final int SCRAMBLING_STATUS_SCRAMBLED =
- android.hardware.tv.tuner.V1_1.Constants.ScramblingStatus.SCRAMBLED;
+ android.hardware.tv.tuner.ScramblingStatus.SCRAMBLED;
/** @hide */
@IntDef(flag = true,
@@ -215,12 +217,11 @@ public class Filter implements AutoCloseable {
* Monitor scrambling status change.
*/
public static final int MONITOR_EVENT_SCRAMBLING_STATUS =
- android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
+ DemuxFilterMonitorEventType.SCRAMBLING_STATUS;
/**
* Monitor ip cid change.
*/
- public static final int MONITOR_EVENT_IP_CID_CHANGE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxFilterMonitorEventType.IP_CID_CHANGE;
+ public static final int MONITOR_EVENT_IP_CID_CHANGE = DemuxFilterMonitorEventType.IP_CID_CHANGE;
private static final String TAG = "Filter";
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 4b69807e5078..657846486158 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.SystemApi;
+import android.hardware.tv.tuner.Constant;
import android.media.tv.tuner.TunerVersionChecker;
/**
@@ -33,8 +34,7 @@ public final class IpFilterConfiguration extends FilterConfiguration {
/**
* Undefined filter type.
*/
- public static final int INVALID_IP_FILTER_CONTEXT_ID =
- android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_IP_FILTER_CONTEXT_ID;
+ public static final int INVALID_IP_FILTER_CONTEXT_ID = Constant.INVALID_IP_FILTER_CONTEXT_ID;
private final byte[] mSrcIpAddress;
private final byte[] mDstIpAddress;
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index 91992afadb3e..cd703651f2fa 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -19,7 +19,10 @@ package android.media.tv.tuner.filter;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.DemuxRecordScIndexType;
+import android.hardware.tv.tuner.DemuxScHevcIndex;
+import android.hardware.tv.tuner.DemuxScIndex;
+import android.hardware.tv.tuner.DemuxTsIndex;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
@@ -57,88 +60,80 @@ public class RecordSettings extends Settings {
/**
* TS index FIRST_PACKET.
*/
- public static final int TS_INDEX_FIRST_PACKET = Constants.DemuxTsIndex.FIRST_PACKET;
+ public static final int TS_INDEX_FIRST_PACKET = DemuxTsIndex.FIRST_PACKET;
/**
* TS index PAYLOAD_UNIT_START_INDICATOR.
*/
public static final int TS_INDEX_PAYLOAD_UNIT_START_INDICATOR =
- Constants.DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
+ DemuxTsIndex.PAYLOAD_UNIT_START_INDICATOR;
/**
* TS index CHANGE_TO_NOT_SCRAMBLED.
*/
- public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
+ public static final int TS_INDEX_CHANGE_TO_NOT_SCRAMBLED = DemuxTsIndex.CHANGE_TO_NOT_SCRAMBLED;
/**
* TS index CHANGE_TO_EVEN_SCRAMBLED.
*/
public static final int TS_INDEX_CHANGE_TO_EVEN_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
+ DemuxTsIndex.CHANGE_TO_EVEN_SCRAMBLED;
/**
* TS index CHANGE_TO_ODD_SCRAMBLED.
*/
- public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED =
- Constants.DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
+ public static final int TS_INDEX_CHANGE_TO_ODD_SCRAMBLED = DemuxTsIndex.CHANGE_TO_ODD_SCRAMBLED;
/**
* TS index DISCONTINUITY_INDICATOR.
*/
- public static final int TS_INDEX_DISCONTINUITY_INDICATOR =
- Constants.DemuxTsIndex.DISCONTINUITY_INDICATOR;
+ public static final int TS_INDEX_DISCONTINUITY_INDICATOR = DemuxTsIndex.DISCONTINUITY_INDICATOR;
/**
* TS index RANDOM_ACCESS_INDICATOR.
*/
- public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR =
- Constants.DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
+ public static final int TS_INDEX_RANDOM_ACCESS_INDICATOR = DemuxTsIndex.RANDOM_ACCESS_INDICATOR;
/**
* TS index PRIORITY_INDICATOR.
*/
- public static final int TS_INDEX_PRIORITY_INDICATOR = Constants.DemuxTsIndex.PRIORITY_INDICATOR;
+ public static final int TS_INDEX_PRIORITY_INDICATOR = DemuxTsIndex.PRIORITY_INDICATOR;
/**
* TS index PCR_FLAG.
*/
- public static final int TS_INDEX_PCR_FLAG = Constants.DemuxTsIndex.PCR_FLAG;
+ public static final int TS_INDEX_PCR_FLAG = DemuxTsIndex.PCR_FLAG;
/**
* TS index OPCR_FLAG.
*/
- public static final int TS_INDEX_OPCR_FLAG = Constants.DemuxTsIndex.OPCR_FLAG;
+ public static final int TS_INDEX_OPCR_FLAG = DemuxTsIndex.OPCR_FLAG;
/**
* TS index SPLICING_POINT_FLAG.
*/
- public static final int TS_INDEX_SPLICING_POINT_FLAG =
- Constants.DemuxTsIndex.SPLICING_POINT_FLAG;
+ public static final int TS_INDEX_SPLICING_POINT_FLAG = DemuxTsIndex.SPLICING_POINT_FLAG;
/**
* TS index PRIVATE_DATA.
*/
- public static final int TS_INDEX_PRIVATE_DATA = Constants.DemuxTsIndex.PRIVATE_DATA;
+ public static final int TS_INDEX_PRIVATE_DATA = DemuxTsIndex.PRIVATE_DATA;
/**
* TS index ADAPTATION_EXTENSION_FLAG.
*/
public static final int TS_INDEX_ADAPTATION_EXTENSION_FLAG =
- Constants.DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
+ DemuxTsIndex.ADAPTATION_EXTENSION_FLAG;
/**
* Index the address of MPEG Media Transport Packet Table(MPT).
*/
- public static final int MPT_INDEX_MPT =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_MPT;
+ public static final int MPT_INDEX_MPT = DemuxTsIndex.MPT_INDEX_MPT;
/**
* Index the address of Video.
*/
- public static final int MPT_INDEX_VIDEO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_VIDEO;
+ public static final int MPT_INDEX_VIDEO = DemuxTsIndex.MPT_INDEX_VIDEO;
/**
* Index the address of Audio.
*/
- public static final int MPT_INDEX_AUDIO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_AUDIO;
+ public static final int MPT_INDEX_AUDIO = DemuxTsIndex.MPT_INDEX_AUDIO;
/**
* Index to indicate this is a target of timestamp extraction for video.
*/
public static final int MPT_INDEX_TIMESTAMP_TARGET_VIDEO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
+ DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_VIDEO;
/**
* Index to indicate this is a target of timestamp extraction for audio.
*/
public static final int MPT_INDEX_TIMESTAMP_TARGET_AUDIO =
- android.hardware.tv.tuner.V1_1.Constants.DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
+ DemuxTsIndex.MPT_INDEX_TIMESTAMP_TARGET_AUDIO;
/** @hide */
@@ -150,15 +145,15 @@ public class RecordSettings extends Settings {
/**
* Start Code Index is not used.
*/
- public static final int INDEX_TYPE_NONE = Constants.DemuxRecordScIndexType.NONE;
+ public static final int INDEX_TYPE_NONE = DemuxRecordScIndexType.NONE;
/**
* Start Code index.
*/
- public static final int INDEX_TYPE_SC = Constants.DemuxRecordScIndexType.SC;
+ public static final int INDEX_TYPE_SC = DemuxRecordScIndexType.SC;
/**
* Start Code index for HEVC.
*/
- public static final int INDEX_TYPE_SC_HEVC = Constants.DemuxRecordScIndexType.SC_HEVC;
+ public static final int INDEX_TYPE_SC_HEVC = DemuxRecordScIndexType.SC_HEVC;
/**
* Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
@@ -176,44 +171,39 @@ public class RecordSettings extends Settings {
/**
* SC index for a new I-frame.
*/
- public static final int SC_INDEX_I_FRAME = Constants.DemuxScIndex.I_FRAME;
+ public static final int SC_INDEX_I_FRAME = DemuxScIndex.I_FRAME;
/**
* SC index for a new P-frame.
*/
- public static final int SC_INDEX_P_FRAME = Constants.DemuxScIndex.P_FRAME;
+ public static final int SC_INDEX_P_FRAME = DemuxScIndex.P_FRAME;
/**
* SC index for a new B-frame.
*/
- public static final int SC_INDEX_B_FRAME = Constants.DemuxScIndex.B_FRAME;
+ public static final int SC_INDEX_B_FRAME = DemuxScIndex.B_FRAME;
/**
* SC index for a new sequence.
*/
- public static final int SC_INDEX_SEQUENCE = Constants.DemuxScIndex.SEQUENCE;
+ public static final int SC_INDEX_SEQUENCE = DemuxScIndex.SEQUENCE;
/**
* All blocks are coded as I blocks.
*/
- public static final int SC_INDEX_I_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.I_SLICE;
+ public static final int SC_INDEX_I_SLICE = DemuxScIndex.I_SLICE;
/**
* Blocks are coded as I or P blocks.
*/
- public static final int SC_INDEX_P_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.P_SLICE;
+ public static final int SC_INDEX_P_SLICE = DemuxScIndex.P_SLICE;
/**
* Blocks are coded as I, P or B blocks.
*/
- public static final int SC_INDEX_B_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.B_SLICE;
+ public static final int SC_INDEX_B_SLICE = DemuxScIndex.B_SLICE;
/**
* A so-called switching I slice that is coded.
*/
- public static final int SC_INDEX_SI_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SI_SLICE;
+ public static final int SC_INDEX_SI_SLICE = DemuxScIndex.SI_SLICE;
/**
* A so-called switching P slice that is coded.
*/
- public static final int SC_INDEX_SP_SLICE =
- android.hardware.tv.tuner.V1_1.Constants.DemuxScIndex.SP_SLICE;
+ public static final int SC_INDEX_SP_SLICE = DemuxScIndex.SP_SLICE;
/**
* Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
@@ -231,41 +221,35 @@ public class RecordSettings extends Settings {
/**
* SC HEVC index SPS.
*/
- public static final int SC_HEVC_INDEX_SPS = Constants.DemuxScHevcIndex.SPS;
+ public static final int SC_HEVC_INDEX_SPS = DemuxScHevcIndex.SPS;
/**
* SC HEVC index AUD.
*/
- public static final int SC_HEVC_INDEX_AUD = Constants.DemuxScHevcIndex.AUD;
+ public static final int SC_HEVC_INDEX_AUD = DemuxScHevcIndex.AUD;
/**
* SC HEVC index SLICE_CE_BLA_W_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP =
- Constants.DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
+ public static final int SC_HEVC_INDEX_SLICE_CE_BLA_W_LP = DemuxScHevcIndex.SLICE_CE_BLA_W_LP;
/**
* SC HEVC index SLICE_BLA_W_RADL.
*/
- public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL =
- Constants.DemuxScHevcIndex.SLICE_BLA_W_RADL;
+ public static final int SC_HEVC_INDEX_SLICE_BLA_W_RADL = DemuxScHevcIndex.SLICE_BLA_W_RADL;
/**
* SC HEVC index SLICE_BLA_N_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP =
- Constants.DemuxScHevcIndex.SLICE_BLA_N_LP;
+ public static final int SC_HEVC_INDEX_SLICE_BLA_N_LP = DemuxScHevcIndex.SLICE_BLA_N_LP;
/**
* SC HEVC index SLICE_IDR_W_RADL.
*/
- public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL =
- Constants.DemuxScHevcIndex.SLICE_IDR_W_RADL;
+ public static final int SC_HEVC_INDEX_SLICE_IDR_W_RADL = DemuxScHevcIndex.SLICE_IDR_W_RADL;
/**
* SC HEVC index SLICE_IDR_N_LP.
*/
- public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP =
- Constants.DemuxScHevcIndex.SLICE_IDR_N_LP;
+ public static final int SC_HEVC_INDEX_SLICE_IDR_N_LP = DemuxScHevcIndex.SLICE_IDR_N_LP;
/**
* SC HEVC index SLICE_TRAIL_CRA.
*/
- public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA =
- Constants.DemuxScHevcIndex.SLICE_TRAIL_CRA;
+ public static final int SC_HEVC_INDEX_SLICE_TRAIL_CRA = DemuxScHevcIndex.SLICE_TRAIL_CRA;
/**
* @hide
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index b2c3fd243de0..768f1d389a32 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -20,7 +20,9 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAnalogAftFlag;
+import android.hardware.tv.tuner.FrontendAnalogSifStandard;
+import android.hardware.tv.tuner.FrontendAnalogType;
import android.media.tv.tuner.TunerVersionChecker;
import java.lang.annotation.Retention;
@@ -45,39 +47,39 @@ public class AnalogFrontendSettings extends FrontendSettings {
/**
* Undefined analog signal type.
*/
- public static final int SIGNAL_TYPE_UNDEFINED = Constants.FrontendAnalogType.UNDEFINED;
+ public static final int SIGNAL_TYPE_UNDEFINED = FrontendAnalogType.UNDEFINED;
/**
* AUTO analog signal type.
*/
- public static final int SIGNAL_TYPE_AUTO = Constants.FrontendAnalogType.AUTO;
+ public static final int SIGNAL_TYPE_AUTO = FrontendAnalogType.AUTO;
/**
* PAL analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL = Constants.FrontendAnalogType.PAL;
+ public static final int SIGNAL_TYPE_PAL = FrontendAnalogType.PAL;
/**
* PAL M analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_M = Constants.FrontendAnalogType.PAL_M;
+ public static final int SIGNAL_TYPE_PAL_M = FrontendAnalogType.PAL_M;
/**
* PAL N analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_N = Constants.FrontendAnalogType.PAL_N;
+ public static final int SIGNAL_TYPE_PAL_N = FrontendAnalogType.PAL_N;
/**
* PAL 60 analog signal type.
*/
- public static final int SIGNAL_TYPE_PAL_60 = Constants.FrontendAnalogType.PAL_60;
+ public static final int SIGNAL_TYPE_PAL_60 = FrontendAnalogType.PAL_60;
/**
* NTSC analog signal type.
*/
- public static final int SIGNAL_TYPE_NTSC = Constants.FrontendAnalogType.NTSC;
+ public static final int SIGNAL_TYPE_NTSC = FrontendAnalogType.NTSC;
/**
* NTSC 443 analog signal type.
*/
- public static final int SIGNAL_TYPE_NTSC_443 = Constants.FrontendAnalogType.NTSC_443;
+ public static final int SIGNAL_TYPE_NTSC_443 = FrontendAnalogType.NTSC_443;
/**
* SECM analog signal type.
*/
- public static final int SIGNAL_TYPE_SECAM = Constants.FrontendAnalogType.SECAM;
+ public static final int SIGNAL_TYPE_SECAM = FrontendAnalogType.SECAM;
/** @hide */
@IntDef(flag = true,
@@ -91,79 +93,79 @@ public class AnalogFrontendSettings extends FrontendSettings {
/**
* Undefined Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_UNDEFINED = Constants.FrontendAnalogSifStandard.UNDEFINED;
+ public static final int SIF_UNDEFINED = FrontendAnalogSifStandard.UNDEFINED;
/**
* Audo Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_AUTO = Constants.FrontendAnalogSifStandard.AUTO;
+ public static final int SIF_AUTO = FrontendAnalogSifStandard.AUTO;
/**
* BG Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG = Constants.FrontendAnalogSifStandard.BG;
+ public static final int SIF_BG = FrontendAnalogSifStandard.BG;
/**
* BG-A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG_A2 = Constants.FrontendAnalogSifStandard.BG_A2;
+ public static final int SIF_BG_A2 = FrontendAnalogSifStandard.BG_A2;
/**
* BG-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_BG_NICAM = Constants.FrontendAnalogSifStandard.BG_NICAM;
+ public static final int SIF_BG_NICAM = FrontendAnalogSifStandard.BG_NICAM;
/**
* I Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_I = Constants.FrontendAnalogSifStandard.I;
+ public static final int SIF_I = FrontendAnalogSifStandard.I;
/**
* DK Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK = Constants.FrontendAnalogSifStandard.DK;
+ public static final int SIF_DK = FrontendAnalogSifStandard.DK;
/**
* DK1 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK1_A2 = Constants.FrontendAnalogSifStandard.DK1_A2;
+ public static final int SIF_DK1_A2 = FrontendAnalogSifStandard.DK1_A2;
/**
* DK2 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK2_A2 = Constants.FrontendAnalogSifStandard.DK2_A2;
+ public static final int SIF_DK2_A2 = FrontendAnalogSifStandard.DK2_A2;
/**
* DK3 A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK3_A2 = Constants.FrontendAnalogSifStandard.DK3_A2;
+ public static final int SIF_DK3_A2 = FrontendAnalogSifStandard.DK3_A2;
/**
* DK-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_DK_NICAM = Constants.FrontendAnalogSifStandard.DK_NICAM;
+ public static final int SIF_DK_NICAM = FrontendAnalogSifStandard.DK_NICAM;
/**
* L Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L = Constants.FrontendAnalogSifStandard.L;
+ public static final int SIF_L = FrontendAnalogSifStandard.L;
/**
* M Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M = Constants.FrontendAnalogSifStandard.M;
+ public static final int SIF_M = FrontendAnalogSifStandard.M;
/**
* M-BTSC Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_BTSC = Constants.FrontendAnalogSifStandard.M_BTSC;
+ public static final int SIF_M_BTSC = FrontendAnalogSifStandard.M_BTSC;
/**
* M-A2 Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_A2 = Constants.FrontendAnalogSifStandard.M_A2;
+ public static final int SIF_M_A2 = FrontendAnalogSifStandard.M_A2;
/**
* M-EIAJ Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_M_EIAJ = Constants.FrontendAnalogSifStandard.M_EIAJ;
+ public static final int SIF_M_EIAJ = FrontendAnalogSifStandard.M_EIAJ;
/**
* I-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_I_NICAM = Constants.FrontendAnalogSifStandard.I_NICAM;
+ public static final int SIF_I_NICAM = FrontendAnalogSifStandard.I_NICAM;
/**
* L-NICAM Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L_NICAM = Constants.FrontendAnalogSifStandard.L_NICAM;
+ public static final int SIF_L_NICAM = FrontendAnalogSifStandard.L_NICAM;
/**
* L-PRIME Analog Standard Interchange Format (SIF).
*/
- public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME;
+ public static final int SIF_L_PRIME = FrontendAnalogSifStandard.L_PRIME;
/** @hide */
@IntDef(prefix = "AFT_FLAG_",
@@ -174,18 +176,15 @@ public class AnalogFrontendSettings extends FrontendSettings {
/**
* Aft flag is not defined.
*/
- public static final int AFT_FLAG_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.UNDEFINED;
+ public static final int AFT_FLAG_UNDEFINED = FrontendAnalogAftFlag.UNDEFINED;
/**
* Aft flag is set true.
*/
- public static final int AFT_FLAG_TRUE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_TRUE;
+ public static final int AFT_FLAG_TRUE = FrontendAnalogAftFlag.AFT_TRUE;
/**
* Aft flag is not set.
*/
- public static final int AFT_FLAG_FALSE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_FALSE;
+ public static final int AFT_FLAG_FALSE = FrontendAnalogAftFlag.AFT_FALSE;
private final int mSignalType;
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index ed1ce2d6a566..52a20cb8b815 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -20,7 +20,12 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtsc3Bandwidth;
+import android.hardware.tv.tuner.FrontendAtsc3CodeRate;
+import android.hardware.tv.tuner.FrontendAtsc3DemodOutputFormat;
+import android.hardware.tv.tuner.FrontendAtsc3Fec;
+import android.hardware.tv.tuner.FrontendAtsc3Modulation;
+import android.hardware.tv.tuner.FrontendAtsc3TimeInterleaveMode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,27 +49,23 @@ public class Atsc3FrontendSettings extends FrontendSettings {
/**
* Bandwidth not defined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- Constants.FrontendAtsc3Bandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendAtsc3Bandwidth.UNDEFINED;
/**
* Hardware is able to detect and set bandwidth automatically
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendAtsc3Bandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendAtsc3Bandwidth.AUTO;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_6MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_6MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_6MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_7MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_7MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_7MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_BANDWIDTH_8MHZ =
- Constants.FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_BANDWIDTH_8MHZ = FrontendAtsc3Bandwidth.BANDWIDTH_8MHZ;
/** @hide */
@@ -80,35 +81,35 @@ public class Atsc3FrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendAtsc3Modulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendAtsc3Modulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically.
*/
- public static final int MODULATION_AUTO = Constants.FrontendAtsc3Modulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendAtsc3Modulation.AUTO;
/**
* QPSK modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendAtsc3Modulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendAtsc3Modulation.MOD_QPSK;
/**
* 16QAM modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendAtsc3Modulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendAtsc3Modulation.MOD_16QAM;
/**
* 64QAM modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendAtsc3Modulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendAtsc3Modulation.MOD_64QAM;
/**
* 256QAM modulation.
*/
- public static final int MODULATION_MOD_256QAM = Constants.FrontendAtsc3Modulation.MOD_256QAM;
+ public static final int MODULATION_MOD_256QAM = FrontendAtsc3Modulation.MOD_256QAM;
/**
* 1024QAM modulation.
*/
- public static final int MODULATION_MOD_1024QAM = Constants.FrontendAtsc3Modulation.MOD_1024QAM;
+ public static final int MODULATION_MOD_1024QAM = FrontendAtsc3Modulation.MOD_1024QAM;
/**
* 4096QAM modulation.
*/
- public static final int MODULATION_MOD_4096QAM = Constants.FrontendAtsc3Modulation.MOD_4096QAM;
+ public static final int MODULATION_MOD_4096QAM = FrontendAtsc3Modulation.MOD_4096QAM;
/** @hide */
@@ -123,22 +124,19 @@ public class Atsc3FrontendSettings extends FrontendSettings {
* Time interleave mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- Constants.FrontendAtsc3TimeInterleaveMode.UNDEFINED;
+ FrontendAtsc3TimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set Time Interleave Mode automatically.
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- Constants.FrontendAtsc3TimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendAtsc3TimeInterleaveMode.AUTO;
/**
* CTI Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_CTI =
- Constants.FrontendAtsc3TimeInterleaveMode.CTI;
+ public static final int TIME_INTERLEAVE_MODE_CTI = FrontendAtsc3TimeInterleaveMode.CTI;
/**
* HTI Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_HTI =
- Constants.FrontendAtsc3TimeInterleaveMode.HTI;
+ public static final int TIME_INTERLEAVE_MODE_HTI = FrontendAtsc3TimeInterleaveMode.HTI;
/** @hide */
@@ -153,59 +151,59 @@ public class Atsc3FrontendSettings extends FrontendSettings {
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendAtsc3CodeRate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendAtsc3CodeRate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically
*/
- public static final int CODERATE_AUTO = Constants.FrontendAtsc3CodeRate.AUTO;
+ public static final int CODERATE_AUTO = FrontendAtsc3CodeRate.AUTO;
/**
* 2/15 code rate.
*/
- public static final int CODERATE_2_15 = Constants.FrontendAtsc3CodeRate.CODERATE_2_15;
+ public static final int CODERATE_2_15 = FrontendAtsc3CodeRate.CODERATE_2_15;
/**
* 3/15 code rate.
*/
- public static final int CODERATE_3_15 = Constants.FrontendAtsc3CodeRate.CODERATE_3_15;
+ public static final int CODERATE_3_15 = FrontendAtsc3CodeRate.CODERATE_3_15;
/**
* 4/15 code rate.
*/
- public static final int CODERATE_4_15 = Constants.FrontendAtsc3CodeRate.CODERATE_4_15;
+ public static final int CODERATE_4_15 = FrontendAtsc3CodeRate.CODERATE_4_15;
/**
* 5/15 code rate.
*/
- public static final int CODERATE_5_15 = Constants.FrontendAtsc3CodeRate.CODERATE_5_15;
+ public static final int CODERATE_5_15 = FrontendAtsc3CodeRate.CODERATE_5_15;
/**
* 6/15 code rate.
*/
- public static final int CODERATE_6_15 = Constants.FrontendAtsc3CodeRate.CODERATE_6_15;
+ public static final int CODERATE_6_15 = FrontendAtsc3CodeRate.CODERATE_6_15;
/**
* 7/15 code rate.
*/
- public static final int CODERATE_7_15 = Constants.FrontendAtsc3CodeRate.CODERATE_7_15;
+ public static final int CODERATE_7_15 = FrontendAtsc3CodeRate.CODERATE_7_15;
/**
* 8/15 code rate.
*/
- public static final int CODERATE_8_15 = Constants.FrontendAtsc3CodeRate.CODERATE_8_15;
+ public static final int CODERATE_8_15 = FrontendAtsc3CodeRate.CODERATE_8_15;
/**
* 9/15 code rate.
*/
- public static final int CODERATE_9_15 = Constants.FrontendAtsc3CodeRate.CODERATE_9_15;
+ public static final int CODERATE_9_15 = FrontendAtsc3CodeRate.CODERATE_9_15;
/**
* 10/15 code rate.
*/
- public static final int CODERATE_10_15 = Constants.FrontendAtsc3CodeRate.CODERATE_10_15;
+ public static final int CODERATE_10_15 = FrontendAtsc3CodeRate.CODERATE_10_15;
/**
* 11/15 code rate.
*/
- public static final int CODERATE_11_15 = Constants.FrontendAtsc3CodeRate.CODERATE_11_15;
+ public static final int CODERATE_11_15 = FrontendAtsc3CodeRate.CODERATE_11_15;
/**
* 12/15 code rate.
*/
- public static final int CODERATE_12_15 = Constants.FrontendAtsc3CodeRate.CODERATE_12_15;
+ public static final int CODERATE_12_15 = FrontendAtsc3CodeRate.CODERATE_12_15;
/**
* 13/15 code rate.
*/
- public static final int CODERATE_13_15 = Constants.FrontendAtsc3CodeRate.CODERATE_13_15;
+ public static final int CODERATE_13_15 = FrontendAtsc3CodeRate.CODERATE_13_15;
/** @hide */
@@ -219,35 +217,35 @@ public class Atsc3FrontendSettings extends FrontendSettings {
/**
* Forward Error Correction undefined.
*/
- public static final int FEC_UNDEFINED = Constants.FrontendAtsc3Fec.UNDEFINED;
+ public static final int FEC_UNDEFINED = FrontendAtsc3Fec.UNDEFINED;
/**
* Hardware is able to detect and set FEC automatically
*/
- public static final int FEC_AUTO = Constants.FrontendAtsc3Fec.AUTO;
+ public static final int FEC_AUTO = FrontendAtsc3Fec.AUTO;
/**
* BCH LDPC 16K Forward Error Correction
*/
- public static final int FEC_BCH_LDPC_16K = Constants.FrontendAtsc3Fec.BCH_LDPC_16K;
+ public static final int FEC_BCH_LDPC_16K = FrontendAtsc3Fec.BCH_LDPC_16K;
/**
* BCH LDPC 64K Forward Error Correction
*/
- public static final int FEC_BCH_LDPC_64K = Constants.FrontendAtsc3Fec.BCH_LDPC_64K;
+ public static final int FEC_BCH_LDPC_64K = FrontendAtsc3Fec.BCH_LDPC_64K;
/**
* CRC LDPC 16K Forward Error Correction
*/
- public static final int FEC_CRC_LDPC_16K = Constants.FrontendAtsc3Fec.CRC_LDPC_16K;
+ public static final int FEC_CRC_LDPC_16K = FrontendAtsc3Fec.CRC_LDPC_16K;
/**
* CRC LDPC 64K Forward Error Correction
*/
- public static final int FEC_CRC_LDPC_64K = Constants.FrontendAtsc3Fec.CRC_LDPC_64K;
+ public static final int FEC_CRC_LDPC_64K = FrontendAtsc3Fec.CRC_LDPC_64K;
/**
* LDPC 16K Forward Error Correction
*/
- public static final int FEC_LDPC_16K = Constants.FrontendAtsc3Fec.LDPC_16K;
+ public static final int FEC_LDPC_16K = FrontendAtsc3Fec.LDPC_16K;
/**
* LDPC 64K Forward Error Correction
*/
- public static final int FEC_LDPC_64K = Constants.FrontendAtsc3Fec.LDPC_64K;
+ public static final int FEC_LDPC_64K = FrontendAtsc3Fec.LDPC_64K;
/** @hide */
@@ -262,17 +260,17 @@ public class Atsc3FrontendSettings extends FrontendSettings {
* Demod output format undefined.
*/
public static final int DEMOD_OUTPUT_FORMAT_UNDEFINED =
- Constants.FrontendAtsc3DemodOutputFormat.UNDEFINED;
+ FrontendAtsc3DemodOutputFormat.UNDEFINED;
/**
* ALP format. Typically used in US region.
*/
public static final int DEMOD_OUTPUT_FORMAT_ATSC3_LINKLAYER_PACKET =
- Constants.FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
+ FrontendAtsc3DemodOutputFormat.ATSC3_LINKLAYER_PACKET;
/**
* BaseBand packet format. Typically used in Korea region.
*/
public static final int DEMOD_OUTPUT_FORMAT_BASEBAND_PACKET =
- Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
+ FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
private final int mBandwidth;
private final int mDemodOutputFormat;
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
index f7244bbdf951..042bba890d22 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
@@ -20,7 +20,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendAtscModulation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,19 +44,19 @@ public class AtscFrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendAtscModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendAtscModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendAtscModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendAtscModulation.AUTO;
/**
* 8VSB Modulation.
*/
- public static final int MODULATION_MOD_8VSB = Constants.FrontendAtscModulation.MOD_8VSB;
+ public static final int MODULATION_MOD_8VSB = FrontendAtscModulation.MOD_8VSB;
/**
* 16VSB Modulation.
*/
- public static final int MODULATION_MOD_16VSB = Constants.FrontendAtscModulation.MOD_16VSB;
+ public static final int MODULATION_MOD_16VSB = FrontendAtscModulation.MOD_16VSB;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index c1d08339c690..9ba41d5e1851 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -21,6 +21,12 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.hardware.tv.tuner.FrontendDtmbBandwidth;
+import android.hardware.tv.tuner.FrontendDtmbCodeRate;
+import android.hardware.tv.tuner.FrontendDtmbGuardInterval;
+import android.hardware.tv.tuner.FrontendDtmbModulation;
+import android.hardware.tv.tuner.FrontendDtmbTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDtmbTransmissionMode;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -46,23 +52,19 @@ public final class DtmbFrontendSettings extends FrontendSettings {
/**
* Bandwidth not defined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDtmbBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set bandwidth automatically
*/
- public static final int BANDWIDTH_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendDtmbBandwidth.AUTO;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDtmbBandwidth.BANDWIDTH_6MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDtmbBandwidth.BANDWIDTH_8MHZ;
/** @hide */
@@ -77,22 +79,21 @@ public final class DtmbFrontendSettings extends FrontendSettings {
* Time Interleave Mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.UNDEFINED;
+ FrontendDtmbTimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set time interleave mode automatically
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendDtmbTimeInterleaveMode.AUTO;
/**
* Time Interleave Mode timer int 240.
*/
public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
+ FrontendDtmbTimeInterleaveMode.TIMER_INT_240;
/**
* Time Interleave Mode timer int 720.
*/
public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
+ FrontendDtmbTimeInterleaveMode.TIMER_INT_720;
/** @hide */
@@ -108,43 +109,37 @@ public final class DtmbFrontendSettings extends FrontendSettings {
/**
* Guard Interval undefined.
*/
- public static final int GUARD_INTERVAL_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.UNDEFINED;
+ public static final int GUARD_INTERVAL_UNDEFINED = FrontendDtmbGuardInterval.UNDEFINED;
/**
* Hardware is able to detect and set Guard Interval automatically.
*/
- public static final int GUARD_INTERVAL_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.AUTO;
+ public static final int GUARD_INTERVAL_AUTO = FrontendDtmbGuardInterval.AUTO;
/**
* PN_420_VARIOUS Guard Interval.
*/
public static final int GUARD_INTERVAL_PN_420_VARIOUS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_VARIOUS;
+ FrontendDtmbGuardInterval.PN_420_VARIOUS;
/**
* PN_595_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_595_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_595_CONST;
+ public static final int GUARD_INTERVAL_PN_595_CONST = FrontendDtmbGuardInterval.PN_595_CONST;
/**
* PN_945_VARIOUS Guard Interval.
*/
public static final int GUARD_INTERVAL_PN_945_VARIOUS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_VARIOUS;
+ FrontendDtmbGuardInterval.PN_945_VARIOUS;
/**
* PN_420_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_420_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_CONST;
+ public static final int GUARD_INTERVAL_PN_420_CONST = FrontendDtmbGuardInterval.PN_420_CONST;
/**
* PN_945_CONST Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_945_CONST =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_CONST;
+ public static final int GUARD_INTERVAL_PN_945_CONST = FrontendDtmbGuardInterval.PN_945_CONST;
/**
* PN_RESERVED Guard Interval.
*/
- public static final int GUARD_INTERVAL_PN_RESERVED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_RESERVED;
+ public static final int GUARD_INTERVAL_PN_RESERVED = FrontendDtmbGuardInterval.PN_RESERVED;
/** @hide */
@@ -160,38 +155,36 @@ public final class DtmbFrontendSettings extends FrontendSettings {
/**
* Constellation not defined.
*/
- public static final int MODULATION_CONSTELLATION_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.UNDEFINED;
+ public static final int MODULATION_CONSTELLATION_UNDEFINED = FrontendDtmbModulation.UNDEFINED;
/**
* Hardware is able to detect and set Constellation automatically.
*/
- public static final int MODULATION_CONSTELLATION_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.AUTO;
+ public static final int MODULATION_CONSTELLATION_AUTO = FrontendDtmbModulation.AUTO;
/**
* 4QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_4QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM;
+ FrontendDtmbModulation.CONSTELLATION_4QAM;
/**
* 4QAM_NR Constellation.
*/
public static final int MODULATION_CONSTELLATION_4QAM_NR =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
+ FrontendDtmbModulation.CONSTELLATION_4QAM_NR;
/**
* 16QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_16QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_16QAM;
+ FrontendDtmbModulation.CONSTELLATION_16QAM;
/**
* 32QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_32QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_32QAM;
+ FrontendDtmbModulation.CONSTELLATION_32QAM;
/**
* 64QAM Constellation.
*/
public static final int MODULATION_CONSTELLATION_64QAM =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_64QAM;
+ FrontendDtmbModulation.CONSTELLATION_64QAM;
/** @hide */
@IntDef(flag = true,
@@ -203,28 +196,23 @@ public final class DtmbFrontendSettings extends FrontendSettings {
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendDtmbCodeRate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.AUTO;
+ public static final int CODERATE_AUTO = FrontendDtmbCodeRate.AUTO;
/**
* 2/5 code rate.
*/
- public static final int CODERATE_2_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_2_5;
+ public static final int CODERATE_2_5 = FrontendDtmbCodeRate.CODERATE_2_5;
/**
* 3/5 code rate.
*/
- public static final int CODERATE_3_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendDtmbCodeRate.CODERATE_3_5;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendDtmbCodeRate.CODERATE_4_5;
/** @hide */
@IntDef(flag = true,
@@ -237,23 +225,19 @@ public final class DtmbFrontendSettings extends FrontendSettings {
/**
* Transmission Mode undefined.
*/
- public static final int TRANSMISSION_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.UNDEFINED;
+ public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDtmbTransmissionMode.UNDEFINED;
/**
* Hardware is able to detect and set Transmission Mode automatically
*/
- public static final int TRANSMISSION_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.AUTO;
+ public static final int TRANSMISSION_MODE_AUTO = FrontendDtmbTransmissionMode.AUTO;
/**
* C1 Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_C1 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C1;
+ public static final int TRANSMISSION_MODE_C1 = FrontendDtmbTransmissionMode.C1;
/**
* C3780 Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_C3780 =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C3780;
+ public static final int TRANSMISSION_MODE_C3780 = FrontendDtmbTransmissionMode.C3780;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index db28631fe06c..b209d97feee5 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -20,7 +20,11 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendCableTimeInterleaveMode;
+import android.hardware.tv.tuner.FrontendDvbcAnnex;
+import android.hardware.tv.tuner.FrontendDvbcBandwidth;
+import android.hardware.tv.tuner.FrontendDvbcModulation;
+import android.hardware.tv.tuner.FrontendDvbcOuterFec;
import android.media.tv.tuner.TunerVersionChecker;
import android.media.tv.tuner.frontend.FrontendSettings.FrontendSpectralInversion;
@@ -47,31 +51,31 @@ public class DvbcFrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendDvbcModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendDvbcModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendDvbcModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendDvbcModulation.AUTO;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbcModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendDvbcModulation.MOD_16QAM;
/**
* 32QAM Modulation.
*/
- public static final int MODULATION_MOD_32QAM = Constants.FrontendDvbcModulation.MOD_32QAM;
+ public static final int MODULATION_MOD_32QAM = FrontendDvbcModulation.MOD_32QAM;
/**
* 64QAM Modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendDvbcModulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendDvbcModulation.MOD_64QAM;
/**
* 128QAM Modulation.
*/
- public static final int MODULATION_MOD_128QAM = Constants.FrontendDvbcModulation.MOD_128QAM;
+ public static final int MODULATION_MOD_128QAM = FrontendDvbcModulation.MOD_128QAM;
/**
* 256QAM Modulation.
*/
- public static final int MODULATION_MOD_256QAM = Constants.FrontendDvbcModulation.MOD_256QAM;
+ public static final int MODULATION_MOD_256QAM = FrontendDvbcModulation.MOD_256QAM;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -82,16 +86,15 @@ public class DvbcFrontendSettings extends FrontendSettings {
/**
* Outer Forward Error Correction (FEC) Type undefined.
*/
- public static final int OUTER_FEC_UNDEFINED = Constants.FrontendDvbcOuterFec.UNDEFINED;
+ public static final int OUTER_FEC_UNDEFINED = FrontendDvbcOuterFec.UNDEFINED;
/**
* None Outer Forward Error Correction (FEC) Type.
*/
- public static final int OUTER_FEC_OUTER_FEC_NONE =
- Constants.FrontendDvbcOuterFec.OUTER_FEC_NONE;
+ public static final int OUTER_FEC_OUTER_FEC_NONE = FrontendDvbcOuterFec.OUTER_FEC_NONE;
/**
* RS Outer Forward Error Correction (FEC) Type.
*/
- public static final int OUTER_FEC_OUTER_FEC_RS = Constants.FrontendDvbcOuterFec.OUTER_FEC_RS;
+ public static final int OUTER_FEC_OUTER_FEC_RS = FrontendDvbcOuterFec.OUTER_FEC_RS;
/** @hide */
@@ -104,19 +107,19 @@ public class DvbcFrontendSettings extends FrontendSettings {
/**
* Annex Type undefined.
*/
- public static final int ANNEX_UNDEFINED = Constants.FrontendDvbcAnnex.UNDEFINED;
+ public static final int ANNEX_UNDEFINED = FrontendDvbcAnnex.UNDEFINED;
/**
* Annex Type A.
*/
- public static final int ANNEX_A = Constants.FrontendDvbcAnnex.A;
+ public static final int ANNEX_A = FrontendDvbcAnnex.A;
/**
* Annex Type B.
*/
- public static final int ANNEX_B = Constants.FrontendDvbcAnnex.B;
+ public static final int ANNEX_B = FrontendDvbcAnnex.B;
/**
* Annex Type C.
*/
- public static final int ANNEX_C = Constants.FrontendDvbcAnnex.C;
+ public static final int ANNEX_C = FrontendDvbcAnnex.C;
/**
@@ -137,7 +140,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
*/
@Deprecated
public static final int SPECTRAL_INVERSION_UNDEFINED =
- Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
/**
* Normal Spectral Inversion.
*
@@ -145,7 +148,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
*/
@Deprecated
public static final int SPECTRAL_INVERSION_NORMAL =
- Constants.FrontendDvbcSpectralInversion.NORMAL;
+ android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
/**
* Inverted Spectral Inversion.
*
@@ -153,7 +156,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
*/
@Deprecated
public static final int SPECTRAL_INVERSION_INVERTED =
- Constants.FrontendDvbcSpectralInversion.INVERTED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
/** @hide */
@IntDef(flag = true,
@@ -171,57 +174,56 @@ public class DvbcFrontendSettings extends FrontendSettings {
* Time interleave mode undefined.
*/
public static final int TIME_INTERLEAVE_MODE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.UNDEFINED;
+ FrontendCableTimeInterleaveMode.UNDEFINED;
/**
* Hardware is able to detect and set Time Interleave Mode automatically.
*/
- public static final int TIME_INTERLEAVE_MODE_AUTO =
- android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.AUTO;
+ public static final int TIME_INTERLEAVE_MODE_AUTO = FrontendCableTimeInterleaveMode.AUTO;
/**
* 128/1/0 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_1_0 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
+ public static final int TIME_INTERLEAVE_MODE_128_1_0 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0;
/**
* 128/1/1 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_1_1 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
+ public static final int TIME_INTERLEAVE_MODE_128_1_1 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1;
/**
* 64/2 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_64_2 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
+ public static final int TIME_INTERLEAVE_MODE_64_2 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_64_2;
/**
* 32/4 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_32_4 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
+ public static final int TIME_INTERLEAVE_MODE_32_4 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_32_4;
/**
* 16/8 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_16_8 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
+ public static final int TIME_INTERLEAVE_MODE_16_8 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_16_8;
/**
* 8/16 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_8_16 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
+ public static final int TIME_INTERLEAVE_MODE_8_16 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_8_16;
/**
* 128/2 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_2 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
+ public static final int TIME_INTERLEAVE_MODE_128_2 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_2;
/**
* 128/3 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_3 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
+ public static final int TIME_INTERLEAVE_MODE_128_3 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_3;
/**
* 128/4 Time Interleave Mode.
*/
- public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants
- .FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
+ public static final int TIME_INTERLEAVE_MODE_128_4 =
+ FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
/** @hide */
@IntDef(flag = true,
@@ -234,28 +236,23 @@ public class DvbcFrontendSettings extends FrontendSettings {
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDvbcBandwidth.UNDEFINED;
/**
* 5 MHz bandwidth.
*/
- public static final int BANDWIDTH_5MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
+ public static final int BANDWIDTH_5MHZ = FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index f68d554c50c2..6e3d98a11a2b 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -21,7 +21,12 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbsModulation;
+import android.hardware.tv.tuner.FrontendDvbsPilot;
+import android.hardware.tv.tuner.FrontendDvbsRolloff;
+import android.hardware.tv.tuner.FrontendDvbsScanType;
+import android.hardware.tv.tuner.FrontendDvbsStandard;
+import android.hardware.tv.tuner.FrontendDvbsVcmMode;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerVersionChecker;
@@ -47,32 +52,27 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* Dvbs scan type undefined.
*/
- public static final int SCAN_TYPE_UNDEFINED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNDEFINED;
+ public static final int SCAN_TYPE_UNDEFINED = FrontendDvbsScanType.UNDEFINED;
/**
* Dvbs scan type DIRECT.
*/
- public static final int SCAN_TYPE_DIRECT =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DIRECT;
+ public static final int SCAN_TYPE_DIRECT = FrontendDvbsScanType.DIRECT;
/**
* Dvbs scan type DISEQC.
*/
- public static final int SCAN_TYPE_DISEQC =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DISEQC;
+ public static final int SCAN_TYPE_DISEQC = FrontendDvbsScanType.DISEQC;
/**
* Dvbs scan type UNICABLE.
*/
- public static final int SCAN_TYPE_UNICABLE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNICABLE;
+ public static final int SCAN_TYPE_UNICABLE = FrontendDvbsScanType.UNICABLE;
/**
* Dvbs scan type JESS.
*/
- public static final int SCAN_TYPE_JESS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.JESS;
+ public static final int SCAN_TYPE_JESS = FrontendDvbsScanType.JESS;
/** @hide */
@IntDef(flag = true,
@@ -88,63 +88,63 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendDvbsModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendDvbsModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendDvbsModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendDvbsModulation.AUTO;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendDvbsModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendDvbsModulation.MOD_QPSK;
/**
* 8PSK Modulation.
*/
- public static final int MODULATION_MOD_8PSK = Constants.FrontendDvbsModulation.MOD_8PSK;
+ public static final int MODULATION_MOD_8PSK = FrontendDvbsModulation.MOD_8PSK;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendDvbsModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendDvbsModulation.MOD_16QAM;
/**
* 16PSK Modulation.
*/
- public static final int MODULATION_MOD_16PSK = Constants.FrontendDvbsModulation.MOD_16PSK;
+ public static final int MODULATION_MOD_16PSK = FrontendDvbsModulation.MOD_16PSK;
/**
* 32PSK Modulation.
*/
- public static final int MODULATION_MOD_32PSK = Constants.FrontendDvbsModulation.MOD_32PSK;
+ public static final int MODULATION_MOD_32PSK = FrontendDvbsModulation.MOD_32PSK;
/**
* ACM Modulation.
*/
- public static final int MODULATION_MOD_ACM = Constants.FrontendDvbsModulation.MOD_ACM;
+ public static final int MODULATION_MOD_ACM = FrontendDvbsModulation.MOD_ACM;
/**
* 8APSK Modulation.
*/
- public static final int MODULATION_MOD_8APSK = Constants.FrontendDvbsModulation.MOD_8APSK;
+ public static final int MODULATION_MOD_8APSK = FrontendDvbsModulation.MOD_8APSK;
/**
* 16APSK Modulation.
*/
- public static final int MODULATION_MOD_16APSK = Constants.FrontendDvbsModulation.MOD_16APSK;
+ public static final int MODULATION_MOD_16APSK = FrontendDvbsModulation.MOD_16APSK;
/**
* 32APSK Modulation.
*/
- public static final int MODULATION_MOD_32APSK = Constants.FrontendDvbsModulation.MOD_32APSK;
+ public static final int MODULATION_MOD_32APSK = FrontendDvbsModulation.MOD_32APSK;
/**
* 64APSK Modulation.
*/
- public static final int MODULATION_MOD_64APSK = Constants.FrontendDvbsModulation.MOD_64APSK;
+ public static final int MODULATION_MOD_64APSK = FrontendDvbsModulation.MOD_64APSK;
/**
* 128APSK Modulation.
*/
- public static final int MODULATION_MOD_128APSK = Constants.FrontendDvbsModulation.MOD_128APSK;
+ public static final int MODULATION_MOD_128APSK = FrontendDvbsModulation.MOD_128APSK;
/**
* 256APSK Modulation.
*/
- public static final int MODULATION_MOD_256APSK = Constants.FrontendDvbsModulation.MOD_256APSK;
+ public static final int MODULATION_MOD_256APSK = FrontendDvbsModulation.MOD_256APSK;
/**
* Reversed Modulation.
*/
- public static final int MODULATION_MOD_RESERVED = Constants.FrontendDvbsModulation.MOD_RESERVED;
+ public static final int MODULATION_MOD_RESERVED = FrontendDvbsModulation.MOD_RESERVED;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -156,31 +156,31 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* Rolloff range undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendDvbsRolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendDvbsRolloff.UNDEFINED;
/**
* Rolloff range 0,35.
*/
- public static final int ROLLOFF_0_35 = Constants.FrontendDvbsRolloff.ROLLOFF_0_35;
+ public static final int ROLLOFF_0_35 = FrontendDvbsRolloff.ROLLOFF_0_35;
/**
* Rolloff range 0,25.
*/
- public static final int ROLLOFF_0_25 = Constants.FrontendDvbsRolloff.ROLLOFF_0_25;
+ public static final int ROLLOFF_0_25 = FrontendDvbsRolloff.ROLLOFF_0_25;
/**
* Rolloff range 0,20.
*/
- public static final int ROLLOFF_0_20 = Constants.FrontendDvbsRolloff.ROLLOFF_0_20;
+ public static final int ROLLOFF_0_20 = FrontendDvbsRolloff.ROLLOFF_0_20;
/**
* Rolloff range 0,15.
*/
- public static final int ROLLOFF_0_15 = Constants.FrontendDvbsRolloff.ROLLOFF_0_15;
+ public static final int ROLLOFF_0_15 = FrontendDvbsRolloff.ROLLOFF_0_15;
/**
* Rolloff range 0,10.
*/
- public static final int ROLLOFF_0_10 = Constants.FrontendDvbsRolloff.ROLLOFF_0_10;
+ public static final int ROLLOFF_0_10 = FrontendDvbsRolloff.ROLLOFF_0_10;
/**
* Rolloff range 0,5.
*/
- public static final int ROLLOFF_0_5 = Constants.FrontendDvbsRolloff.ROLLOFF_0_5;
+ public static final int ROLLOFF_0_5 = FrontendDvbsRolloff.ROLLOFF_0_5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -191,19 +191,19 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* Pilot mode undefined.
*/
- public static final int PILOT_UNDEFINED = Constants.FrontendDvbsPilot.UNDEFINED;
+ public static final int PILOT_UNDEFINED = FrontendDvbsPilot.UNDEFINED;
/**
* Pilot mode on.
*/
- public static final int PILOT_ON = Constants.FrontendDvbsPilot.ON;
+ public static final int PILOT_ON = FrontendDvbsPilot.ON;
/**
* Pilot mode off.
*/
- public static final int PILOT_OFF = Constants.FrontendDvbsPilot.OFF;
+ public static final int PILOT_OFF = FrontendDvbsPilot.OFF;
/**
* Pilot mode auto.
*/
- public static final int PILOT_AUTO = Constants.FrontendDvbsPilot.AUTO;
+ public static final int PILOT_AUTO = FrontendDvbsPilot.AUTO;
/** @hide */
@@ -216,19 +216,19 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* Standard undefined.
*/
- public static final int STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
+ public static final int STANDARD_AUTO = FrontendDvbsStandard.AUTO;
/**
* Standard S.
*/
- public static final int STANDARD_S = Constants.FrontendDvbsStandard.S;
+ public static final int STANDARD_S = FrontendDvbsStandard.S;
/**
* Standard S2.
*/
- public static final int STANDARD_S2 = Constants.FrontendDvbsStandard.S2;
+ public static final int STANDARD_S2 = FrontendDvbsStandard.S2;
/**
* Standard S2X.
*/
- public static final int STANDARD_S2X = Constants.FrontendDvbsStandard.S2X;
+ public static final int STANDARD_S2X = FrontendDvbsStandard.S2X;
/** @hide */
@IntDef(prefix = "VCM_MODE_",
@@ -239,15 +239,15 @@ public class DvbsFrontendSettings extends FrontendSettings {
/**
* VCM mode undefined.
*/
- public static final int VCM_MODE_UNDEFINED = Constants.FrontendDvbsVcmMode.UNDEFINED;
+ public static final int VCM_MODE_UNDEFINED = FrontendDvbsVcmMode.UNDEFINED;
/**
* Auto VCM mode.
*/
- public static final int VCM_MODE_AUTO = Constants.FrontendDvbsVcmMode.AUTO;
+ public static final int VCM_MODE_AUTO = FrontendDvbsVcmMode.AUTO;
/**
* Manual VCM mode.
*/
- public static final int VCM_MODE_MANUAL = Constants.FrontendDvbsVcmMode.MANUAL;
+ public static final int VCM_MODE_MANUAL = FrontendDvbsVcmMode.MANUAL;
private final int mModulation;
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 536c7b82d0af..5735b39b0a56 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -20,7 +20,14 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendDvbtBandwidth;
+import android.hardware.tv.tuner.FrontendDvbtCoderate;
+import android.hardware.tv.tuner.FrontendDvbtConstellation;
+import android.hardware.tv.tuner.FrontendDvbtGuardInterval;
+import android.hardware.tv.tuner.FrontendDvbtHierarchy;
+import android.hardware.tv.tuner.FrontendDvbtPlpMode;
+import android.hardware.tv.tuner.FrontendDvbtStandard;
+import android.hardware.tv.tuner.FrontendDvbtTransmissionMode;
import android.media.tv.tuner.TunerVersionChecker;
import java.lang.annotation.Retention;
@@ -46,51 +53,49 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Transmission Mode undefined.
*/
- public static final int TRANSMISSION_MODE_UNDEFINED =
- Constants.FrontendDvbtTransmissionMode.UNDEFINED;
+ public static final int TRANSMISSION_MODE_UNDEFINED = FrontendDvbtTransmissionMode.UNDEFINED;
/**
* Hardware is able to detect and set Transmission Mode automatically
*/
- public static final int TRANSMISSION_MODE_AUTO = Constants.FrontendDvbtTransmissionMode.AUTO;
+ public static final int TRANSMISSION_MODE_AUTO = FrontendDvbtTransmissionMode.AUTO;
/**
* 2K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_2K = Constants.FrontendDvbtTransmissionMode.MODE_2K;
+ public static final int TRANSMISSION_MODE_2K = FrontendDvbtTransmissionMode.MODE_2K;
/**
* 8K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_8K = Constants.FrontendDvbtTransmissionMode.MODE_8K;
+ public static final int TRANSMISSION_MODE_8K = FrontendDvbtTransmissionMode.MODE_8K;
/**
* 4K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_4K = Constants.FrontendDvbtTransmissionMode.MODE_4K;
+ public static final int TRANSMISSION_MODE_4K = FrontendDvbtTransmissionMode.MODE_4K;
/**
* 1K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_1K = Constants.FrontendDvbtTransmissionMode.MODE_1K;
+ public static final int TRANSMISSION_MODE_1K = FrontendDvbtTransmissionMode.MODE_1K;
/**
* 16K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_16K = Constants.FrontendDvbtTransmissionMode.MODE_16K;
+ public static final int TRANSMISSION_MODE_16K = FrontendDvbtTransmissionMode.MODE_16K;
/**
* 32K Transmission Mode.
*/
- public static final int TRANSMISSION_MODE_32K = Constants.FrontendDvbtTransmissionMode.MODE_32K;
+ public static final int TRANSMISSION_MODE_32K = FrontendDvbtTransmissionMode.MODE_32K;
/**
* 8K Transmission Extended Mode.
*/
- public static final int TRANSMISSION_MODE_EXTENDED_8K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_8K_E;
+ public static final int TRANSMISSION_MODE_EXTENDED_8K = FrontendDvbtTransmissionMode.MODE_8K_E;
/**
* 16K Transmission Extended Mode.
*/
public static final int TRANSMISSION_MODE_EXTENDED_16K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_16K_E;
+ FrontendDvbtTransmissionMode.MODE_16K_E;
/**
* 32K Transmission Extended Mode.
*/
public static final int TRANSMISSION_MODE_EXTENDED_32K =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_32K_E;
+ FrontendDvbtTransmissionMode.MODE_32K_E;
/** @hide */
@IntDef(flag = true,
@@ -103,35 +108,35 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED = Constants.FrontendDvbtBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendDvbtBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set Bandwidth automatically.
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendDvbtBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendDvbtBandwidth.AUTO;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendDvbtBandwidth.BANDWIDTH_8MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_7MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendDvbtBandwidth.BANDWIDTH_6MHZ;
/**
* 5 MHz bandwidth.
*/
- public static final int BANDWIDTH_5MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
+ public static final int BANDWIDTH_5MHZ = FrontendDvbtBandwidth.BANDWIDTH_5MHZ;
/**
* 1,7 MHz bandwidth.
*/
- public static final int BANDWIDTH_1_7MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
+ public static final int BANDWIDTH_1_7MHZ = FrontendDvbtBandwidth.BANDWIDTH_1_7MHZ;
/**
* 10 MHz bandwidth.
*/
- public static final int BANDWIDTH_10MHZ = Constants.FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
+ public static final int BANDWIDTH_10MHZ = FrontendDvbtBandwidth.BANDWIDTH_10MHZ;
/** @hide */
@@ -147,55 +152,44 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Constellation not defined.
*/
- public static final int CONSTELLATION_UNDEFINED = Constants.FrontendDvbtConstellation.UNDEFINED;
+ public static final int CONSTELLATION_UNDEFINED = FrontendDvbtConstellation.UNDEFINED;
/**
* Hardware is able to detect and set Constellation automatically.
*/
- public static final int CONSTELLATION_AUTO = Constants.FrontendDvbtConstellation.AUTO;
+ public static final int CONSTELLATION_AUTO = FrontendDvbtConstellation.AUTO;
/**
* QPSK Constellation.
*/
- public static final int CONSTELLATION_QPSK =
- Constants.FrontendDvbtConstellation.CONSTELLATION_QPSK;
+ public static final int CONSTELLATION_QPSK = FrontendDvbtConstellation.CONSTELLATION_QPSK;
/**
* 16QAM Constellation.
*/
- public static final int CONSTELLATION_16QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_16QAM;
+ public static final int CONSTELLATION_16QAM = FrontendDvbtConstellation.CONSTELLATION_16QAM;
/**
* 64QAM Constellation.
*/
- public static final int CONSTELLATION_64QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_64QAM;
+ public static final int CONSTELLATION_64QAM = FrontendDvbtConstellation.CONSTELLATION_64QAM;
/**
* 256QAM Constellation.
*/
- public static final int CONSTELLATION_256QAM =
- Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
+ public static final int CONSTELLATION_256QAM = FrontendDvbtConstellation.CONSTELLATION_256QAM;
/**
* QPSK Rotated Constellation.
*/
- public static final int CONSTELLATION_QPSK_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_QPSK_R;
+ public static final int CONSTELLATION_QPSK_R = FrontendDvbtConstellation.CONSTELLATION_QPSK_R;
/**
* 16QAM Rotated Constellation.
*/
- public static final int CONSTELLATION_16QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_16QAM_R;
+ public static final int CONSTELLATION_16QAM_R = FrontendDvbtConstellation.CONSTELLATION_16QAM_R;
/**
* 64QAM Rotated Constellation.
*/
- public static final int CONSTELLATION_64QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_64QAM_R;
+ public static final int CONSTELLATION_64QAM_R = FrontendDvbtConstellation.CONSTELLATION_64QAM_R;
/**
* 256QAM Rotated Constellation.
*/
public static final int CONSTELLATION_256QAM_R =
- android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation
- .CONSTELLATION_256QAM_R;
+ FrontendDvbtConstellation.CONSTELLATION_256QAM_R;
/** @hide */
@IntDef(flag = true,
@@ -209,48 +203,43 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Hierarchy undefined.
*/
- public static final int HIERARCHY_UNDEFINED = Constants.FrontendDvbtHierarchy.UNDEFINED;
+ public static final int HIERARCHY_UNDEFINED = FrontendDvbtHierarchy.UNDEFINED;
/**
* Hardware is able to detect and set Hierarchy automatically.
*/
- public static final int HIERARCHY_AUTO = Constants.FrontendDvbtHierarchy.AUTO;
+ public static final int HIERARCHY_AUTO = FrontendDvbtHierarchy.AUTO;
/**
* Non-native Hierarchy
*/
- public static final int HIERARCHY_NON_NATIVE =
- Constants.FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
+ public static final int HIERARCHY_NON_NATIVE = FrontendDvbtHierarchy.HIERARCHY_NON_NATIVE;
/**
* 1-native Hierarchy
*/
- public static final int HIERARCHY_1_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
+ public static final int HIERARCHY_1_NATIVE = FrontendDvbtHierarchy.HIERARCHY_1_NATIVE;
/**
* 2-native Hierarchy
*/
- public static final int HIERARCHY_2_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
+ public static final int HIERARCHY_2_NATIVE = FrontendDvbtHierarchy.HIERARCHY_2_NATIVE;
/**
* 4-native Hierarchy
*/
- public static final int HIERARCHY_4_NATIVE = Constants.FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
+ public static final int HIERARCHY_4_NATIVE = FrontendDvbtHierarchy.HIERARCHY_4_NATIVE;
/**
* Non-indepth Hierarchy
*/
- public static final int HIERARCHY_NON_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
+ public static final int HIERARCHY_NON_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_NON_INDEPTH;
/**
* 1-indepth Hierarchy
*/
- public static final int HIERARCHY_1_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
+ public static final int HIERARCHY_1_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_1_INDEPTH;
/**
* 2-indepth Hierarchy
*/
- public static final int HIERARCHY_2_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
+ public static final int HIERARCHY_2_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_2_INDEPTH;
/**
* 4-indepth Hierarchy
*/
- public static final int HIERARCHY_4_INDEPTH =
- Constants.FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
+ public static final int HIERARCHY_4_INDEPTH = FrontendDvbtHierarchy.HIERARCHY_4_INDEPTH;
/** @hide */
@@ -264,48 +253,47 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED =
- Constants.FrontendDvbtCoderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendDvbtCoderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendDvbtCoderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendDvbtCoderate.AUTO;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendDvbtCoderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendDvbtCoderate.CODERATE_1_2;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendDvbtCoderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendDvbtCoderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendDvbtCoderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendDvbtCoderate.CODERATE_3_4;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendDvbtCoderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendDvbtCoderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendDvbtCoderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendDvbtCoderate.CODERATE_7_8;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_3_5 = Constants.FrontendDvbtCoderate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendDvbtCoderate.CODERATE_3_5;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 = Constants.FrontendDvbtCoderate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendDvbtCoderate.CODERATE_4_5;
/**
* 6/7 code rate.
*/
- public static final int CODERATE_6_7 = Constants.FrontendDvbtCoderate.CODERATE_6_7;
+ public static final int CODERATE_6_7 = FrontendDvbtCoderate.CODERATE_6_7;
/**
* 8/9 code rate.
*/
- public static final int CODERATE_8_9 = Constants.FrontendDvbtCoderate.CODERATE_8_9;
+ public static final int CODERATE_8_9 = FrontendDvbtCoderate.CODERATE_8_9;
/** @hide */
@IntDef(flag = true,
@@ -323,46 +311,39 @@ public class DvbtFrontendSettings extends FrontendSettings {
* Guard Interval undefined.
*/
public static final int GUARD_INTERVAL_UNDEFINED =
- Constants.FrontendDvbtGuardInterval.UNDEFINED;
+ FrontendDvbtGuardInterval.UNDEFINED;
/**
* Hardware is able to detect and set Guard Interval automatically.
*/
- public static final int GUARD_INTERVAL_AUTO = Constants.FrontendDvbtGuardInterval.AUTO;
+ public static final int GUARD_INTERVAL_AUTO = FrontendDvbtGuardInterval.AUTO;
/**
* 1/32 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_32 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_32;
+ public static final int GUARD_INTERVAL_1_32 = FrontendDvbtGuardInterval.INTERVAL_1_32;
/**
* 1/16 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_16 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_16;
+ public static final int GUARD_INTERVAL_1_16 = FrontendDvbtGuardInterval.INTERVAL_1_16;
/**
* 1/8 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_8 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_8;
+ public static final int GUARD_INTERVAL_1_8 = FrontendDvbtGuardInterval.INTERVAL_1_8;
/**
* 1/4 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_4 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_4;
+ public static final int GUARD_INTERVAL_1_4 = FrontendDvbtGuardInterval.INTERVAL_1_4;
/**
* 1/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_1_128 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_1_128;
+ public static final int GUARD_INTERVAL_1_128 = FrontendDvbtGuardInterval.INTERVAL_1_128;
/**
* 19/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_19_128 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_19_128;
+ public static final int GUARD_INTERVAL_19_128 = FrontendDvbtGuardInterval.INTERVAL_19_128;
/**
* 19/256 Guard Interval.
*/
- public static final int GUARD_INTERVAL_19_256 =
- Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
+ public static final int GUARD_INTERVAL_19_256 = FrontendDvbtGuardInterval.INTERVAL_19_256;
/** @hide */
@IntDef(flag = true,
@@ -375,15 +356,15 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Hardware is able to detect and set Standard automatically.
*/
- public static final int STANDARD_AUTO = Constants.FrontendDvbtStandard.AUTO;
+ public static final int STANDARD_AUTO = FrontendDvbtStandard.AUTO;
/**
* T standard.
*/
- public static final int STANDARD_T = Constants.FrontendDvbtStandard.T;
+ public static final int STANDARD_T = FrontendDvbtStandard.T;
/**
* T2 standard.
*/
- public static final int STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
+ public static final int STANDARD_T2 = FrontendDvbtStandard.T2;
/** @hide */
@IntDef(prefix = "PLP_MODE_",
@@ -394,15 +375,15 @@ public class DvbtFrontendSettings extends FrontendSettings {
/**
* Physical Layer Pipe (PLP) Mode undefined.
*/
- public static final int PLP_MODE_UNDEFINED = Constants.FrontendDvbtPlpMode.UNDEFINED;
+ public static final int PLP_MODE_UNDEFINED = FrontendDvbtPlpMode.UNDEFINED;
/**
* Hardware is able to detect and set Physical Layer Pipe (PLP) Mode automatically.
*/
- public static final int PLP_MODE_AUTO = Constants.FrontendDvbtPlpMode.AUTO;
+ public static final int PLP_MODE_AUTO = FrontendDvbtPlpMode.AUTO;
/**
* Physical Layer Pipe (PLP) manual Mode.
*/
- public static final int PLP_MODE_MANUAL = Constants.FrontendDvbtPlpMode.MANUAL;
+ public static final int PLP_MODE_MANUAL = FrontendDvbtPlpMode.MANUAL;
private int mTransmissionMode;
private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index 4bfe8078be35..4a31686e0895 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -20,7 +20,8 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.LongDef;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendInnerFec;
+import android.hardware.tv.tuner.FrontendType;
import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerVersionChecker;
@@ -44,47 +45,47 @@ public abstract class FrontendSettings {
/**
* Undefined frontend type.
*/
- public static final int TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+ public static final int TYPE_UNDEFINED = FrontendType.UNDEFINED;
/**
* Analog frontend type.
*/
- public static final int TYPE_ANALOG = Constants.FrontendType.ANALOG;
+ public static final int TYPE_ANALOG = FrontendType.ANALOG;
/**
* Advanced Television Systems Committee (ATSC) frontend type.
*/
- public static final int TYPE_ATSC = Constants.FrontendType.ATSC;
+ public static final int TYPE_ATSC = FrontendType.ATSC;
/**
* Advanced Television Systems Committee 3.0 (ATSC-3) frontend type.
*/
- public static final int TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+ public static final int TYPE_ATSC3 = FrontendType.ATSC3;
/**
* Digital Video Broadcasting-Cable (DVB-C) frontend type.
*/
- public static final int TYPE_DVBC = Constants.FrontendType.DVBC;
+ public static final int TYPE_DVBC = FrontendType.DVBC;
/**
* Digital Video Broadcasting-Satellite (DVB-S) frontend type.
*/
- public static final int TYPE_DVBS = Constants.FrontendType.DVBS;
+ public static final int TYPE_DVBS = FrontendType.DVBS;
/**
* Digital Video Broadcasting-Terrestrial (DVB-T) frontend type.
*/
- public static final int TYPE_DVBT = Constants.FrontendType.DVBT;
+ public static final int TYPE_DVBT = FrontendType.DVBT;
/**
* Integrated Services Digital Broadcasting-Satellite (ISDB-S) frontend type.
*/
- public static final int TYPE_ISDBS = Constants.FrontendType.ISDBS;
+ public static final int TYPE_ISDBS = FrontendType.ISDBS;
/**
* Integrated Services Digital Broadcasting-Satellite 3 (ISDB-S3) frontend type.
*/
- public static final int TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+ public static final int TYPE_ISDBS3 = FrontendType.ISDBS3;
/**
* Integrated Services Digital Broadcasting-Terrestrial (ISDB-T) frontend type.
*/
- public static final int TYPE_ISDBT = Constants.FrontendType.ISDBT;
+ public static final int TYPE_ISDBT = FrontendType.ISDBT;
/**
* Digital Terrestrial Multimedia Broadcast standard (DTMB) frontend type.
*/
- public static final int TYPE_DTMB = android.hardware.tv.tuner.V1_1.Constants.FrontendType.DTMB;
+ public static final int TYPE_DTMB = FrontendType.DTMB;
/** @hide */
@@ -101,151 +102,151 @@ public abstract class FrontendSettings {
/**
* FEC not defined.
*/
- public static final long FEC_UNDEFINED = Constants.FrontendInnerFec.FEC_UNDEFINED;
+ public static final long FEC_UNDEFINED = FrontendInnerFec.FEC_UNDEFINED;
/**
* hardware is able to detect and set FEC automatically.
*/
- public static final long FEC_AUTO = Constants.FrontendInnerFec.AUTO;
+ public static final long FEC_AUTO = FrontendInnerFec.AUTO;
/**
* 1/2 conv. code rate.
*/
- public static final long FEC_1_2 = Constants.FrontendInnerFec.FEC_1_2;
+ public static final long FEC_1_2 = FrontendInnerFec.FEC_1_2;
/**
* 1/3 conv. code rate.
*/
- public static final long FEC_1_3 = Constants.FrontendInnerFec.FEC_1_3;
+ public static final long FEC_1_3 = FrontendInnerFec.FEC_1_3;
/**
* 1/4 conv. code rate.
*/
- public static final long FEC_1_4 = Constants.FrontendInnerFec.FEC_1_4;
+ public static final long FEC_1_4 = FrontendInnerFec.FEC_1_4;
/**
* 1/5 conv. code rate.
*/
- public static final long FEC_1_5 = Constants.FrontendInnerFec.FEC_1_5;
+ public static final long FEC_1_5 = FrontendInnerFec.FEC_1_5;
/**
* 2/3 conv. code rate.
*/
- public static final long FEC_2_3 = Constants.FrontendInnerFec.FEC_2_3;
+ public static final long FEC_2_3 = FrontendInnerFec.FEC_2_3;
/**
* 2/5 conv. code rate.
*/
- public static final long FEC_2_5 = Constants.FrontendInnerFec.FEC_2_5;
+ public static final long FEC_2_5 = FrontendInnerFec.FEC_2_5;
/**
* 2/9 conv. code rate.
*/
- public static final long FEC_2_9 = Constants.FrontendInnerFec.FEC_2_9;
+ public static final long FEC_2_9 = FrontendInnerFec.FEC_2_9;
/**
* 3/4 conv. code rate.
*/
- public static final long FEC_3_4 = Constants.FrontendInnerFec.FEC_3_4;
+ public static final long FEC_3_4 = FrontendInnerFec.FEC_3_4;
/**
* 3/5 conv. code rate.
*/
- public static final long FEC_3_5 = Constants.FrontendInnerFec.FEC_3_5;
+ public static final long FEC_3_5 = FrontendInnerFec.FEC_3_5;
/**
* 4/5 conv. code rate.
*/
- public static final long FEC_4_5 = Constants.FrontendInnerFec.FEC_4_5;
+ public static final long FEC_4_5 = FrontendInnerFec.FEC_4_5;
/**
* 4/15 conv. code rate.
*/
- public static final long FEC_4_15 = Constants.FrontendInnerFec.FEC_4_15;
+ public static final long FEC_4_15 = FrontendInnerFec.FEC_4_15;
/**
* 5/6 conv. code rate.
*/
- public static final long FEC_5_6 = Constants.FrontendInnerFec.FEC_5_6;
+ public static final long FEC_5_6 = FrontendInnerFec.FEC_5_6;
/**
* 5/9 conv. code rate.
*/
- public static final long FEC_5_9 = Constants.FrontendInnerFec.FEC_5_9;
+ public static final long FEC_5_9 = FrontendInnerFec.FEC_5_9;
/**
* 6/7 conv. code rate.
*/
- public static final long FEC_6_7 = Constants.FrontendInnerFec.FEC_6_7;
+ public static final long FEC_6_7 = FrontendInnerFec.FEC_6_7;
/**
* 7/8 conv. code rate.
*/
- public static final long FEC_7_8 = Constants.FrontendInnerFec.FEC_7_8;
+ public static final long FEC_7_8 = FrontendInnerFec.FEC_7_8;
/**
* 7/9 conv. code rate.
*/
- public static final long FEC_7_9 = Constants.FrontendInnerFec.FEC_7_9;
+ public static final long FEC_7_9 = FrontendInnerFec.FEC_7_9;
/**
* 7/15 conv. code rate.
*/
- public static final long FEC_7_15 = Constants.FrontendInnerFec.FEC_7_15;
+ public static final long FEC_7_15 = FrontendInnerFec.FEC_7_15;
/**
* 8/9 conv. code rate.
*/
- public static final long FEC_8_9 = Constants.FrontendInnerFec.FEC_8_9;
+ public static final long FEC_8_9 = FrontendInnerFec.FEC_8_9;
/**
* 8/15 conv. code rate.
*/
- public static final long FEC_8_15 = Constants.FrontendInnerFec.FEC_8_15;
+ public static final long FEC_8_15 = FrontendInnerFec.FEC_8_15;
/**
* 9/10 conv. code rate.
*/
- public static final long FEC_9_10 = Constants.FrontendInnerFec.FEC_9_10;
+ public static final long FEC_9_10 = FrontendInnerFec.FEC_9_10;
/**
* 9/20 conv. code rate.
*/
- public static final long FEC_9_20 = Constants.FrontendInnerFec.FEC_9_20;
+ public static final long FEC_9_20 = FrontendInnerFec.FEC_9_20;
/**
* 11/15 conv. code rate.
*/
- public static final long FEC_11_15 = Constants.FrontendInnerFec.FEC_11_15;
+ public static final long FEC_11_15 = FrontendInnerFec.FEC_11_15;
/**
* 11/20 conv. code rate.
*/
- public static final long FEC_11_20 = Constants.FrontendInnerFec.FEC_11_20;
+ public static final long FEC_11_20 = FrontendInnerFec.FEC_11_20;
/**
* 11/45 conv. code rate.
*/
- public static final long FEC_11_45 = Constants.FrontendInnerFec.FEC_11_45;
+ public static final long FEC_11_45 = FrontendInnerFec.FEC_11_45;
/**
* 13/18 conv. code rate.
*/
- public static final long FEC_13_18 = Constants.FrontendInnerFec.FEC_13_18;
+ public static final long FEC_13_18 = FrontendInnerFec.FEC_13_18;
/**
* 13/45 conv. code rate.
*/
- public static final long FEC_13_45 = Constants.FrontendInnerFec.FEC_13_45;
+ public static final long FEC_13_45 = FrontendInnerFec.FEC_13_45;
/**
* 14/45 conv. code rate.
*/
- public static final long FEC_14_45 = Constants.FrontendInnerFec.FEC_14_45;
+ public static final long FEC_14_45 = FrontendInnerFec.FEC_14_45;
/**
* 23/36 conv. code rate.
*/
- public static final long FEC_23_36 = Constants.FrontendInnerFec.FEC_23_36;
+ public static final long FEC_23_36 = FrontendInnerFec.FEC_23_36;
/**
* 25/36 conv. code rate.
*/
- public static final long FEC_25_36 = Constants.FrontendInnerFec.FEC_25_36;
+ public static final long FEC_25_36 = FrontendInnerFec.FEC_25_36;
/**
* 26/45 conv. code rate.
*/
- public static final long FEC_26_45 = Constants.FrontendInnerFec.FEC_26_45;
+ public static final long FEC_26_45 = FrontendInnerFec.FEC_26_45;
/**
* 28/45 conv. code rate.
*/
- public static final long FEC_28_45 = Constants.FrontendInnerFec.FEC_28_45;
+ public static final long FEC_28_45 = FrontendInnerFec.FEC_28_45;
/**
* 29/45 conv. code rate.
*/
- public static final long FEC_29_45 = Constants.FrontendInnerFec.FEC_29_45;
+ public static final long FEC_29_45 = FrontendInnerFec.FEC_29_45;
/**
* 31/45 conv. code rate.
*/
- public static final long FEC_31_45 = Constants.FrontendInnerFec.FEC_31_45;
+ public static final long FEC_31_45 = FrontendInnerFec.FEC_31_45;
/**
* 32/45 conv. code rate.
*/
- public static final long FEC_32_45 = Constants.FrontendInnerFec.FEC_32_45;
+ public static final long FEC_32_45 = FrontendInnerFec.FEC_32_45;
/**
* 77/90 conv. code rate.
*/
- public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90;
+ public static final long FEC_77_90 = FrontendInnerFec.FEC_77_90;
/** @hide */
@IntDef(prefix = "FRONTEND_SPECTRAL_INVERSION_",
@@ -258,17 +259,17 @@ public abstract class FrontendSettings {
* Spectral Inversion Type undefined.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED =
- Constants.FrontendDvbcSpectralInversion.UNDEFINED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.UNDEFINED;
/**
* Normal Spectral Inversion.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL =
- Constants.FrontendDvbcSpectralInversion.NORMAL;
+ android.hardware.tv.tuner.FrontendSpectralInversion.NORMAL;
/**
* Inverted Spectral Inversion.
*/
public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED =
- Constants.FrontendDvbcSpectralInversion.INVERTED;
+ android.hardware.tv.tuner.FrontendSpectralInversion.INVERTED;
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index b82a5a914da8..36fd94234e09 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Lnb;
import android.media.tv.tuner.TunerVersionChecker;
@@ -61,175 +60,188 @@ public class FrontendStatus {
* Lock status for Demod.
*/
public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK =
- Constants.FrontendStatusType.DEMOD_LOCK;
+ android.hardware.tv.tuner.FrontendStatusType.DEMOD_LOCK;
/**
* Signal to Noise Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_SNR = Constants.FrontendStatusType.SNR;
+ public static final int FRONTEND_STATUS_TYPE_SNR =
+ android.hardware.tv.tuner.FrontendStatusType.SNR;
/**
* Bit Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_BER = Constants.FrontendStatusType.BER;
+ public static final int FRONTEND_STATUS_TYPE_BER =
+ android.hardware.tv.tuner.FrontendStatusType.BER;
/**
* Packages Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_PER = Constants.FrontendStatusType.PER;
+ public static final int FRONTEND_STATUS_TYPE_PER =
+ android.hardware.tv.tuner.FrontendStatusType.PER;
/**
* Bit Error Ratio before FEC.
*/
- public static final int FRONTEND_STATUS_TYPE_PRE_BER = Constants.FrontendStatusType.PRE_BER;
+ public static final int FRONTEND_STATUS_TYPE_PRE_BER =
+ android.hardware.tv.tuner.FrontendStatusType.PRE_BER;
/**
* Signal Quality (0..100). Good data over total data in percent can be
* used as a way to present Signal Quality.
*/
public static final int FRONTEND_STATUS_TYPE_SIGNAL_QUALITY =
- Constants.FrontendStatusType.SIGNAL_QUALITY;
+ android.hardware.tv.tuner.FrontendStatusType.SIGNAL_QUALITY;
/**
* Signal Strength.
*/
public static final int FRONTEND_STATUS_TYPE_SIGNAL_STRENGTH =
- Constants.FrontendStatusType.SIGNAL_STRENGTH;
+ android.hardware.tv.tuner.FrontendStatusType.SIGNAL_STRENGTH;
/**
* Symbol Rate in symbols per second.
*/
public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE =
- Constants.FrontendStatusType.SYMBOL_RATE;
+ android.hardware.tv.tuner.FrontendStatusType.SYMBOL_RATE;
/**
* Forward Error Correction Type.
*/
- public static final int FRONTEND_STATUS_TYPE_FEC = Constants.FrontendStatusType.FEC;
+ public static final int FRONTEND_STATUS_TYPE_FEC =
+ android.hardware.tv.tuner.FrontendStatusType.FEC;
/**
* Modulation Type.
*/
public static final int FRONTEND_STATUS_TYPE_MODULATION =
- Constants.FrontendStatusType.MODULATION;
+ android.hardware.tv.tuner.FrontendStatusType.MODULATION;
/**
* Spectral Inversion Type.
*/
- public static final int FRONTEND_STATUS_TYPE_SPECTRAL = Constants.FrontendStatusType.SPECTRAL;
+ public static final int FRONTEND_STATUS_TYPE_SPECTRAL =
+ android.hardware.tv.tuner.FrontendStatusType.SPECTRAL;
/**
* LNB Voltage.
*/
public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE =
- Constants.FrontendStatusType.LNB_VOLTAGE;
+ android.hardware.tv.tuner.FrontendStatusType.LNB_VOLTAGE;
/**
* Physical Layer Pipe ID.
*/
- public static final int FRONTEND_STATUS_TYPE_PLP_ID = Constants.FrontendStatusType.PLP_ID;
+ public static final int FRONTEND_STATUS_TYPE_PLP_ID =
+ android.hardware.tv.tuner.FrontendStatusType.PLP_ID;
/**
* Status for Emergency Warning Broadcasting System.
*/
- public static final int FRONTEND_STATUS_TYPE_EWBS = Constants.FrontendStatusType.EWBS;
+ public static final int FRONTEND_STATUS_TYPE_EWBS =
+ android.hardware.tv.tuner.FrontendStatusType.EWBS;
/**
* Automatic Gain Control.
*/
- public static final int FRONTEND_STATUS_TYPE_AGC = Constants.FrontendStatusType.AGC;
+ public static final int FRONTEND_STATUS_TYPE_AGC =
+ android.hardware.tv.tuner.FrontendStatusType.AGC;
/**
* Low Noise Amplifier.
*/
- public static final int FRONTEND_STATUS_TYPE_LNA = Constants.FrontendStatusType.LNA;
+ public static final int FRONTEND_STATUS_TYPE_LNA =
+ android.hardware.tv.tuner.FrontendStatusType.LNA;
/**
* Error status by layer.
*/
public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR =
- Constants.FrontendStatusType.LAYER_ERROR;
+ android.hardware.tv.tuner.FrontendStatusType.LAYER_ERROR;
/**
* Modulation Error Ratio.
*/
- public static final int FRONTEND_STATUS_TYPE_MER = Constants.FrontendStatusType.MER;
+ public static final int FRONTEND_STATUS_TYPE_MER =
+ android.hardware.tv.tuner.FrontendStatusType.MER;
/**
* Difference between tuning frequency and actual locked frequency.
*/
public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET =
- Constants.FrontendStatusType.FREQ_OFFSET;
+ android.hardware.tv.tuner.FrontendStatusType.FREQ_OFFSET;
/**
* Hierarchy for DVBT.
*/
- public static final int FRONTEND_STATUS_TYPE_HIERARCHY = Constants.FrontendStatusType.HIERARCHY;
+ public static final int FRONTEND_STATUS_TYPE_HIERARCHY =
+ android.hardware.tv.tuner.FrontendStatusType.HIERARCHY;
/**
* Lock status for RF.
*/
- public static final int FRONTEND_STATUS_TYPE_RF_LOCK = Constants.FrontendStatusType.RF_LOCK;
+ public static final int FRONTEND_STATUS_TYPE_RF_LOCK =
+ android.hardware.tv.tuner.FrontendStatusType.RF_LOCK;
/**
* PLP information in a frequency band for ATSC-3.0 frontend.
*/
public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
- Constants.FrontendStatusType.ATSC3_PLP_INFO;
+ android.hardware.tv.tuner.FrontendStatusType.ATSC3_PLP_INFO;
/**
* BERS Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_BERS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BERS;
+ android.hardware.tv.tuner.FrontendStatusType.BERS;
/**
* Coderate Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_CODERATES =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.CODERATES;
+ android.hardware.tv.tuner.FrontendStatusType.CODERATES;
/**
* Bandwidth Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_BANDWIDTH =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BANDWIDTH;
+ android.hardware.tv.tuner.FrontendStatusType.BANDWIDTH;
/**
* Guard Interval Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.GUARD_INTERVAL;
+ android.hardware.tv.tuner.FrontendStatusType.GUARD_INTERVAL;
/**
* Transmission Mode Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TRANSMISSION_MODE;
+ android.hardware.tv.tuner.FrontendStatusType.TRANSMISSION_MODE;
/**
* UEC Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_UEC =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.UEC;
+ android.hardware.tv.tuner.FrontendStatusType.UEC;
/**
* T2 System Id Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.T2_SYSTEM_ID;
+ android.hardware.tv.tuner.FrontendStatusType.T2_SYSTEM_ID;
/**
* Interleavings Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.INTERLEAVINGS;
+ android.hardware.tv.tuner.FrontendStatusType.INTERLEAVINGS;
/**
* ISDBT Segments Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ISDBT_SEGMENTS;
+ android.hardware.tv.tuner.FrontendStatusType.ISDBT_SEGMENTS;
/**
* TS Data Rates Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TS_DATA_RATES;
+ android.hardware.tv.tuner.FrontendStatusType.TS_DATA_RATES;
/**
* Extended Modulations Type. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.MODULATIONS;
+ android.hardware.tv.tuner.FrontendStatusType.MODULATIONS;
/**
* Roll Off Type status of the frontend. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_ROLL_OFF =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ROLL_OFF;
+ android.hardware.tv.tuner.FrontendStatusType.ROLL_OFF;
/**
* If the frontend currently supports MISO or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_MISO_ENABLED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_MISO;
+ android.hardware.tv.tuner.FrontendStatusType.IS_MISO;
/**
* If the frontend code rate is linear or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_LINEAR =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_LINEAR;
+ android.hardware.tv.tuner.FrontendStatusType.IS_LINEAR;
/**
* If short frames is enabled or not. Only supported in Tuner HAL 1.1 or higher.
*/
public static final int FRONTEND_STATUS_TYPE_IS_SHORT_FRAMES_ENABLED =
- android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.IS_SHORT_FRAMES;
+ android.hardware.tv.tuner.FrontendStatusType.IS_SHORT_FRAMES;
/** @hide */
@IntDef(value = {
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index 02cdb96285e3..14b0b029ab37 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -20,7 +20,9 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbs3Coderate;
+import android.hardware.tv.tuner.FrontendIsdbs3Modulation;
+import android.hardware.tv.tuner.FrontendIsdbs3Rolloff;
import android.media.tv.tuner.Tuner;
import java.lang.annotation.Retention;
@@ -45,31 +47,31 @@ public class Isdbs3FrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbs3Modulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbs3Modulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically.
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbs3Modulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbs3Modulation.AUTO;
/**
* BPSK Modulation.
*/
- public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbs3Modulation.MOD_BPSK;
+ public static final int MODULATION_MOD_BPSK = FrontendIsdbs3Modulation.MOD_BPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbs3Modulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbs3Modulation.MOD_QPSK;
/**
* 8PSK Modulation.
*/
- public static final int MODULATION_MOD_8PSK = Constants.FrontendIsdbs3Modulation.MOD_8PSK;
+ public static final int MODULATION_MOD_8PSK = FrontendIsdbs3Modulation.MOD_8PSK;
/**
* 16APSK Modulation.
*/
- public static final int MODULATION_MOD_16APSK = Constants.FrontendIsdbs3Modulation.MOD_16APSK;
+ public static final int MODULATION_MOD_16APSK = FrontendIsdbs3Modulation.MOD_16APSK;
/**
* 32APSK Modulation.
*/
- public static final int MODULATION_MOD_32APSK = Constants.FrontendIsdbs3Modulation.MOD_32APSK;
+ public static final int MODULATION_MOD_32APSK = FrontendIsdbs3Modulation.MOD_32APSK;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -83,55 +85,55 @@ public class Isdbs3FrontendSettings extends FrontendSettings {
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbs3Coderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendIsdbs3Coderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendIsdbs3Coderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendIsdbs3Coderate.AUTO;
/**
* 1/3 code rate.
*/
- public static final int CODERATE_1_3 = Constants.FrontendIsdbs3Coderate.CODERATE_1_3;
+ public static final int CODERATE_1_3 = FrontendIsdbs3Coderate.CODERATE_1_3;
/**
* 2/5 code rate.
*/
- public static final int CODERATE_2_5 = Constants.FrontendIsdbs3Coderate.CODERATE_2_5;
+ public static final int CODERATE_2_5 = FrontendIsdbs3Coderate.CODERATE_2_5;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendIsdbs3Coderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendIsdbs3Coderate.CODERATE_1_2;
/**
* 3/5 code rate.
*/
- public static final int CODERATE_3_5 = Constants.FrontendIsdbs3Coderate.CODERATE_3_5;
+ public static final int CODERATE_3_5 = FrontendIsdbs3Coderate.CODERATE_3_5;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendIsdbs3Coderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendIsdbs3Coderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendIsdbs3Coderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendIsdbs3Coderate.CODERATE_3_4;
/**
* 7/9 code rate.
*/
- public static final int CODERATE_7_9 = Constants.FrontendIsdbs3Coderate.CODERATE_7_9;
+ public static final int CODERATE_7_9 = FrontendIsdbs3Coderate.CODERATE_7_9;
/**
* 4/5 code rate.
*/
- public static final int CODERATE_4_5 = Constants.FrontendIsdbs3Coderate.CODERATE_4_5;
+ public static final int CODERATE_4_5 = FrontendIsdbs3Coderate.CODERATE_4_5;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendIsdbs3Coderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendIsdbs3Coderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendIsdbs3Coderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendIsdbs3Coderate.CODERATE_7_8;
/**
* 9/10 code rate.
*/
- public static final int CODERATE_9_10 = Constants.FrontendIsdbs3Coderate.CODERATE_9_10;
+ public static final int CODERATE_9_10 = FrontendIsdbs3Coderate.CODERATE_9_10;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -142,11 +144,11 @@ public class Isdbs3FrontendSettings extends FrontendSettings {
/**
* Rolloff type undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbs3Rolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendIsdbs3Rolloff.UNDEFINED;
/**
* 0,03 Rolloff.
*/
- public static final int ROLLOFF_0_03 = Constants.FrontendIsdbs3Rolloff.ROLLOFF_0_03;
+ public static final int ROLLOFF_0_03 = FrontendIsdbs3Rolloff.ROLLOFF_0_03;
private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index 3cc1aab6a9a6..aab6408e4f42 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -20,7 +20,10 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbsCoderate;
+import android.hardware.tv.tuner.FrontendIsdbsModulation;
+import android.hardware.tv.tuner.FrontendIsdbsRolloff;
+import android.hardware.tv.tuner.FrontendIsdbsStreamIdType;
import android.media.tv.tuner.Tuner;
import java.lang.annotation.Retention;
@@ -42,12 +45,12 @@ public class IsdbsFrontendSettings extends FrontendSettings {
/**
* Uses stream ID.
*/
- public static final int STREAM_ID_TYPE_ID = Constants.FrontendIsdbsStreamIdType.STREAM_ID;
+ public static final int STREAM_ID_TYPE_ID = FrontendIsdbsStreamIdType.STREAM_ID;
/**
* Uses relative number.
*/
public static final int STREAM_ID_TYPE_RELATIVE_NUMBER =
- Constants.FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
+ FrontendIsdbsStreamIdType.RELATIVE_STREAM_NUMBER;
/** @hide */
@@ -61,23 +64,23 @@ public class IsdbsFrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbsModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbsModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbsModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbsModulation.AUTO;
/**
* BPSK Modulation.
*/
- public static final int MODULATION_MOD_BPSK = Constants.FrontendIsdbsModulation.MOD_BPSK;
+ public static final int MODULATION_MOD_BPSK = FrontendIsdbsModulation.MOD_BPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbsModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbsModulation.MOD_QPSK;
/**
* TC8PSK Modulation.
*/
- public static final int MODULATION_MOD_TC8PSK = Constants.FrontendIsdbsModulation.MOD_TC8PSK;
+ public static final int MODULATION_MOD_TC8PSK = FrontendIsdbsModulation.MOD_TC8PSK;
/** @hide */
@@ -91,31 +94,31 @@ public class IsdbsFrontendSettings extends FrontendSettings {
/**
* Code rate undefined.
*/
- public static final int CODERATE_UNDEFINED = Constants.FrontendIsdbsCoderate.UNDEFINED;
+ public static final int CODERATE_UNDEFINED = FrontendIsdbsCoderate.UNDEFINED;
/**
* Hardware is able to detect and set code rate automatically.
*/
- public static final int CODERATE_AUTO = Constants.FrontendIsdbsCoderate.AUTO;
+ public static final int CODERATE_AUTO = FrontendIsdbsCoderate.AUTO;
/**
* 1/2 code rate.
*/
- public static final int CODERATE_1_2 = Constants.FrontendIsdbsCoderate.CODERATE_1_2;
+ public static final int CODERATE_1_2 = FrontendIsdbsCoderate.CODERATE_1_2;
/**
* 2/3 code rate.
*/
- public static final int CODERATE_2_3 = Constants.FrontendIsdbsCoderate.CODERATE_2_3;
+ public static final int CODERATE_2_3 = FrontendIsdbsCoderate.CODERATE_2_3;
/**
* 3/4 code rate.
*/
- public static final int CODERATE_3_4 = Constants.FrontendIsdbsCoderate.CODERATE_3_4;
+ public static final int CODERATE_3_4 = FrontendIsdbsCoderate.CODERATE_3_4;
/**
* 5/6 code rate.
*/
- public static final int CODERATE_5_6 = Constants.FrontendIsdbsCoderate.CODERATE_5_6;
+ public static final int CODERATE_5_6 = FrontendIsdbsCoderate.CODERATE_5_6;
/**
* 7/8 code rate.
*/
- public static final int CODERATE_7_8 = Constants.FrontendIsdbsCoderate.CODERATE_7_8;
+ public static final int CODERATE_7_8 = FrontendIsdbsCoderate.CODERATE_7_8;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -126,11 +129,11 @@ public class IsdbsFrontendSettings extends FrontendSettings {
/**
* Rolloff type undefined.
*/
- public static final int ROLLOFF_UNDEFINED = Constants.FrontendIsdbsRolloff.UNDEFINED;
+ public static final int ROLLOFF_UNDEFINED = FrontendIsdbsRolloff.UNDEFINED;
/**
* 0,35 rolloff.
*/
- public static final int ROLLOFF_0_35 = Constants.FrontendIsdbsRolloff.ROLLOFF_0_35;
+ public static final int ROLLOFF_0_35 = FrontendIsdbsRolloff.ROLLOFF_0_35;
private final int mStreamId;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 6a14d08a4248..de2476a6ba20 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -20,7 +20,9 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendIsdbtBandwidth;
+import android.hardware.tv.tuner.FrontendIsdbtMode;
+import android.hardware.tv.tuner.FrontendIsdbtModulation;
import android.media.tv.tuner.frontend.DvbtFrontendSettings.CodeRate;
import java.lang.annotation.Retention;
@@ -44,27 +46,27 @@ public class IsdbtFrontendSettings extends FrontendSettings {
/**
* Modulation undefined.
*/
- public static final int MODULATION_UNDEFINED = Constants.FrontendIsdbtModulation.UNDEFINED;
+ public static final int MODULATION_UNDEFINED = FrontendIsdbtModulation.UNDEFINED;
/**
* Hardware is able to detect and set modulation automatically
*/
- public static final int MODULATION_AUTO = Constants.FrontendIsdbtModulation.AUTO;
+ public static final int MODULATION_AUTO = FrontendIsdbtModulation.AUTO;
/**
* DQPSK Modulation.
*/
- public static final int MODULATION_MOD_DQPSK = Constants.FrontendIsdbtModulation.MOD_DQPSK;
+ public static final int MODULATION_MOD_DQPSK = FrontendIsdbtModulation.MOD_DQPSK;
/**
* QPSK Modulation.
*/
- public static final int MODULATION_MOD_QPSK = Constants.FrontendIsdbtModulation.MOD_QPSK;
+ public static final int MODULATION_MOD_QPSK = FrontendIsdbtModulation.MOD_QPSK;
/**
* 16QAM Modulation.
*/
- public static final int MODULATION_MOD_16QAM = Constants.FrontendIsdbtModulation.MOD_16QAM;
+ public static final int MODULATION_MOD_16QAM = FrontendIsdbtModulation.MOD_16QAM;
/**
* 64QAM Modulation.
*/
- public static final int MODULATION_MOD_64QAM = Constants.FrontendIsdbtModulation.MOD_64QAM;
+ public static final int MODULATION_MOD_64QAM = FrontendIsdbtModulation.MOD_64QAM;
/** @hide */
@@ -77,23 +79,23 @@ public class IsdbtFrontendSettings extends FrontendSettings {
/**
* Mode undefined.
*/
- public static final int MODE_UNDEFINED = Constants.FrontendIsdbtMode.UNDEFINED;
+ public static final int MODE_UNDEFINED = FrontendIsdbtMode.UNDEFINED;
/**
* Hardware is able to detect and set Mode automatically.
*/
- public static final int MODE_AUTO = Constants.FrontendIsdbtMode.AUTO;
+ public static final int MODE_AUTO = FrontendIsdbtMode.AUTO;
/**
* Mode 1
*/
- public static final int MODE_1 = Constants.FrontendIsdbtMode.MODE_1;
+ public static final int MODE_1 = FrontendIsdbtMode.MODE_1;
/**
* Mode 2
*/
- public static final int MODE_2 = Constants.FrontendIsdbtMode.MODE_2;
+ public static final int MODE_2 = FrontendIsdbtMode.MODE_2;
/**
* Mode 3
*/
- public static final int MODE_3 = Constants.FrontendIsdbtMode.MODE_3;
+ public static final int MODE_3 = FrontendIsdbtMode.MODE_3;
/** @hide */
@@ -107,23 +109,23 @@ public class IsdbtFrontendSettings extends FrontendSettings {
/**
* Bandwidth undefined.
*/
- public static final int BANDWIDTH_UNDEFINED = Constants.FrontendIsdbtBandwidth.UNDEFINED;
+ public static final int BANDWIDTH_UNDEFINED = FrontendIsdbtBandwidth.UNDEFINED;
/**
* Hardware is able to detect and set Bandwidth automatically.
*/
- public static final int BANDWIDTH_AUTO = Constants.FrontendIsdbtBandwidth.AUTO;
+ public static final int BANDWIDTH_AUTO = FrontendIsdbtBandwidth.AUTO;
/**
* 8 MHz bandwidth.
*/
- public static final int BANDWIDTH_8MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
+ public static final int BANDWIDTH_8MHZ = FrontendIsdbtBandwidth.BANDWIDTH_8MHZ;
/**
* 7 MHz bandwidth.
*/
- public static final int BANDWIDTH_7MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
+ public static final int BANDWIDTH_7MHZ = FrontendIsdbtBandwidth.BANDWIDTH_7MHZ;
/**
* 6 MHz bandwidth.
*/
- public static final int BANDWIDTH_6MHZ = Constants.FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
+ public static final int BANDWIDTH_6MHZ = FrontendIsdbtBandwidth.BANDWIDTH_6MHZ;
private final int mModulation;
private final int mBandwidth;
diff --git a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
index 5cf0d319c7c9..3b5419e74769 100644
--- a/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
+++ b/media/java/android/media/tv/tuner/frontend/OnTuneEventListener.java
@@ -18,7 +18,7 @@ package android.media.tv.tuner.frontend;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
+import android.hardware.tv.tuner.FrontendEventType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -37,11 +37,11 @@ public interface OnTuneEventListener {
@interface TuneEvent {}
/** The frontend has locked to the signal specified by the tune method. */
- int SIGNAL_LOCKED = Constants.FrontendEventType.LOCKED;
+ int SIGNAL_LOCKED = FrontendEventType.LOCKED;
/** The frontend is unable to lock to the signal specified by the tune method. */
- int SIGNAL_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+ int SIGNAL_NO_SIGNAL = FrontendEventType.NO_SIGNAL;
/** The frontend has lost the lock to the signal specified by the tune method. */
- int SIGNAL_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+ int SIGNAL_LOST_LOCK = FrontendEventType.LOST_LOCK;
/** Tune Event from the frontend */
void onTuneEvent(@TuneEvent int tuneEvent);
diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp
index c904ca2be00c..65e7e10738ca 100644
--- a/media/java/android/media/tv/tunerresourcemanager/Android.bp
+++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp
@@ -24,7 +24,7 @@ aidl_interface {
enabled: true,
},
cpp: {
- enabled: true,
+ enabled: false,
},
ndk: {
enabled: true,
@@ -33,5 +33,4 @@ aidl_interface {
srcs: [
":framework-media-tv-tunerresourcemanager-sources-aidl",
],
- imports: ["tv_tuner_frontend_info_aidl_interface"],
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index e399fbdfabcf..6f7adbc65318 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -24,7 +24,6 @@ import android.annotation.RequiresFeature;
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.media.tv.tuner.TunerFrontendInfo;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index 483d9720b430..a1f6687a1b81 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -16,13 +16,13 @@
package android.media.tv.tunerresourcemanager;
-import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
+import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
new file mode 100644
index 000000000000..8981ce00d509
--- /dev/null
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
@@ -0,0 +1,41 @@
+/**
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tunerresourcemanager;
+
+/**
+ * FrontendInfo interface that carries tuner frontend information.
+ *
+ * This is used to update the TunerResourceManager fronted resources.
+ * @hide
+ */
+parcelable TunerFrontendInfo {
+ /**
+ * Frontend Handle
+ */
+ int handle;
+
+ /**
+ * Frontend Type
+ */
+ int type;
+
+ /**
+ * Frontends are assigned with the same exclusiveGroupId if they can't
+ * function at same time. For instance, they share same hardware module.
+ */
+ int exclusiveGroupId;
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index bc73f6ad1ad2..e817f2dc9e1d 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -172,8 +172,7 @@ cc_library_shared {
shared_libs: [
"android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.tv.tuner@1.0",
- "android.hardware.tv.tuner@1.1",
+ "android.hardware.tv.tuner-V1-ndk",
"libbinder_ndk",
"libandroid_runtime",
"libcutils",
@@ -183,8 +182,7 @@ cc_library_shared {
"libmedia",
"libnativehelper",
"libutils",
- "tv_tuner_aidl_interface-ndk_platform",
- "tv_tuner_resource_manager_aidl_interface-ndk_platform",
+ "tv_tuner_aidl_interface-ndk",
],
static_libs: [
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 3cf9b0370823..d1c4b3458347 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -14,154 +14,280 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
#define LOG_TAG "TvTuner-JNI"
-#include <utils/Log.h>
-#include "android_media_MediaCodecLinearBlock.h"
#include "android_media_tv_Tuner.h"
-#include "android_runtime/AndroidRuntime.h"
+#include <aidl/android/hardware/tv/tuner/AudioExtraMetaData.h>
+#include <aidl/android/hardware/tv/tuner/AudioStreamType.h>
+#include <aidl/android/hardware/tv/tuner/AvStreamType.h>
+#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <aidl/android/hardware/tv/tuner/Constant64Bit.h>
+#include <aidl/android/hardware/tv/tuner/DataFormat.h>
+#include <aidl/android/hardware/tv/tuner/DemuxAlpFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxAlpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxAlpLengthType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxCapabilities.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterAvSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterDownloadEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterDownloadSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterIpPayloadEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterPesDataSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterPesEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterRecordSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterScIndexMask.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionBits.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSectionSettingsCondition.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSubType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterTemiEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterTsRecordEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpAddress.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxIpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxMmtpFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxMmtpFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
+#include <aidl/android/hardware/tv/tuner/DemuxRecordScIndexType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxScHevcIndex.h>
+#include <aidl/android/hardware/tv/tuner/DemuxScIndex.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTlvFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTlvFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTsFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTsFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxTsIndex.h>
+#include <aidl/android/hardware/tv/tuner/DvrSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAnalogAftFlag.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAnalogSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAnalogSifStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAnalogType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3Bandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3CodeRate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3DemodOutputFormat.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3Fec.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3Modulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3PlpSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3Settings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtsc3TimeInterleaveMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtscModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendAtscSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendCableTimeInterleaveMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbCapabilities.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbCodeRate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbTimeInterleaveMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDtmbTransmissionMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbcAnnex.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbcBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbcModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbcOuterFec.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbcSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsCodeRate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsPilot.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsRolloff.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsScanType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbsVcmMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtCoderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtConstellation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtHierarchy.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtPlpMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendDvbtTransmissionMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendInnerFec.h>
+#include <aidl/android/hardware/tv/tuner/FrontendInterleaveMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbs3Coderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbs3Modulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbs3Rolloff.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbs3Settings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbsCoderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbsModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbsRolloff.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbsSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbsStreamIdType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtBandwidth.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtCoderate.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtGuardInterval.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendIsdbtSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendModulation.h>
+#include <aidl/android/hardware/tv/tuner/FrontendModulationStatus.h>
+#include <aidl/android/hardware/tv/tuner/FrontendRollOff.h>
+#include <aidl/android/hardware/tv/tuner/FrontendScanAtsc3PlpInfo.h>
+#include <aidl/android/hardware/tv/tuner/FrontendScanMessageStandard.h>
+#include <aidl/android/hardware/tv/tuner/FrontendSpectralInversion.h>
+#include <aidl/android/hardware/tv/tuner/FrontendStatus.h>
+#include <aidl/android/hardware/tv/tuner/FrontendStatusAtsc3PlpInfo.h>
+#include <aidl/android/hardware/tv/tuner/FrontendStatusType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendTransmissionMode.h>
+#include <aidl/android/hardware/tv/tuner/FrontendType.h>
+#include <aidl/android/hardware/tv/tuner/LnbPosition.h>
+#include <aidl/android/hardware/tv/tuner/LnbTone.h>
+#include <aidl/android/hardware/tv/tuner/LnbVoltage.h>
+#include <aidl/android/hardware/tv/tuner/PlaybackSettings.h>
+#include <aidl/android/hardware/tv/tuner/RecordSettings.h>
+#include <aidl/android/hardware/tv/tuner/VideoStreamType.h>
+#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
-#include <utils/NativeHandle.h>
+#include <utils/Log.h>
+
+#include "android_media_MediaCodecLinearBlock.h"
+#include "android_runtime/AndroidRuntime.h"
#pragma GCC diagnostic ignored "-Wunused-function"
-using ::android::hardware::Void;
-using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::tv::tuner::V1_0::AudioExtraMetaData;
-using ::android::hardware::tv::tuner::V1_0::DataFormat;
-using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType;
-using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterIpPayloadEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterMediaEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterMmtpRecordEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterTemiEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
-using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
-using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
-using ::android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
-using ::android::hardware::tv::tuner::V1_0::DemuxScHevcIndex;
-using ::android::hardware::tv::tuner::V1_0::DemuxScIndex;
-using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsIndex;
-using ::android::hardware::tv::tuner::V1_0::DvrSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3CodeRate;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3DemodOutputFormat;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Fec;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3PlpSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Settings;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcOuterFec;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsCodeRate;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsPilot;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsVcmMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtPlpMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Coderate;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Settings;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsCoderate;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsStreamIdType;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtCoderate;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
-using ::android::hardware::tv::tuner::V1_0::FrontendType;
-using ::android::hardware::tv::tuner::V1_0::LnbPosition;
-using ::android::hardware::tv::tuner::V1_0::LnbTone;
-using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
-using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
-using ::android::hardware::tv::tuner::V1_0::RecordSettings;
-using ::android::hardware::tv::tuner::V1_1::AudioStreamType;
-using ::android::hardware::tv::tuner::V1_1::AvStreamType;
-using ::android::hardware::tv::tuner::V1_1::Constant;
-using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
-using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
-using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCodeRate;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbSettings;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval;
-using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
-using ::android::hardware::tv::tuner::V1_1::FrontendRollOff;
-using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
-using ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode;
-using ::android::hardware::tv::tuner::V1_1::VideoStreamType;
+using ::aidl::android::hardware::tv::tuner::AudioExtraMetaData;
+using ::aidl::android::hardware::tv::tuner::AudioStreamType;
+using ::aidl::android::hardware::tv::tuner::AvStreamType;
+using ::aidl::android::hardware::tv::tuner::Constant;
+using ::aidl::android::hardware::tv::tuner::Constant64Bit;
+using ::aidl::android::hardware::tv::tuner::DataFormat;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxAlpLengthType;
+using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterAvSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterDownloadEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterDownloadSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterIpPayloadEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMainType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMediaEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMediaEventExtraMetaData;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMmtpRecordEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterPesDataSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterPesEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterRecordSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterScIndexMask;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionBits;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettingsCondition;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSectionSettingsConditionTableInfo;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSubType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterTemiEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterTsRecordEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxIpAddress;
+using ::aidl::android::hardware::tv::tuner::DemuxIpAddressIpAddress;
+using ::aidl::android::hardware::tv::tuner::DemuxIpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxIpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxIpFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
+using ::aidl::android::hardware::tv::tuner::DemuxRecordScIndexType;
+using ::aidl::android::hardware::tv::tuner::DemuxScHevcIndex;
+using ::aidl::android::hardware::tv::tuner::DemuxScIndex;
+using ::aidl::android::hardware::tv::tuner::DemuxTlvFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTlvFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTlvFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxTsIndex;
+using ::aidl::android::hardware::tv::tuner::DvrSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogAftFlag;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogSifStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendAnalogType;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Bandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3CodeRate;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3DemodOutputFormat;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Fec;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Modulation;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3PlpSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3Settings;
+using ::aidl::android::hardware::tv::tuner::FrontendAtsc3TimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendAtscModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendAtscSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendCableTimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbCodeRate;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbTimeInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDtmbTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcAnnex;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcOuterFec;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbcSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsCodeRate;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsPilot;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsRolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsScanType;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbsVcmMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtCoderate;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtConstellation;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtHierarchy;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtPlpMode;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendDvbtTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::FrontendGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendInnerFec;
+using ::aidl::android::hardware::tv::tuner::FrontendInterleaveMode;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Coderate;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Modulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Rolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbs3Settings;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsCoderate;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsRolloff;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbsStreamIdType;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtBandwidth;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtCoderate;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtGuardInterval;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtMode;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendIsdbtSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendModulation;
+using ::aidl::android::hardware::tv::tuner::FrontendModulationStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendRollOff;
+using ::aidl::android::hardware::tv::tuner::FrontendScanAtsc3PlpInfo;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageStandard;
+using ::aidl::android::hardware::tv::tuner::FrontendSpectralInversion;
+using ::aidl::android::hardware::tv::tuner::FrontendStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusAtsc3PlpInfo;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
+using ::aidl::android::hardware::tv::tuner::FrontendTransmissionMode;
+using ::aidl::android::hardware::tv::tuner::FrontendType;
+using ::aidl::android::hardware::tv::tuner::LnbPosition;
+using ::aidl::android::hardware::tv::tuner::LnbTone;
+using ::aidl::android::hardware::tv::tuner::LnbVoltage;
+using ::aidl::android::hardware::tv::tuner::PlaybackSettings;
+using ::aidl::android::hardware::tv::tuner::RecordSettings;
+using ::aidl::android::hardware::tv::tuner::VideoStreamType;
struct fields_t {
jfieldID tunerContext;
@@ -192,17 +318,16 @@ struct fields_t {
static fields_t gFields;
-
static int IP_V4_LENGTH = 4;
static int IP_V6_LENGTH = 16;
void DestroyCallback(const C2Buffer * buf, void *arg) {
android::sp<android::MediaEvent> event = (android::MediaEvent *)arg;
android::Mutex::Autolock autoLock(event->mLock);
- if (event->mLinearBlockObj != NULL) {
+ if (event->mLinearBlockObj != nullptr) {
JNIEnv *env = android::AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(event->mLinearBlockObj);
- event->mLinearBlockObj = NULL;
+ event->mLinearBlockObj = nullptr;
}
event->mAvHandleRefCnt--;
@@ -211,11 +336,9 @@ void DestroyCallback(const C2Buffer * buf, void *arg) {
}
namespace android {
-
/////////////// LnbClientCallbackImpl ///////////////////////
-
void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
- ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
+ ALOGV("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject lnb(env->NewLocalRef(mLnbObj));
if (!env->IsSameObject(lnb, nullptr)) {
@@ -229,14 +352,14 @@ void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
}
}
-void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
- ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
+void LnbClientCallbackImpl::onDiseqcMessage(const vector<uint8_t> &diseqcMessage) {
+ ALOGV("LnbClientCallbackImpl::onDiseqcMessage");
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject lnb(env->NewLocalRef(mLnbObj));
if (!env->IsSameObject(lnb, nullptr)) {
jbyteArray array = env->NewByteArray(diseqcMessage.size());
- env->SetByteArrayRegion(
- array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
+ env->SetByteArrayRegion(array, 0, diseqcMessage.size(),
+ reinterpret_cast<const jbyte *>(&diseqcMessage[0]));
env->CallVoidMethod(
lnb,
gFields.onLnbDiseqcMessageID,
@@ -248,22 +371,21 @@ void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessa
}
void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
- ALOGD("LnbClientCallbackImpl::setLnb");
+ ALOGV("LnbClientCallbackImpl::setLnb");
mLnbObj = lnbObj;
}
LnbClientCallbackImpl::~LnbClientCallbackImpl() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (mLnbObj != NULL) {
+ if (mLnbObj != nullptr) {
env->DeleteWeakGlobalRef(mLnbObj);
- mLnbObj = NULL;
+ mLnbObj = nullptr;
}
}
/////////////// DvrClientCallbackImpl ///////////////////////
-
void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
- ALOGD("DvrClientCallbackImpl::onRecordStatus");
+ ALOGV("DvrClientCallbackImpl::onRecordStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject dvr(env->NewLocalRef(mDvrObj));
if (!env->IsSameObject(dvr, nullptr)) {
@@ -278,7 +400,7 @@ void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
}
void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
- ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
+ ALOGV("DvrClientCallbackImpl::onPlaybackStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject dvr(env->NewLocalRef(mDvrObj));
if (!env->IsSameObject(dvr, nullptr)) {
@@ -293,20 +415,19 @@ void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
}
void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
- ALOGD("DvrClientCallbackImpl::setDvr");
+ ALOGV("DvrClientCallbackImpl::setDvr");
mDvrObj = dvrObj;
}
DvrClientCallbackImpl::~DvrClientCallbackImpl() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (mDvrObj != NULL) {
+ if (mDvrObj != nullptr) {
env->DeleteWeakGlobalRef(mDvrObj);
- mDvrObj = NULL;
+ mDvrObj = nullptr;
}
}
/////////////// C2DataIdInfo ///////////////////////
-
C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize, index) {
CHECK(isGlobal());
CHECK_EQ(C2Param::INFO, kind());
@@ -316,40 +437,44 @@ C2DataIdInfo::C2DataIdInfo(uint32_t index, uint64_t value) : C2Param(kParamSize,
}
/////////////// MediaEvent ///////////////////////
-
-MediaEvent::MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle,
- uint64_t dataId, uint64_t dataSize, jobject obj) : mFilterClient(filterClient),
- mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr),
- mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
+MediaEvent::MediaEvent(sp<FilterClient> filterClient, native_handle_t *avHandle, uint64_t dataId,
+ uint64_t dataSize, jobject obj)
+ : mFilterClient(filterClient),
+ mDataId(dataId),
+ mDataSize(dataSize),
+ mBuffer(nullptr),
+ mDataIdRefCnt(0),
+ mAvHandleRefCnt(0),
+ mIonHandle(nullptr) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
mMediaEventObj = env->NewWeakGlobalRef(obj);
- mAvHandle = native_handle_clone(avHandle.getNativeHandle());
- mLinearBlockObj = NULL;
+ mAvHandle = avHandle;
+ mLinearBlockObj = nullptr;
}
MediaEvent::~MediaEvent() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mMediaEventObj);
- mMediaEventObj = NULL;
+ mMediaEventObj = nullptr;
native_handle_delete(mAvHandle);
- if (mIonHandle != NULL) {
+ if (mIonHandle != nullptr) {
delete mIonHandle;
}
std::shared_ptr<C2Buffer> pC2Buffer = mC2Buffer.lock();
- if (pC2Buffer != NULL) {
+ if (pC2Buffer != nullptr) {
pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
}
- if (mLinearBlockObj != NULL) {
+ if (mLinearBlockObj != nullptr) {
env->DeleteWeakGlobalRef(mLinearBlockObj);
- mLinearBlockObj = NULL;
+ mLinearBlockObj = nullptr;
}
- mFilterClient = NULL;
+ mFilterClient = nullptr;
}
void MediaEvent::finalize() {
- if (mAvHandleRefCnt == 0 && mFilterClient != NULL) {
+ if (mAvHandleRefCnt == 0 && mFilterClient != nullptr) {
mFilterClient->releaseAvHandle(
mAvHandle, mDataIdRefCnt == 0 ? mDataId : 0);
native_handle_close(mAvHandle);
@@ -357,11 +482,11 @@ void MediaEvent::finalize() {
}
jobject MediaEvent::getLinearBlock() {
- ALOGD("MediaEvent::getLinearBlock");
- if (mAvHandle == NULL) {
- return NULL;
+ ALOGV("MediaEvent::getLinearBlock");
+ if (mAvHandle == nullptr) {
+ return nullptr;
}
- if (mLinearBlockObj != NULL) {
+ if (mLinearBlockObj != nullptr) {
return mLinearBlockObj;
}
@@ -374,13 +499,13 @@ jobject MediaEvent::getLinearBlock() {
uint64_t avSharedMemSize = info.size;
if (mAvHandle->numFds == 0) {
- if (avSharedHandle == NULL) {
+ if (avSharedHandle == nullptr) {
ALOGE("Shared AV memory handle is not initialized.");
- return NULL;
+ return nullptr;
}
if (avSharedHandle->numFds == 0) {
ALOGE("Shared AV memory handle is empty.");
- return NULL;
+ return nullptr;
}
fd = avSharedHandle->data[0];
dataSize = avSharedMemSize;
@@ -398,7 +523,7 @@ jobject MediaEvent::getLinearBlock() {
// event has value, use it as the index
memIndex = mAvHandle->data[mAvHandle->numFds];
} else {
- if (avSharedHandle != NULL) {
+ if (avSharedHandle != nullptr) {
numInts = avSharedHandle->numInts;
if (numInts > 0) {
// If the first int in the shared native handle has value, use it as the index
@@ -413,7 +538,7 @@ jobject MediaEvent::getLinearBlock() {
if (block != nullptr) {
// CreateLinearBlock delete mIonHandle after it create block successfully.
// ToDo: coordinate who is response to delete mIonHandle
- mIonHandle = NULL;
+ mIonHandle = nullptr;
JNIEnv *env = AndroidRuntime::getJNIEnv();
std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
context->mBlock = block;
@@ -444,8 +569,8 @@ jobject MediaEvent::getLinearBlock() {
reinterpret_cast<const native_handle_t*>(mIonHandle)));
native_handle_delete(const_cast<native_handle_t*>(
reinterpret_cast<const native_handle_t*>(mIonHandle)));
- mIonHandle = NULL;
- return NULL;
+ mIonHandle = nullptr;
+ return nullptr;
}
}
@@ -455,31 +580,24 @@ uint64_t MediaEvent::getAudioHandle() {
}
/////////////// FilterClientCallbackImpl ///////////////////////
-
-jobjectArray FilterClientCallbackImpl::getSectionEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getSectionEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIII)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterSectionEvent sectionEvent = event.section();
-
- jint tableId = static_cast<jint>(sectionEvent.tableId);
- jint version = static_cast<jint>(sectionEvent.version);
- jint sectionNum = static_cast<jint>(sectionEvent.sectionNum);
- jint dataLength = static_cast<jint>(sectionEvent.dataLength);
+ const DemuxFilterSectionEvent &sectionEvent = event.get<DemuxFilterEvent::Tag::section>();
+ jint tableId = static_cast<jint>(sectionEvent.tableId);
+ jint version = static_cast<jint>(sectionEvent.version);
+ jint sectionNum = static_cast<jint>(sectionEvent.sectionNum);
+ jint dataLength = static_cast<jint>(sectionEvent.dataLength);
- jobject obj =
- env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj = env->NewObject(eventClazz, eventInit, tableId, version, sectionNum, dataLength);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getMediaEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getMediaEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
jmethodID eventInit = env->GetMethodID(eventClazz,
@@ -488,353 +606,284 @@ jobjectArray FilterClientCallbackImpl::getMediaEvent(
"ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V");
jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterMediaEvent mediaEvent = event.media();
-
- jobject audioDescriptor = NULL;
- if (mediaEvent.extraMetaData.getDiscriminator()
- == DemuxFilterMediaEvent::ExtraMetaData::hidl_discriminator::audio) {
- jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
- jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
-
- AudioExtraMetaData ad = mediaEvent.extraMetaData.audio();
- jbyte adFade = static_cast<jbyte>(ad.adFade);
- jbyte adPan = static_cast<jbyte>(ad.adPan);
- jchar versionTextTag = static_cast<jchar>(ad.versionTextTag);
- jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter);
- jbyte adGainFront = static_cast<jbyte>(ad.adGainFront);
- jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround);
-
- audioDescriptor =
- env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag, adGainCenter,
- adGainFront, adGainSurround);
- }
-
- jlong dataLength = static_cast<jlong>(mediaEvent.dataLength);
-
- jint streamId = static_cast<jint>(mediaEvent.streamId);
- jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent);
- jlong pts = static_cast<jlong>(mediaEvent.pts);
- jlong offset = static_cast<jlong>(mediaEvent.offset);
- jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory);
- jlong avDataId = static_cast<jlong>(mediaEvent.avDataId);
- jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber);
- jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData);
-
- jobject obj =
- env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength,
- offset, NULL, isSecureMemory, avDataId, mpuSequenceNumber, isPesPrivateData,
- audioDescriptor);
-
- if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
- sp<MediaEvent> mediaEventSp =
- new MediaEvent(mFilterClient, mediaEvent.avMemory,
+ const DemuxFilterMediaEvent &mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
+ jobject audioDescriptor = nullptr;
+ if (mediaEvent.extraMetaData.getTag() == DemuxFilterMediaEventExtraMetaData::Tag::audio) {
+ jclass adClazz = env->FindClass("android/media/tv/tuner/filter/AudioDescriptor");
+ jmethodID adInit = env->GetMethodID(adClazz, "<init>", "(BBCBBB)V");
+
+ const AudioExtraMetaData &ad =
+ mediaEvent.extraMetaData.get<DemuxFilterMediaEventExtraMetaData::Tag::audio>();
+ jbyte adFade = static_cast<jbyte>(ad.adFade);
+ jbyte adPan = static_cast<jbyte>(ad.adPan);
+ jchar versionTextTag = static_cast<jchar>(ad.versionTextTag);
+ jbyte adGainCenter = static_cast<jbyte>(ad.adGainCenter);
+ jbyte adGainFront = static_cast<jbyte>(ad.adGainFront);
+ jbyte adGainSurround = static_cast<jbyte>(ad.adGainSurround);
+
+ audioDescriptor = env->NewObject(adClazz, adInit, adFade, adPan, versionTextTag,
+ adGainCenter, adGainFront, adGainSurround);
+ }
+
+ jlong dataLength = static_cast<jlong>(mediaEvent.dataLength);
+ jint streamId = static_cast<jint>(mediaEvent.streamId);
+ jboolean isPtsPresent = static_cast<jboolean>(mediaEvent.isPtsPresent);
+ jlong pts = static_cast<jlong>(mediaEvent.pts);
+ jlong offset = static_cast<jlong>(mediaEvent.offset);
+ jboolean isSecureMemory = static_cast<jboolean>(mediaEvent.isSecureMemory);
+ jlong avDataId = static_cast<jlong>(mediaEvent.avDataId);
+ jint mpuSequenceNumber = static_cast<jint>(mediaEvent.mpuSequenceNumber);
+ jboolean isPesPrivateData = static_cast<jboolean>(mediaEvent.isPesPrivateData);
+
+ jobject obj = env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, dataLength,
+ offset, nullptr, isSecureMemory, avDataId, mpuSequenceNumber,
+ isPesPrivateData, audioDescriptor);
+
+ if (mediaEvent.avMemory.fds.size() > 0 || mediaEvent.avDataId != 0) {
+ sp<MediaEvent> mediaEventSp =
+ new MediaEvent(mFilterClient, makeFromAidl(mediaEvent.avMemory),
mediaEvent.avDataId, dataLength + offset, obj);
- mediaEventSp->mAvHandleRefCnt++;
- env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
- mediaEventSp->incStrong(obj);
- }
-
- env->SetObjectArrayElement(arr, i, obj);
+ mediaEventSp->mAvHandleRefCnt++;
+ env->SetLongField(obj, eventContext, (jlong)mediaEventSp.get());
+ mediaEventSp->incStrong(obj);
}
- return arr;
+
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getPesEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getPesEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(III)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterPesEvent pesEvent = event.pes();
-
- jint streamId = static_cast<jint>(pesEvent.streamId);
- jint dataLength = static_cast<jint>(pesEvent.dataLength);
- jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber);
+ const DemuxFilterPesEvent &pesEvent = event.get<DemuxFilterEvent::Tag::pes>();
+ jint streamId = static_cast<jint>(pesEvent.streamId);
+ jint dataLength = static_cast<jint>(pesEvent.dataLength);
+ jint mpuSequenceNumber = static_cast<jint>(pesEvent.mpuSequenceNumber);
- jobject obj =
- env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj = env->NewObject(eventClazz, eventInit, streamId, dataLength, mpuSequenceNumber);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getTsRecordEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
- const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
+void FilterClientCallbackImpl::getTsRecordEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TsRecordEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIJJI)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterTsRecordEvent tsRecordEvent = event.tsRecord();
- DemuxPid pid = tsRecordEvent.pid;
-
- jint jpid = static_cast<jint>(Constant::INVALID_TS_PID);
-
- if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::tPid) {
- jpid = static_cast<jint>(pid.tPid());
- } else if (pid.getDiscriminator() == DemuxPid::hidl_discriminator::mmtpPid) {
- jpid = static_cast<jint>(pid.mmtpPid());
- }
-
- jint sc = 0;
-
- if (tsRecordEvent.scIndexMask.getDiscriminator()
- == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::sc) {
- sc = static_cast<jint>(tsRecordEvent.scIndexMask.sc());
- } else if (tsRecordEvent.scIndexMask.getDiscriminator()
- == DemuxFilterTsRecordEvent::ScIndexMask::hidl_discriminator::scHevc) {
- sc = static_cast<jint>(tsRecordEvent.scIndexMask.scHevc());
- }
+ const DemuxFilterTsRecordEvent &tsRecordEvent = event.get<DemuxFilterEvent::Tag::tsRecord>();
+ DemuxPid pid = tsRecordEvent.pid;
- jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask);
+ jint jpid = static_cast<jint>(Constant::INVALID_TS_PID);
+ if (pid.getTag() == DemuxPid::Tag::tPid) {
+ jpid = static_cast<jint>(pid.get<DemuxPid::Tag::tPid>());
+ } else if (pid.getTag() == DemuxPid::Tag::mmtpPid) {
+ jpid = static_cast<jint>(pid.get<DemuxPid::Tag::mmtpPid>());
+ }
- jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber);
+ jint sc = 0;
+ if (tsRecordEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scIndex) {
+ sc = static_cast<jint>(
+ tsRecordEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scIndex>());
+ } else if (tsRecordEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scHevc) {
+ sc = static_cast<jint>(
+ tsRecordEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scHevc>());
+ }
- jlong pts;
- jlong firstMbInSlice;
- if (eventsExt.size() > i && eventsExt[i].getDiscriminator() ==
- DemuxFilterEventExt::Event::hidl_discriminator::tsRecord) {
- pts = static_cast<jlong>(eventsExt[i].tsRecord().pts);
- firstMbInSlice = static_cast<jint>(eventsExt[i].tsRecord().firstMbInSlice);
- } else {
- pts = static_cast<jlong>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
- firstMbInSlice = static_cast<jint>(Constant::INVALID_FIRST_MACROBLOCK_IN_SLICE);
- }
+ jint ts = static_cast<jint>(tsRecordEvent.tsIndexMask);
+ jlong byteNumber = static_cast<jlong>(tsRecordEvent.byteNumber);
+ jlong pts = static_cast<jlong>(tsRecordEvent.pts);
+ jint firstMbInSlice = static_cast<jint>(tsRecordEvent.firstMbInSlice);
- jobject obj =
- env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber,
- pts, firstMbInSlice);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj =
+ env->NewObject(eventClazz, eventInit, jpid, ts, sc, byteNumber, pts, firstMbInSlice);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getMmtpRecordEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
- const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
+void FilterClientCallbackImpl::getMmtpRecordEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MmtpRecordEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IJIJII)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
-
- DemuxFilterMmtpRecordEvent mmtpRecordEvent = event.mmtpRecord();
-
- jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask);
- jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber);
-
- jint mpuSequenceNumber;
- jlong pts;
- jlong firstMbInSlice;
- jlong tsIndexMask;
+ const DemuxFilterMmtpRecordEvent &mmtpRecordEvent =
+ event.get<DemuxFilterEvent::Tag::mmtpRecord>();
+ jint scHevcIndexMask = static_cast<jint>(mmtpRecordEvent.scHevcIndexMask);
+ jlong byteNumber = static_cast<jlong>(mmtpRecordEvent.byteNumber);
+ jint mpuSequenceNumber = static_cast<jint>(mmtpRecordEvent.mpuSequenceNumber);
+ jlong pts = static_cast<jlong>(mmtpRecordEvent.pts);
+ jint firstMbInSlice = static_cast<jint>(mmtpRecordEvent.firstMbInSlice);
+ jlong tsIndexMask = static_cast<jlong>(mmtpRecordEvent.tsIndexMask);
- if (eventsExt.size() > i && eventsExt[i].getDiscriminator() ==
- DemuxFilterEventExt::Event::hidl_discriminator::mmtpRecord) {
- mpuSequenceNumber = static_cast<jint>(eventsExt[i].mmtpRecord().mpuSequenceNumber);
- pts = static_cast<jlong>(eventsExt[i].mmtpRecord().pts);
- firstMbInSlice = static_cast<jint>(eventsExt[i].mmtpRecord().firstMbInSlice);
- tsIndexMask = static_cast<jint>(eventsExt[i].mmtpRecord().tsIndexMask);
- } else {
- mpuSequenceNumber =
- static_cast<jint>(Constant::INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM);
- pts = static_cast<jlong>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
- firstMbInSlice = static_cast<jint>(Constant::INVALID_FIRST_MACROBLOCK_IN_SLICE);
- tsIndexMask = 0;
- }
-
- jobject obj =
- env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber,
- mpuSequenceNumber, pts, firstMbInSlice, tsIndexMask);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj = env->NewObject(eventClazz, eventInit, scHevcIndexMask, byteNumber,
+ mpuSequenceNumber, pts, firstMbInSlice, tsIndexMask);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getDownloadEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getDownloadEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(IIIII)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterDownloadEvent downloadEvent = event.download();
+ const DemuxFilterDownloadEvent &downloadEvent = event.get<DemuxFilterEvent::Tag::download>();
+ jint itemId = static_cast<jint>(downloadEvent.itemId);
+ jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber);
+ jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex);
+ jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex);
+ jint dataLength = static_cast<jint>(downloadEvent.dataLength);
- jint itemId = static_cast<jint>(downloadEvent.itemId);
- jint mpuSequenceNumber = static_cast<jint>(downloadEvent.mpuSequenceNumber);
- jint itemFragmentIndex = static_cast<jint>(downloadEvent.itemFragmentIndex);
- jint lastItemFragmentIndex = static_cast<jint>(downloadEvent.lastItemFragmentIndex);
- jint dataLength = static_cast<jint>(downloadEvent.dataLength);
-
- jobject obj =
- env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber, itemFragmentIndex,
- lastItemFragmentIndex, dataLength);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj = env->NewObject(eventClazz, eventInit, itemId, mpuSequenceNumber,
+ itemFragmentIndex, lastItemFragmentIndex, dataLength);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getIpPayloadEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getIpPayloadEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterIpPayloadEvent ipPayloadEvent = event.ipPayload();
- jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength);
- jobject obj = env->NewObject(eventClazz, eventInit, dataLength);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ const DemuxFilterIpPayloadEvent &ipPayloadEvent = event.get<DemuxFilterEvent::Tag::ipPayload>();
+ jint dataLength = static_cast<jint>(ipPayloadEvent.dataLength);
+ jobject obj = env->NewObject(eventClazz, eventInit, dataLength);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getTemiEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
+void FilterClientCallbackImpl::getTemiEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(JB[B)V");
- for (int i = 0; i < events.size(); i++) {
- auto event = events[i];
- DemuxFilterTemiEvent temiEvent = event.temi();
- jlong pts = static_cast<jlong>(temiEvent.pts);
- jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag);
- std::vector<uint8_t> descrData = temiEvent.descrData;
+ const DemuxFilterTemiEvent &temiEvent = event.get<DemuxFilterEvent::Tag::temi>();
+ jlong pts = static_cast<jlong>(temiEvent.pts);
+ jbyte descrTag = static_cast<jbyte>(temiEvent.descrTag);
+ std::vector<uint8_t> descrData = temiEvent.descrData;
- jbyteArray array = env->NewByteArray(descrData.size());
- env->SetByteArrayRegion(
- array, 0, descrData.size(), reinterpret_cast<jbyte*>(&descrData[0]));
+ jbyteArray array = env->NewByteArray(descrData.size());
+ env->SetByteArrayRegion(array, 0, descrData.size(), reinterpret_cast<jbyte *>(&descrData[0]));
- jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array);
- env->SetObjectArrayElement(arr, i, obj);
- }
- return arr;
+ jobject obj = env->NewObject(eventClazz, eventInit, pts, descrTag, array);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getScramblingStatusEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
+void FilterClientCallbackImpl::getScramblingStatusEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/ScramblingStatusEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
- auto scramblingStatus = eventsExt[0].monitorEvent().scramblingStatus();
- jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(scramblingStatus));
- env->SetObjectArrayElement(arr, 0, obj);
- return arr;
+ const DemuxFilterMonitorEvent &scramblingStatus =
+ event.get<DemuxFilterEvent::Tag::monitorEvent>()
+ .get<DemuxFilterMonitorEvent::Tag::scramblingStatus>();
+ jobject obj = env->NewObject(eventClazz, eventInit, scramblingStatus);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getIpCidChangeEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
+void FilterClientCallbackImpl::getIpCidChangeEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpCidChangeEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
- auto cid = eventsExt[0].monitorEvent().cid();
- jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(cid));
- env->SetObjectArrayElement(arr, 0, obj);
- return arr;
+ const DemuxFilterMonitorEvent &cid = event.get<DemuxFilterEvent::Tag::monitorEvent>()
+ .get<DemuxFilterMonitorEvent::Tag::cid>();
+ jobject obj = env->NewObject(eventClazz, eventInit, cid);
+ env->SetObjectArrayElement(arr, size, obj);
}
-jobjectArray FilterClientCallbackImpl::getRestartEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
+void FilterClientCallbackImpl::getRestartEvent(jobjectArray &arr, const int size,
+ const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/RestartEvent");
jmethodID eventInit = env->GetMethodID(eventClazz, "<init>", "(I)V");
- auto startId = eventsExt[0].startId();
+ const int32_t &startId = event.get<DemuxFilterEvent::Tag::startId>();
jobject obj = env->NewObject(eventClazz, eventInit, static_cast<jint>(startId));
- env->SetObjectArrayElement(arr, 0, obj);
- return arr;
+ env->SetObjectArrayElement(arr, size, obj);
}
-void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
- const DemuxFilterEventExt& filterEventExt) {
- ALOGD("FilterClientCallbackImpl::onFilterEvent_1_1");
-
+void FilterClientCallbackImpl::onFilterEvent(const vector<DemuxFilterEvent> &events) {
+ ALOGV("FilterClientCallbackImpl::onFilterEvent");
JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent");
jobjectArray array;
- std::vector<DemuxFilterEvent::Event> events = filterEvent.events;
- std::vector<DemuxFilterEventExt::Event> eventsExt = filterEventExt.events;
- jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/FilterEvent");
+ if (!events.empty()) {
+ array = env->NewObjectArray(events.size(), eventClazz, nullptr);
+ }
- if (events.empty() && !eventsExt.empty()) {
- // Monitor event should be sent with one DemuxFilterMonitorEvent in DemuxFilterEventExt.
- array = env->NewObjectArray(1, eventClazz, NULL);
- auto eventExt = eventsExt[0];
- switch (eventExt.getDiscriminator()) {
- case DemuxFilterEventExt::Event::hidl_discriminator::monitorEvent: {
- switch (eventExt.monitorEvent().getDiscriminator()) {
- case DemuxFilterMonitorEvent::hidl_discriminator::scramblingStatus: {
- array = getScramblingStatusEvent(array, eventsExt);
- break;
- }
- case DemuxFilterMonitorEvent::hidl_discriminator::cid: {
- array = getIpCidChangeEvent(array, eventsExt);
- break;
- }
- default: {
- break;
- }
- }
+ for (int i = 0, arraySize = 0; i < events.size(); i++) {
+ const DemuxFilterEvent &event = events[i];
+ switch (event.getTag()) {
+ case DemuxFilterEvent::Tag::media: {
+ getMediaEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEventExt::Event::hidl_discriminator::startId: {
- array = getRestartEvent(array, eventsExt);
+ case DemuxFilterEvent::Tag::section: {
+ getSectionEvent(array, arraySize, event);
+ arraySize++;
break;
}
- default: {
- break;
- }
- }
- }
-
- if (!events.empty()) {
- array = env->NewObjectArray(events.size(), eventClazz, NULL);
- auto event = events[0];
- switch (event.getDiscriminator()) {
- case DemuxFilterEvent::Event::hidl_discriminator::media: {
- array = getMediaEvent(array, events);
+ case DemuxFilterEvent::Tag::pes: {
+ getPesEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::section: {
- array = getSectionEvent(array, events);
+ case DemuxFilterEvent::Tag::tsRecord: {
+ getTsRecordEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::pes: {
- array = getPesEvent(array, events);
+ case DemuxFilterEvent::Tag::mmtpRecord: {
+ getMmtpRecordEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::tsRecord: {
- array = getTsRecordEvent(array, events, eventsExt);
+ case DemuxFilterEvent::Tag::download: {
+ getDownloadEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::mmtpRecord: {
- array = getMmtpRecordEvent(array, events, eventsExt);
+ case DemuxFilterEvent::Tag::ipPayload: {
+ getIpPayloadEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::download: {
- array = getDownloadEvent(array, events);
+ case DemuxFilterEvent::Tag::temi: {
+ getTemiEvent(array, arraySize, event);
+ arraySize++;
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::ipPayload: {
- array = getIpPayloadEvent(array, events);
+ case DemuxFilterEvent::Tag::monitorEvent: {
+ switch (event.get<DemuxFilterEvent::Tag::monitorEvent>().getTag()) {
+ case DemuxFilterMonitorEvent::Tag::scramblingStatus: {
+ getScramblingStatusEvent(array, arraySize, event);
+ arraySize++;
+ break;
+ }
+ case DemuxFilterMonitorEvent::Tag::cid: {
+ getIpCidChangeEvent(array, arraySize, event);
+ arraySize++;
+ break;
+ }
+ default: {
+ ALOGE("FilterClientCallbackImpl::onFilterEvent: unknown MonitorEvent");
+ break;
+ }
+ }
break;
}
- case DemuxFilterEvent::Event::hidl_discriminator::temi: {
- array = getTemiEvent(array, events);
+ case DemuxFilterEvent::Tag::startId: {
+ getRestartEvent(array, arraySize, event);
+ arraySize++;
break;
}
default: {
+ ALOGE("FilterClientCallbackImpl::onFilterEvent: unknown DemuxFilterEvent");
break;
}
}
@@ -846,22 +895,13 @@ void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterE
gFields.onFilterEventID,
array);
} else {
- ALOGE("FilterClientCallbackImpl::onFilterEvent_1_1:"
- "Filter object has been freed. Ignoring callback.");
+ ALOGE("FilterClientCallbackImpl::onFilterEvent:"
+ "Filter object has been freed. Ignoring callback.");
}
}
-void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
- ALOGD("FilterClientCallbackImpl::onFilterEvent");
- std::vector<DemuxFilterEventExt::Event> emptyEventsExt;
- DemuxFilterEventExt emptyFilterEventExt {
- .events = emptyEventsExt,
- };
- return onFilterEvent_1_1(filterEvent, emptyFilterEventExt);
-}
-
void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
- ALOGD("FilterClientCallbackImpl::onFilterStatus");
+ ALOGV("FilterClientCallbackImpl::onFilterStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject filter(env->NewLocalRef(mFilterObj));
if (!env->IsSameObject(filter, nullptr)) {
@@ -876,7 +916,7 @@ void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
}
void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
- ALOGD("FilterClientCallbackImpl::setFilter");
+ ALOGV("FilterClientCallbackImpl::setFilter");
// Java Object
mFilterObj = filterObj;
mFilterClient = filterClient;
@@ -884,19 +924,18 @@ void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filte
FilterClientCallbackImpl::~FilterClientCallbackImpl() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (mFilterObj != NULL) {
+ if (mFilterObj != nullptr) {
env->DeleteWeakGlobalRef(mFilterObj);
- mFilterObj = NULL;
+ mFilterObj = nullptr;
}
- mFilterClient = NULL;
+ mFilterClient = nullptr;
}
/////////////// FrontendClientCallbackImpl ///////////////////////
-
FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
- ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
+ ALOGV("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobject frontend(env->NewLocalRef(mObject));
if (!env->IsSameObject(frontend, nullptr)) {
@@ -912,7 +951,7 @@ void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
void FrontendClientCallbackImpl::onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message) {
- ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
+ ALOGV("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
jobject frontend(env->NewLocalRef(mObject));
@@ -923,7 +962,7 @@ void FrontendClientCallbackImpl::onScanMessage(
}
switch(type) {
case FrontendScanMessageType::LOCKED: {
- if (message.isLocked()) {
+ if (message.get<FrontendScanMessage::Tag::isLocked>()) {
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onLocked", "()V"));
@@ -931,7 +970,7 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::END: {
- if (message.isEnd()) {
+ if (message.get<FrontendScanMessage::Tag::isEnd>()) {
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onScanStopped", "()V"));
@@ -939,14 +978,12 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::PROGRESS_PERCENT: {
- env->CallVoidMethod(
- frontend,
- env->GetMethodID(clazz, "onProgress", "(I)V"),
- (jint) message.progressPercent());
+ env->CallVoidMethod(frontend, env->GetMethodID(clazz, "onProgress", "(I)V"),
+ (jint)message.get<FrontendScanMessage::Tag::progressPercent>());
break;
}
case FrontendScanMessageType::FREQUENCY: {
- std::vector<uint32_t> v = message.frequencies();
+ std::vector<int32_t> v = message.get<FrontendScanMessage::Tag::frequencies>();
jintArray freqs = env->NewIntArray(v.size());
env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -957,7 +994,7 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::SYMBOL_RATE: {
- std::vector<uint32_t> v = message.symbolRates();
+ std::vector<int32_t> v = message.get<FrontendScanMessage::Tag::symbolRates>();
jintArray symbolRates = env->NewIntArray(v.size());
env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -968,21 +1005,17 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::HIERARCHY: {
- env->CallVoidMethod(
- frontend,
- env->GetMethodID(clazz, "onHierarchy", "(I)V"),
- (jint) message.hierarchy());
+ env->CallVoidMethod(frontend, env->GetMethodID(clazz, "onHierarchy", "(I)V"),
+ (jint)message.get<FrontendScanMessage::Tag::hierarchy>());
break;
}
case FrontendScanMessageType::ANALOG_TYPE: {
- env->CallVoidMethod(
- frontend,
- env->GetMethodID(clazz, "onSignalType", "(I)V"),
- (jint) message.analogType());
+ env->CallVoidMethod(frontend, env->GetMethodID(clazz, "onSignalType", "(I)V"),
+ (jint)message.get<FrontendScanMessage::Tag::analogType>());
break;
}
case FrontendScanMessageType::PLP_IDS: {
- std::vector<uint8_t> v = message.plpIds();
+ std::vector<uint8_t> v = message.get<FrontendScanMessage::Tag::plpIds>();
std::vector<jint> jintV(v.begin(), v.end());
jintArray plpIds = env->NewIntArray(v.size());
env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
@@ -994,7 +1027,7 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::GROUP_IDS: {
- std::vector<uint8_t> v = message.groupIds();
+ std::vector<uint8_t> v = message.get<FrontendScanMessage::groupIds>();
std::vector<jint> jintV(v.begin(), v.end());
jintArray groupIds = env->NewIntArray(v.size());
env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
@@ -1006,7 +1039,7 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::INPUT_STREAM_IDS: {
- std::vector<uint16_t> v = message.inputStreamIds();
+ std::vector<char16_t> v = message.get<FrontendScanMessage::inputStreamIds>();
std::vector<jint> jintV(v.begin(), v.end());
jintArray streamIds = env->NewIntArray(v.size());
env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
@@ -1018,24 +1051,22 @@ void FrontendClientCallbackImpl::onScanMessage(
break;
}
case FrontendScanMessageType::STANDARD: {
- FrontendScanMessage::Standard std = message.std();
+ FrontendScanMessageStandard std = message.get<FrontendScanMessage::std>();
jint standard;
- if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
- standard = (jint) std.sStd();
+ if (std.getTag() == FrontendScanMessageStandard::Tag::sStd) {
+ standard = (jint)std.get<FrontendScanMessageStandard::Tag::sStd>();
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
standard);
- } else if (std.getDiscriminator() ==
- FrontendScanMessage::Standard::hidl_discriminator::tStd) {
- standard = (jint) std.tStd();
+ } else if (std.getTag() == FrontendScanMessageStandard::Tag::tStd) {
+ standard = (jint)std.get<FrontendScanMessageStandard::Tag::tStd>();
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
standard);
- } else if (std.getDiscriminator() ==
- FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
- standard = (jint) std.sifStd();
+ } else if (std.getTag() == FrontendScanMessageStandard::Tag::sifStd) {
+ standard = (jint)std.get<FrontendScanMessageStandard::Tag::sifStd>();
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
@@ -1046,8 +1077,9 @@ void FrontendClientCallbackImpl::onScanMessage(
case FrontendScanMessageType::ATSC3_PLP_INFO: {
jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpInfo");
jmethodID init = env->GetMethodID(plpClazz, "<init>", "(IZ)V");
- std::vector<FrontendScanAtsc3PlpInfo> plpInfos = message.atsc3PlpInfos();
- jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
+ std::vector<FrontendScanAtsc3PlpInfo> plpInfos =
+ message.get<FrontendScanMessage::atsc3PlpInfos>();
+ jobjectArray array = env->NewObjectArray(plpInfos.size(), plpClazz, nullptr);
for (int i = 0; i < plpInfos.size(); i++) {
auto info = plpInfos[i];
@@ -1064,82 +1096,67 @@ void FrontendClientCallbackImpl::onScanMessage(
array);
break;
}
- }
-}
-
-void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
- const FrontendScanMessageExt1_1& message) {
- ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
- jobject frontend(env->NewLocalRef(mObject));
- if (env->IsSameObject(frontend, nullptr)) {
- ALOGE("FrontendClientCallbackImpl::onScanMessageExt1_1:"
- "Frontend object has been freed. Ignoring callback.");
- return;
- }
- switch(type) {
- case FrontendScanMessageTypeExt1_1::MODULATION: {
- jint modulation = -1;
- switch (message.modulation().getDiscriminator()) {
- case FrontendModulation::hidl_discriminator::dvbc: {
- modulation = (jint) message.modulation().dvbc();
+ case FrontendScanMessageType::MODULATION: {
+ jint modulationType = -1;
+ FrontendModulation modulation = message.get<FrontendScanMessage::modulation>();
+ switch (modulation.getTag()) {
+ case FrontendModulation::Tag::dvbc: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::dvbc>();
break;
}
- case FrontendModulation::hidl_discriminator::dvbt: {
- modulation = (jint) message.modulation().dvbt();
+ case FrontendModulation::Tag::dvbt: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::dvbt>();
break;
}
- case FrontendModulation::hidl_discriminator::dvbs: {
- modulation = (jint) message.modulation().dvbs();
+ case FrontendModulation::Tag::dvbs: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::dvbs>();
break;
}
- case FrontendModulation::hidl_discriminator::isdbs: {
- modulation = (jint) message.modulation().isdbs();
+ case FrontendModulation::Tag::isdbs: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::isdbs>();
break;
}
- case FrontendModulation::hidl_discriminator::isdbs3: {
- modulation = (jint) message.modulation().isdbs3();
+ case FrontendModulation::Tag::isdbs3: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::isdbs3>();
break;
}
- case FrontendModulation::hidl_discriminator::isdbt: {
- modulation = (jint) message.modulation().isdbt();
+ case FrontendModulation::Tag::isdbt: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::isdbt>();
break;
}
- case FrontendModulation::hidl_discriminator::atsc: {
- modulation = (jint) message.modulation().atsc();
+ case FrontendModulation::Tag::atsc: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::atsc>();
break;
}
- case FrontendModulation::hidl_discriminator::atsc3: {
- modulation = (jint) message.modulation().atsc3();
+ case FrontendModulation::Tag::atsc3: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::atsc3>();
break;
}
- case FrontendModulation::hidl_discriminator::dtmb: {
- modulation = (jint) message.modulation().dtmb();
+ case FrontendModulation::Tag::dtmb: {
+ modulationType = (jint)modulation.get<FrontendModulation::Tag::dtmb>();
break;
}
default: {
break;
}
}
- if (modulation > 0) {
- env->CallVoidMethod(
- frontend,
- env->GetMethodID(clazz, "onModulationReported", "(I)V"),
- modulation);
+ if (modulationType > 0) {
+ env->CallVoidMethod(frontend,
+ env->GetMethodID(clazz, "onModulationReported", "(I)V"),
+ modulationType);
}
break;
}
- case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
- bool isHighPriority = message.isHighPriority();
+ case FrontendScanMessageType::HIGH_PRIORITY: {
+ bool isHighPriority = message.get<FrontendScanMessage::Tag::isHighPriority>();
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onPriorityReported", "(Z)V"),
isHighPriority);
break;
}
- case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
- jint dvbcAnnex = (jint) message.annex();
+ case FrontendScanMessageType::DVBC_ANNEX: {
+ jint dvbcAnnex = (jint)message.get<FrontendScanMessage::Tag::annex>();
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"),
@@ -1153,57 +1170,57 @@ void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1
FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
- if (mObject != NULL) {
+ if (mObject != nullptr) {
env->DeleteWeakGlobalRef(mObject);
- mObject = NULL;
+ mObject = nullptr;
}
}
/////////////// Tuner ///////////////////////
-
sp<TunerClient> JTuner::mTunerClient;
-JTuner::JTuner(JNIEnv *env, jobject thiz)
- : mClass(NULL) {
+JTuner::JTuner(JNIEnv *env, jobject thiz) : mClass(nullptr) {
jclass clazz = env->GetObjectClass(thiz);
- CHECK(clazz != NULL);
+ CHECK(clazz != nullptr);
mClass = (jclass)env->NewGlobalRef(clazz);
mObject = env->NewWeakGlobalRef(thiz);
- if (mTunerClient == NULL) {
+ if (mTunerClient == nullptr) {
mTunerClient = new TunerClient();
}
+
+ mSharedFeId = (int)Constant::INVALID_FRONTEND_ID;
}
JTuner::~JTuner() {
- if (mFeClient != NULL) {
+ if (mFeClient != nullptr) {
mFeClient->close();
}
- if (mDemuxClient != NULL) {
+ if (mDemuxClient != nullptr) {
mDemuxClient->close();
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
- mTunerClient = NULL;
- mFeClient = NULL;
- mDemuxClient = NULL;
- mClass = NULL;
- mObject = NULL;
+ mTunerClient = nullptr;
+ mFeClient = nullptr;
+ mDemuxClient = nullptr;
+ mClass = nullptr;
+ mObject = nullptr;
}
jint JTuner::getTunerVersion() {
- ALOGD("JTuner::getTunerVersion()");
- return (jint) mTunerClient->getHalTunerVersion();
+ ALOGV("JTuner::getTunerVersion()");
+ return (jint)mTunerClient->getHalTunerVersion();
}
jobject JTuner::getFrontendIds() {
- ALOGD("JTuner::getFrontendIds()");
- vector<FrontendId> ids = mTunerClient->getFrontendIds();
+ ALOGV("JTuner::getFrontendIds()");
+ vector<int32_t> ids = mTunerClient->getFrontendIds();
if (ids.size() == 0) {
ALOGW("Frontend isn't available");
- return NULL;
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1214,9 +1231,9 @@ jobject JTuner::getFrontendIds() {
jclass integerClazz = env->FindClass("java/lang/Integer");
jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
- for (int i=0; i < ids.size(); i++) {
- jobject idObj = env->NewObject(integerClazz, intInit, ids[i]);
- env->CallBooleanMethod(obj, arrayListAdd, idObj);
+ for (int i = 0; i < ids.size(); i++) {
+ jobject idObj = env->NewObject(integerClazz, intInit, ids[i]);
+ env->CallBooleanMethod(obj, arrayListAdd, idObj);
}
return obj;
}
@@ -1224,14 +1241,14 @@ jobject JTuner::getFrontendIds() {
jobject JTuner::openFrontendByHandle(int feHandle) {
// TODO: Handle reopening frontend with different handle
sp<FrontendClient> feClient = mTunerClient->openFrontend(feHandle);
- if (feClient == NULL) {
+ if (feClient == nullptr) {
ALOGE("Failed to open frontend");
- return NULL;
+ return nullptr;
}
mFeClient = feClient;
mFeId = mFeClient->getId();
- if (mDemuxClient != NULL) {
+ if (mDemuxClient != nullptr) {
mDemuxClient->setFrontendDataSource(mFeClient);
}
@@ -1240,10 +1257,11 @@ jobject JTuner::openFrontendByHandle(int feHandle) {
if (env->IsSameObject(tuner, nullptr)) {
ALOGE("openFrontendByHandle"
"Tuner object has been freed. Failed to open frontend.");
- return NULL;
+ return nullptr;
}
- sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
+ sp<FrontendClientCallbackImpl> feClientCb =
+ new FrontendClientCallbackImpl(env->NewWeakGlobalRef(mObject));
mFeClient->setCallback(feClientCb);
// TODO: add more fields to frontend
return env->NewObject(
@@ -1253,127 +1271,135 @@ jobject JTuner::openFrontendByHandle(int feHandle) {
(jint) mFeId);
}
-jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+int JTuner::shareFrontend(int feId) {
+ if (mFeClient != nullptr) {
+ ALOGE("Cannot share frontend:%d because this session is already holding %d",
+ feId, mFeClient->getId());
+ return (int)Result::INVALID_STATE;
+ }
+
+ mSharedFeId = feId;
+ return (int)Result::SUCCESS;
+}
+
+jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
- jint typeCap = caps.analogCaps().typeCap;
- jint sifStandardCap = caps.analogCaps().sifStandardCap;
+ jint typeCap = caps.get<FrontendCapabilities::Tag::analogCaps>().typeCap;
+ jint sifStandardCap = caps.get<FrontendCapabilities::Tag::analogCaps>().sifStandardCap;
return env->NewObject(clazz, capsInit, typeCap, sifStandardCap);
}
-jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getAtsc3FrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V");
- jint bandwidthCap = caps.atsc3Caps().bandwidthCap;
- jint modulationCap = caps.atsc3Caps().modulationCap;
- jint timeInterleaveModeCap = caps.atsc3Caps().timeInterleaveModeCap;
- jint codeRateCap = caps.atsc3Caps().codeRateCap;
- jint fecCap = caps.atsc3Caps().fecCap;
- jint demodOutputFormatCap = caps.atsc3Caps().demodOutputFormatCap;
+ jint bandwidthCap = caps.get<FrontendCapabilities::Tag::atsc3Caps>().bandwidthCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::atsc3Caps>().modulationCap;
+ jint timeInterleaveModeCap =
+ caps.get<FrontendCapabilities::Tag::atsc3Caps>().timeInterleaveModeCap;
+ jint codeRateCap = caps.get<FrontendCapabilities::Tag::atsc3Caps>().codeRateCap;
+ jint fecCap = caps.get<FrontendCapabilities::Tag::atsc3Caps>().fecCap;
+ jint demodOutputFormatCap =
+ caps.get<FrontendCapabilities::Tag::atsc3Caps>().demodOutputFormatCap;
return env->NewObject(clazz, capsInit, bandwidthCap, modulationCap, timeInterleaveModeCap,
codeRateCap, fecCap, demodOutputFormatCap);
}
-jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getAtscFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(I)V");
- jint modulationCap = caps.atscCaps().modulationCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::atscCaps>().modulationCap;
return env->NewObject(clazz, capsInit, modulationCap);
}
-jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getDvbcFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V");
- jint modulationCap = caps.dvbcCaps().modulationCap;
- jlong fecCap = caps.dvbcCaps().fecCap;
- jint annexCap = caps.dvbcCaps().annexCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::dvbcCaps>().modulationCap;
+ jlong fecCap = caps.get<FrontendCapabilities::Tag::dvbcCaps>().fecCap;
+ jint annexCap = caps.get<FrontendCapabilities::Tag::dvbcCaps>().annexCap;
return env->NewObject(clazz, capsInit, modulationCap, fecCap, annexCap);
}
-jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getDvbsFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IJI)V");
- jint modulationCap = caps.dvbsCaps().modulationCap;
- jlong innerfecCap = caps.dvbsCaps().innerfecCap;
- jint standard = caps.dvbsCaps().standard;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::dvbsCaps>().modulationCap;
+ jlong innerfecCap = caps.get<FrontendCapabilities::Tag::dvbsCaps>().innerfecCap;
+ jint standard = caps.get<FrontendCapabilities::Tag::dvbsCaps>().standard;
return env->NewObject(clazz, capsInit, modulationCap, innerfecCap, standard);
}
-jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getDvbtFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIZZ)V");
- jint transmissionModeCap = caps.dvbtCaps().transmissionModeCap;
- jint bandwidthCap = caps.dvbtCaps().bandwidthCap;
- jint constellationCap = caps.dvbtCaps().constellationCap;
- jint coderateCap = caps.dvbtCaps().coderateCap;
- jint hierarchyCap = caps.dvbtCaps().hierarchyCap;
- jint guardIntervalCap = caps.dvbtCaps().guardIntervalCap;
- jboolean isT2Supported = caps.dvbtCaps().isT2Supported;
- jboolean isMisoSupported = caps.dvbtCaps().isMisoSupported;
+ jint transmissionModeCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().transmissionModeCap;
+ jint bandwidthCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().bandwidthCap;
+ jint constellationCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().constellationCap;
+ jint coderateCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().coderateCap;
+ jint hierarchyCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().hierarchyCap;
+ jint guardIntervalCap = caps.get<FrontendCapabilities::Tag::dvbtCaps>().guardIntervalCap;
+ jboolean isT2Supported = caps.get<FrontendCapabilities::Tag::dvbtCaps>().isT2Supported;
+ jboolean isMisoSupported = caps.get<FrontendCapabilities::Tag::dvbtCaps>().isMisoSupported;
return env->NewObject(clazz, capsInit, transmissionModeCap, bandwidthCap, constellationCap,
coderateCap, hierarchyCap, guardIntervalCap, isT2Supported, isMisoSupported);
}
-jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getIsdbs3FrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
- jint modulationCap = caps.isdbs3Caps().modulationCap;
- jint coderateCap = caps.isdbs3Caps().coderateCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::isdbs3Caps>().modulationCap;
+ jint coderateCap = caps.get<FrontendCapabilities::Tag::isdbs3Caps>().coderateCap;
return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
}
-jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getIsdbsFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
- jint modulationCap = caps.isdbsCaps().modulationCap;
- jint coderateCap = caps.isdbsCaps().coderateCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::isdbsCaps>().modulationCap;
+ jint coderateCap = caps.get<FrontendCapabilities::Tag::isdbsCaps>().coderateCap;
return env->NewObject(clazz, capsInit, modulationCap, coderateCap);
}
-jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
+jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIII)V");
- jint modeCap = caps.isdbtCaps().modeCap;
- jint bandwidthCap = caps.isdbtCaps().bandwidthCap;
- jint modulationCap = caps.isdbtCaps().modulationCap;
- jint coderateCap = caps.isdbtCaps().coderateCap;
- jint guardIntervalCap = caps.isdbtCaps().guardIntervalCap;
+ jint modeCap = caps.get<FrontendCapabilities::Tag::isdbtCaps>().modeCap;
+ jint bandwidthCap = caps.get<FrontendCapabilities::Tag::isdbtCaps>().bandwidthCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::isdbtCaps>().modulationCap;
+ jint coderateCap = caps.get<FrontendCapabilities::Tag::isdbtCaps>().coderateCap;
+ jint guardIntervalCap = caps.get<FrontendCapabilities::Tag::isdbtCaps>().guardIntervalCap;
return env->NewObject(clazz, capsInit, modeCap, bandwidthCap, modulationCap, coderateCap,
guardIntervalCap);
}
-jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, int id) {
+jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V");
- shared_ptr<FrontendDtmbCapabilities> dtmbCaps = mTunerClient->getFrontendDtmbCapabilities(id);
- if (dtmbCaps == NULL) {
- return NULL;
- }
-
- jint modulationCap = dtmbCaps->modulationCap;
- jint transmissionModeCap = dtmbCaps->transmissionModeCap;
- jint guardIntervalCap = dtmbCaps->guardIntervalCap;
- jint interleaveModeCap = dtmbCaps->interleaveModeCap;
- jint codeRateCap = dtmbCaps->codeRateCap;
- jint bandwidthCap = dtmbCaps->bandwidthCap;
+ jint modulationCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().modulationCap;
+ jint transmissionModeCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().transmissionModeCap;
+ jint guardIntervalCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().guardIntervalCap;
+ jint interleaveModeCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().interleaveModeCap;
+ jint codeRateCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().codeRateCap;
+ jint bandwidthCap = caps.get<FrontendCapabilities::Tag::dtmbCaps>().bandwidthCap;
return env->NewObject(clazz, capsInit, modulationCap, transmissionModeCap, guardIntervalCap,
interleaveModeCap, codeRateCap, bandwidthCap);
@@ -1382,8 +1408,8 @@ jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, int id) {
jobject JTuner::getFrontendInfo(int id) {
shared_ptr<FrontendInfo> feInfo;
feInfo = mTunerClient->getFrontendInfo(id);
- if (feInfo == NULL) {
- return NULL;
+ if (feInfo == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1402,70 +1428,60 @@ jobject JTuner::getFrontendInfo(int id) {
env->SetIntArrayRegion(
statusCaps, 0, feInfo->statusCaps.size(),
reinterpret_cast<jint*>(&feInfo->statusCaps[0]));
- FrontendInfo::FrontendCapabilities caps = feInfo->frontendCaps;
-
- jobject jcaps = NULL;
-
- if (feInfo->type == static_cast<FrontendType>(
- ::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
- jcaps = getDtmbFrontendCaps(env, id);
- }
+ FrontendCapabilities caps = feInfo->frontendCaps;
+ jobject jcaps = nullptr;
switch(feInfo->type) {
case FrontendType::ANALOG:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::analogCaps == caps.getTag()) {
jcaps = getAnalogFrontendCaps(env, caps);
}
break;
case FrontendType::ATSC3:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::atsc3Caps == caps.getTag()) {
jcaps = getAtsc3FrontendCaps(env, caps);
}
break;
case FrontendType::ATSC:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::atscCaps == caps.getTag()) {
jcaps = getAtscFrontendCaps(env, caps);
}
break;
case FrontendType::DVBC:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::dvbcCaps == caps.getTag()) {
jcaps = getDvbcFrontendCaps(env, caps);
}
break;
case FrontendType::DVBS:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::dvbsCaps == caps.getTag()) {
jcaps = getDvbsFrontendCaps(env, caps);
}
break;
case FrontendType::DVBT:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::dvbtCaps == caps.getTag()) {
jcaps = getDvbtFrontendCaps(env, caps);
}
break;
case FrontendType::ISDBS:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::isdbsCaps == caps.getTag()) {
jcaps = getIsdbsFrontendCaps(env, caps);
}
break;
case FrontendType::ISDBS3:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::isdbs3Caps == caps.getTag()) {
jcaps = getIsdbs3FrontendCaps(env, caps);
}
break;
case FrontendType::ISDBT:
- if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps
- == caps.getDiscriminator()) {
+ if (FrontendCapabilities::Tag::isdbtCaps == caps.getTag()) {
jcaps = getIsdbtFrontendCaps(env, caps);
}
break;
+ case FrontendType::DTMB:
+ if (FrontendCapabilities::Tag::dtmbCaps == caps.getTag()) {
+ jcaps = getDtmbFrontendCaps(env, caps);
+ }
+ break;
default:
break;
}
@@ -1476,21 +1492,21 @@ jobject JTuner::getFrontendInfo(int id) {
}
jobject JTuner::openLnbByHandle(int handle) {
- if (mTunerClient == NULL) {
- return NULL;
+ if (mTunerClient == nullptr) {
+ return nullptr;
}
sp<LnbClient> lnbClient;
sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
lnbClient = mTunerClient->openLnb(handle);
- if (lnbClient == NULL) {
+ if (lnbClient == nullptr) {
ALOGD("Failed to open lnb, handle = %d", handle);
- return NULL;
+ return nullptr;
}
if (lnbClient->setCallback(callback) != Result::SUCCESS) {
ALOGD("Failed to set lnb callback");
- return NULL;
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1506,8 +1522,8 @@ jobject JTuner::openLnbByHandle(int handle) {
}
jobject JTuner::openLnbByName(jstring name) {
- if (mTunerClient == NULL) {
- return NULL;
+ if (mTunerClient == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1515,14 +1531,14 @@ jobject JTuner::openLnbByName(jstring name) {
sp<LnbClient> lnbClient;
sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
lnbClient = mTunerClient->openLnbByName(lnbName);
- if (lnbClient == NULL) {
+ if (lnbClient == nullptr) {
ALOGD("Failed to open lnb by name, name = %s", lnbName.c_str());
- return NULL;
+ return nullptr;
}
if (lnbClient->setCallback(callback) != Result::SUCCESS) {
ALOGD("Failed to set lnb callback");
- return NULL;
+ return nullptr;
}
jobject lnbObj = env->NewObject(
@@ -1536,12 +1552,12 @@ jobject JTuner::openLnbByName(jstring name) {
return lnbObj;
}
-int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) {
+int JTuner::tune(const FrontendSettings &settings) {
if (mFeClient == nullptr) {
ALOGE("frontend is not initialized");
return (int)Result::INVALID_STATE;
}
- return (int) mFeClient->tune(settings, settingsExt1_1);
+ return (int)mFeClient->tune(settings);
}
int JTuner::stopTune() {
@@ -1552,18 +1568,17 @@ int JTuner::stopTune() {
return (int) mFeClient->stopTune();
}
-int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- if (mFeClient == NULL) {
+int JTuner::scan(const FrontendSettings &settings, FrontendScanType scanType) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Result::INVALID_STATE;
}
- Result result = mFeClient->scan(settings, scanType, settingsExt1_1);
+ Result result = mFeClient->scan(settings, scanType);
return (int)result;
}
int JTuner::stopScan() {
- if (mFeClient == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Result::INVALID_STATE;
}
@@ -1572,11 +1587,11 @@ int JTuner::stopScan() {
}
int JTuner::setLnb(sp<LnbClient> lnbClient) {
- if (mFeClient == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Result::INVALID_STATE;
}
- if (lnbClient == NULL) {
+ if (lnbClient == nullptr) {
ALOGE("lnb is not initialized");
return (int)Result::INVALID_STATE;
}
@@ -1585,7 +1600,7 @@ int JTuner::setLnb(sp<LnbClient> lnbClient) {
}
int JTuner::setLna(bool enable) {
- if (mFeClient == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Result::INVALID_STATE;
}
@@ -1600,12 +1615,14 @@ Result JTuner::openDemux(int handle) {
if (mDemuxClient == nullptr) {
mDemuxClient = mTunerClient->openDemux(handle);
- if (mDemuxClient == NULL) {
+ if (mDemuxClient == nullptr) {
ALOGE("Failed to open demux");
return Result::UNKNOWN_ERROR;
}
- if (mFeClient != NULL) {
- mDemuxClient->setFrontendDataSource(mFeClient);
+ if (mFeClient != nullptr) {
+ return mDemuxClient->setFrontendDataSource(mFeClient);
+ } else if (mSharedFeId != (int)Constant::INVALID_FRONTEND_ID) {
+ return mDemuxClient->setFrontendDataSourceById(mSharedFeId);
}
}
@@ -1615,26 +1632,28 @@ Result JTuner::openDemux(int handle) {
jint JTuner::close() {
Result res = Result::SUCCESS;
- if (mFeClient != NULL) {
+ if (mFeClient != nullptr) {
res = mFeClient->close();
if (res != Result::SUCCESS) {
- return (jint) res;
+ return (jint)res;
}
- mFeClient = NULL;
+ mFeClient = nullptr;
}
- if (mDemuxClient != NULL) {
+ if (mDemuxClient != nullptr) {
res = mDemuxClient->close();
if (res != Result::SUCCESS) {
- return (jint) res;
+ return (jint)res;
}
- mDemuxClient = NULL;
+ mDemuxClient = nullptr;
}
- return (jint) res;
+
+ mSharedFeId = (int)Constant::INVALID_FRONTEND_ID;
+ return (jint)res;
}
jobject JTuner::getAvSyncHwId(sp<FilterClient> filterClient) {
- if (mDemuxClient == NULL) {
- return NULL;
+ if (mDemuxClient == nullptr) {
+ return nullptr;
}
int avSyncHwId = mDemuxClient->getAvSyncHwId(filterClient);
@@ -1644,12 +1663,12 @@ jobject JTuner::getAvSyncHwId(sp<FilterClient> filterClient) {
jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
return env->NewObject(integerClazz, intInit, avSyncHwId);
}
- return NULL;
+ return nullptr;
}
jobject JTuner::getAvSyncTime(jint id) {
- if (mDemuxClient == NULL) {
- return NULL;
+ if (mDemuxClient == nullptr) {
+ return nullptr;
}
long time = mDemuxClient->getAvSyncTime((int)id);
if (time >= 0) {
@@ -1658,19 +1677,18 @@ jobject JTuner::getAvSyncTime(jint id) {
jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
return env->NewObject(longClazz, longInit, static_cast<jlong>(time));
}
- return NULL;
+ return nullptr;
}
int JTuner::connectCiCam(jint id) {
- if (mDemuxClient == NULL) {
+ if (mDemuxClient == nullptr) {
return (int)Result::NOT_INITIALIZED;
}
- Result r = mDemuxClient->connectCiCam((int)id);
- return (int) r;
+ return (int)mDemuxClient->connectCiCam((int)id);
}
int JTuner::linkCiCam(int id) {
- if (mFeClient == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Constant::INVALID_LTS_ID;
}
@@ -1678,35 +1696,30 @@ int JTuner::linkCiCam(int id) {
}
int JTuner::disconnectCiCam() {
- if (mDemuxClient == NULL) {
+ if (mDemuxClient == nullptr) {
return (int)Result::NOT_INITIALIZED;
}
- Result r = mDemuxClient->disconnectCiCam();
- return (int) r;
+ return (int)mDemuxClient->disconnectCiCam();
}
-
int JTuner::unlinkCiCam(int id) {
- if (mFeClient == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend client is not initialized");
return (int)Result::INVALID_STATE;
}
-
- Result r = mFeClient->unlinkCiCamToFrontend(id);
-
- return (int) r;
+ return (int)mFeClient->unlinkCiCamToFrontend(id);
}
jobject JTuner::openDescrambler() {
- ALOGD("JTuner::openDescrambler");
+ ALOGV("JTuner::openDescrambler");
if (mTunerClient == nullptr || mDemuxClient == nullptr) {
- return NULL;
+ return nullptr;
}
sp<DescramblerClient> descramblerClient = mTunerClient->openDescrambler(0/*unused*/);
- if (descramblerClient == NULL) {
+ if (descramblerClient == nullptr) {
ALOGD("Failed to open descrambler");
- return NULL;
+ return nullptr;
}
descramblerClient->setDemuxSource(mDemuxClient);
@@ -1724,31 +1737,28 @@ jobject JTuner::openDescrambler() {
}
jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
- if (mDemuxClient == NULL) {
- return NULL;
+ if (mDemuxClient == nullptr) {
+ return nullptr;
}
sp<FilterClient> filterClient;
sp<FilterClientCallbackImpl> callback = new FilterClientCallbackImpl();
filterClient = mDemuxClient->openFilter(type, bufferSize, callback);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to open filter, type = %d", type.mainType);
- return NULL;
+ return nullptr;
}
- uint64_t fId;
+ int64_t fId;
Result res = filterClient->getId64Bit(fId);
if (res != Result::SUCCESS) {
- uint32_t id;
+ int32_t id;
filterClient->getId(id);
- fId = static_cast<uint64_t>(id);
+ fId = static_cast<int64_t>(id);
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
- jobject filterObj =
- env->NewObject(
- env->FindClass("android/media/tv/tuner/filter/Filter"),
- gFields.filterInitID,
- (jlong) fId);
+ jobject filterObj = env->NewObject(env->FindClass("android/media/tv/tuner/filter/Filter"),
+ gFields.filterInitID, (jlong)fId);
filterClient->incStrong(filterObj);
env->SetLongField(filterObj, gFields.filterContext, (jlong)filterClient.get());
@@ -1758,8 +1768,8 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
}
jobject JTuner::openTimeFilter() {
- if (mDemuxClient == NULL) {
- return NULL;
+ if (mDemuxClient == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1768,9 +1778,9 @@ jobject JTuner::openTimeFilter() {
env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
gFields.timeFilterInitID);
sp<TimeFilterClient> timeFilterClient = mDemuxClient->openTimeFilter();
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed to open time filter.");
- return NULL;
+ return nullptr;
}
timeFilterClient->incStrong(timeFilterObj);
env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterClient.get());
@@ -1780,15 +1790,15 @@ jobject JTuner::openTimeFilter() {
jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
ALOGD("JTuner::openDvr");
- if (mDemuxClient == NULL) {
- return NULL;
+ if (mDemuxClient == nullptr) {
+ return nullptr;
}
sp<DvrClient> dvrClient;
sp<DvrClientCallbackImpl> callback = new DvrClientCallbackImpl();
dvrClient = mDemuxClient->openDvr(type, (int) bufferSize, callback);
- if (dvrClient == NULL) {
- return NULL;
+ if (dvrClient == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1815,14 +1825,14 @@ jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
}
jobject JTuner::getDemuxCaps() {
- if (mTunerClient == NULL) {
- return NULL;
+ if (mTunerClient == nullptr) {
+ return nullptr;
}
shared_ptr<DemuxCapabilities> caps;
caps = mTunerClient->getDemuxCaps();
- if (caps == NULL) {
- return NULL;
+ if (caps == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1852,25 +1862,19 @@ jobject JTuner::getDemuxCaps() {
}
jobject JTuner::getFrontendStatus(jintArray types) {
- if (mFeClient == NULL) {
- return NULL;
+ if (mFeClient == nullptr) {
+ return nullptr;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
jsize size = env->GetArrayLength(types);
jint intTypes[size];
env->GetIntArrayRegion(types, 0, size, intTypes);
std::vector<FrontendStatusType> v;
- std::vector<FrontendStatusTypeExt1_1> v_1_1;
for (int i = 0; i < size; i++) {
- if (isV1_1ExtendedStatusType(intTypes[i])) {
- v_1_1.push_back(static_cast<FrontendStatusTypeExt1_1>(intTypes[i]));
- } else {
- v.push_back(static_cast<FrontendStatusType>(intTypes[i]));
- }
+ v.push_back(static_cast<FrontendStatusType>(intTypes[i]));
}
- hidl_vec<FrontendStatus> status = mFeClient->getStatus(v);
- hidl_vec<FrontendStatusExt1_1> status_1_1 = mFeClient->getStatusExtended_1_1(v_1_1);
+ vector<FrontendStatus> status = mFeClient->getStatus(v);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
@@ -1882,96 +1886,114 @@ jobject JTuner::getFrontendStatus(jintArray types) {
jmethodID initBoolean = env->GetMethodID(booleanClazz, "<init>", "(Z)V");
for (auto s : status) {
- switch(s.getDiscriminator()) {
- case FrontendStatus::hidl_discriminator::isDemodLocked: {
+ switch (s.getTag()) {
+ case FrontendStatus::Tag::isDemodLocked: {
jfieldID field = env->GetFieldID(clazz, "mIsDemodLocked", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isDemodLocked()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(
+ s.get<FrontendStatus::Tag::isDemodLocked>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatus::hidl_discriminator::snr: {
+ case FrontendStatus::Tag::snr: {
jfieldID field = env->GetFieldID(clazz, "mSnr", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.snr()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::snr>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::ber: {
+ case FrontendStatus::Tag::ber: {
jfieldID field = env->GetFieldID(clazz, "mBer", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.ber()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::ber>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::per: {
+ case FrontendStatus::Tag::per: {
jfieldID field = env->GetFieldID(clazz, "mPer", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.per()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::per>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::preBer: {
+ case FrontendStatus::Tag::preBer: {
jfieldID field = env->GetFieldID(clazz, "mPerBer", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.preBer()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::preBer>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::signalQuality: {
+ case FrontendStatus::Tag::signalQuality: {
jfieldID field = env->GetFieldID(clazz, "mSignalQuality", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.signalQuality()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(
+ s.get<FrontendStatus::Tag::signalQuality>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::signalStrength: {
+ case FrontendStatus::Tag::signalStrength: {
jfieldID field = env->GetFieldID(clazz, "mSignalStrength", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.signalStrength()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(
+ s.get<FrontendStatus::Tag::signalStrength>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::symbolRate: {
+ case FrontendStatus::Tag::symbolRate: {
jfieldID field = env->GetFieldID(clazz, "mSymbolRate", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.symbolRate()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::symbolRate>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::innerFec: {
+ case FrontendStatus::Tag::innerFec: {
jfieldID field = env->GetFieldID(clazz, "mInnerFec", "Ljava/lang/Long;");
jclass longClazz = env->FindClass("java/lang/Long");
jmethodID initLong = env->GetMethodID(longClazz, "<init>", "(J)V");
- jobject newLongObj = env->NewObject(
- longClazz, initLong, static_cast<jlong>(s.innerFec()));
+ jobject newLongObj =
+ env->NewObject(longClazz, initLong,
+ static_cast<jlong>(s.get<FrontendStatus::Tag::innerFec>()));
env->SetObjectField(statusObj, field, newLongObj);
break;
}
- case FrontendStatus::hidl_discriminator::modulation: {
+ case FrontendStatus::Tag::modulationStatus: {
jfieldID field = env->GetFieldID(clazz, "mModulation", "Ljava/lang/Integer;");
- FrontendModulationStatus modulation = s.modulation();
+ FrontendModulationStatus modulation =
+ s.get<FrontendStatus::Tag::modulationStatus>();
jint intModulation;
bool valid = true;
- switch(modulation.getDiscriminator()) {
- case FrontendModulationStatus::hidl_discriminator::dvbc: {
- intModulation = static_cast<jint>(modulation.dvbc());
+ switch (modulation.getTag()) {
+ case FrontendModulationStatus::Tag::dvbc: {
+ intModulation = static_cast<jint>(
+ modulation.get<FrontendModulationStatus::Tag::dvbc>());
break;
}
- case FrontendModulationStatus::hidl_discriminator::dvbs: {
- intModulation = static_cast<jint>(modulation.dvbs());
+ case FrontendModulationStatus::Tag::dvbs: {
+ intModulation = static_cast<jint>(
+ modulation.get<FrontendModulationStatus::Tag::dvbs>());
break;
}
- case FrontendModulationStatus::hidl_discriminator::isdbs: {
- intModulation = static_cast<jint>(modulation.isdbs());
+ case FrontendModulationStatus::Tag::isdbs: {
+ intModulation = static_cast<jint>(
+ modulation.get<FrontendModulationStatus::Tag::isdbs>());
break;
}
- case FrontendModulationStatus::hidl_discriminator::isdbs3: {
- intModulation = static_cast<jint>(modulation.isdbs3());
+ case FrontendModulationStatus::Tag::isdbs3: {
+ intModulation = static_cast<jint>(
+ modulation.get<FrontendModulationStatus::Tag::isdbs3>());
break;
}
- case FrontendModulationStatus::hidl_discriminator::isdbt: {
- intModulation = static_cast<jint>(modulation.isdbt());
+ case FrontendModulationStatus::Tag::isdbt: {
+ intModulation = static_cast<jint>(
+ modulation.get<FrontendModulationStatus::Tag::isdbt>());
break;
}
default: {
@@ -1985,51 +2007,58 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatus::hidl_discriminator::inversion: {
+ case FrontendStatus::Tag::inversion: {
jfieldID field = env->GetFieldID(clazz, "mInversion", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.inversion()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::inversion>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::lnbVoltage: {
+ case FrontendStatus::Tag::lnbVoltage: {
jfieldID field = env->GetFieldID(clazz, "mLnbVoltage", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.lnbVoltage()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::lnbVoltage>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::plpId: {
+ case FrontendStatus::Tag::plpId: {
jfieldID field = env->GetFieldID(clazz, "mPlpId", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.plpId()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::plpId>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::isEWBS: {
+ case FrontendStatus::Tag::isEWBS: {
jfieldID field = env->GetFieldID(clazz, "mIsEwbs", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isEWBS()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(s.get<FrontendStatus::Tag::isEWBS>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatus::hidl_discriminator::agc: {
+ case FrontendStatus::Tag::agc: {
jfieldID field = env->GetFieldID(clazz, "mAgc", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.agc()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::agc>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::isLnaOn: {
+ case FrontendStatus::Tag::isLnaOn: {
jfieldID field = env->GetFieldID(clazz, "mIsLnaOn", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isLnaOn()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(
+ s.get<FrontendStatus::Tag::isLnaOn>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatus::hidl_discriminator::isLayerError: {
+ case FrontendStatus::Tag::isLayerError: {
jfieldID field = env->GetFieldID(clazz, "mIsLayerErrors", "[Z");
- hidl_vec<bool> layerErr = s.isLayerError();
+ vector<bool> layerErr = s.get<FrontendStatus::Tag::isLayerError>();
jbooleanArray valObj = env->NewBooleanArray(layerErr.size());
@@ -2040,44 +2069,48 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- case FrontendStatus::hidl_discriminator::mer: {
+ case FrontendStatus::Tag::mer: {
jfieldID field = env->GetFieldID(clazz, "mMer", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.mer()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::mer>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::freqOffset: {
+ case FrontendStatus::Tag::freqOffset: {
jfieldID field = env->GetFieldID(clazz, "mFreqOffset", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.freqOffset()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::freqOffset>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::hierarchy: {
+ case FrontendStatus::Tag::hierarchy: {
jfieldID field = env->GetFieldID(clazz, "mHierarchy", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.hierarchy()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::hierarchy>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatus::hidl_discriminator::isRfLocked: {
+ case FrontendStatus::Tag::isRfLocked: {
jfieldID field = env->GetFieldID(clazz, "mIsRfLocked", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isRfLocked()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(
+ s.get<FrontendStatus::Tag::isRfLocked>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatus::hidl_discriminator::plpInfo: {
+ case FrontendStatus::Tag::plpInfo: {
jfieldID field = env->GetFieldID(clazz, "mPlpInfo",
"[Landroid/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo;");
jclass plpClazz = env->FindClass(
"android/media/tv/tuner/frontend/FrontendStatus$Atsc3PlpTuningInfo");
jmethodID initPlp = env->GetMethodID(plpClazz, "<init>", "(IZI)V");
- hidl_vec<FrontendStatusAtsc3PlpInfo> plpInfos = s.plpInfo();
-
- jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, NULL);
+ vector<FrontendStatusAtsc3PlpInfo> plpInfos = s.get<FrontendStatus::Tag::plpInfo>();
+ jobjectArray valObj = env->NewObjectArray(plpInfos.size(), plpClazz, nullptr);
for (int i = 0; i < plpInfos.size(); i++) {
auto info = plpInfos[i];
jint plpId = (jint) info.plpId;
@@ -2091,74 +2124,75 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- default: {
- break;
- }
- }
- }
-
- for (auto s : status_1_1) {
- switch(s.getDiscriminator()) {
- case FrontendStatusExt1_1::hidl_discriminator::modulations: {
+ case FrontendStatus::Tag::modulations: {
jfieldID field = env->GetFieldID(clazz, "mModulationsExt", "[I");
- std::vector<FrontendModulation> v = s.modulations();
+ std::vector<FrontendModulation> v = s.get<FrontendStatus::Tag::modulations>();
jintArray valObj = env->NewIntArray(v.size());
bool valid = false;
jint m[1];
for (int i = 0; i < v.size(); i++) {
auto modulation = v[i];
- switch(modulation.getDiscriminator()) {
- case FrontendModulation::hidl_discriminator::dvbc: {
- m[0] = static_cast<jint>(modulation.dvbc());
+ switch (modulation.getTag()) {
+ case FrontendModulation::Tag::dvbc: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::dvbc>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::dvbs: {
- m[0] = static_cast<jint>(modulation.dvbs());
+ case FrontendModulation::Tag::dvbs: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::dvbs>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::dvbt: {
- m[0] = static_cast<jint>(modulation.dvbt());
+ case FrontendModulation::Tag::dvbt: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::dvbt>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::isdbs: {
- m[0] = static_cast<jint>(modulation.isdbs());
+ case FrontendModulation::Tag::isdbs: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::isdbs>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::isdbs3: {
- m[0] = static_cast<jint>(modulation.isdbs3());
+ case FrontendModulation::Tag::isdbs3: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::isdbs3>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::isdbt: {
- m[0] = static_cast<jint>(modulation.isdbt());
+ case FrontendModulation::Tag::isdbt: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::isdbt>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::atsc: {
- m[0] = static_cast<jint>(modulation.atsc());
+ case FrontendModulation::Tag::atsc: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::atsc>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::atsc3: {
- m[0] = static_cast<jint>(modulation.atsc3());
+ case FrontendModulation::Tag::atsc3: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::atsc3>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
}
- case FrontendModulation::hidl_discriminator::dtmb: {
- m[0] = static_cast<jint>(modulation.dtmb());
+ case FrontendModulation::Tag::dtmb: {
+ m[0] = static_cast<jint>(
+ modulation.get<FrontendModulation::Tag::dtmb>());
env->SetIntArrayRegion(valObj, i, 1, m);
valid = true;
break;
@@ -2172,9 +2206,9 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::bers: {
+ case FrontendStatus::Tag::bers: {
jfieldID field = env->GetFieldID(clazz, "mBers", "[I");
- std::vector<uint32_t> v = s.bers();
+ std::vector<int32_t> v = s.get<FrontendStatus::Tag::bers>();
jintArray valObj = env->NewIntArray(v.size());
env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -2182,10 +2216,9 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::codeRates: {
+ case FrontendStatus::Tag::codeRates: {
jfieldID field = env->GetFieldID(clazz, "mCodeRates", "[I");
- std::vector<::android::hardware::tv::tuner::V1_1::FrontendInnerFec> v
- = s.codeRates();
+ std::vector<FrontendInnerFec> v = s.get<FrontendStatus::Tag::codeRates>();
jintArray valObj = env->NewIntArray(v.size());
env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -2193,30 +2226,35 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::bandwidth: {
+ case FrontendStatus::Tag::bandwidth: {
jfieldID field = env->GetFieldID(clazz, "mBandwidth", "Ljava/lang/Integer;");
- auto bandwidth = s.bandwidth();
+ auto bandwidth = s.get<FrontendStatus::Tag::bandwidth>();
jint intBandwidth;
bool valid = true;
- switch(bandwidth.getDiscriminator()) {
- case FrontendBandwidth::hidl_discriminator::atsc3: {
- intBandwidth = static_cast<jint>(bandwidth.atsc3());
+ switch (bandwidth.getTag()) {
+ case FrontendBandwidth::Tag::atsc3: {
+ intBandwidth =
+ static_cast<jint>(bandwidth.get<FrontendBandwidth::Tag::atsc3>());
break;
}
- case FrontendBandwidth::hidl_discriminator::dvbt: {
- intBandwidth = static_cast<jint>(bandwidth.dvbt());
+ case FrontendBandwidth::Tag::dvbt: {
+ intBandwidth =
+ static_cast<jint>(bandwidth.get<FrontendBandwidth::Tag::dvbt>());
break;
}
- case FrontendBandwidth::hidl_discriminator::dvbc: {
- intBandwidth = static_cast<jint>(bandwidth.dvbc());
+ case FrontendBandwidth::Tag::dvbc: {
+ intBandwidth =
+ static_cast<jint>(bandwidth.get<FrontendBandwidth::Tag::dvbc>());
break;
}
- case FrontendBandwidth::hidl_discriminator::isdbt: {
- intBandwidth = static_cast<jint>(bandwidth.isdbt());
+ case FrontendBandwidth::Tag::isdbt: {
+ intBandwidth =
+ static_cast<jint>(bandwidth.get<FrontendBandwidth::Tag::isdbt>());
break;
}
- case FrontendBandwidth::hidl_discriminator::dtmb: {
- intBandwidth = static_cast<jint>(bandwidth.dtmb());
+ case FrontendBandwidth::Tag::dtmb: {
+ intBandwidth =
+ static_cast<jint>(bandwidth.get<FrontendBandwidth::Tag::dtmb>());
break;
}
default:
@@ -2229,22 +2267,25 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::interval: {
+ case FrontendStatus::Tag::interval: {
jfieldID field = env->GetFieldID(clazz, "mGuardInterval", "Ljava/lang/Integer;");
- auto interval = s.interval();
+ auto interval = s.get<FrontendStatus::Tag::interval>();
jint intInterval;
bool valid = true;
- switch(interval.getDiscriminator()) {
- case FrontendGuardInterval::hidl_discriminator::dvbt: {
- intInterval = static_cast<jint>(interval.dvbt());
+ switch (interval.getTag()) {
+ case FrontendGuardInterval::Tag::dvbt: {
+ intInterval =
+ static_cast<jint>(interval.get<FrontendGuardInterval::Tag::dvbt>());
break;
}
- case FrontendGuardInterval::hidl_discriminator::isdbt: {
- intInterval = static_cast<jint>(interval.isdbt());
+ case FrontendGuardInterval::Tag::isdbt: {
+ intInterval = static_cast<jint>(
+ interval.get<FrontendGuardInterval::Tag::isdbt>());
break;
}
- case FrontendGuardInterval::hidl_discriminator::dtmb: {
- intInterval = static_cast<jint>(interval.dtmb());
+ case FrontendGuardInterval::Tag::dtmb: {
+ intInterval =
+ static_cast<jint>(interval.get<FrontendGuardInterval::Tag::dtmb>());
break;
}
default:
@@ -2257,22 +2298,25 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::transmissionMode: {
+ case FrontendStatus::Tag::transmissionMode: {
jfieldID field = env->GetFieldID(clazz, "mTransmissionMode", "Ljava/lang/Integer;");
- auto transmissionMode = s.transmissionMode();
+ auto transmissionMode = s.get<FrontendStatus::Tag::transmissionMode>();
jint intTransmissionMode;
bool valid = true;
- switch(transmissionMode.getDiscriminator()) {
- case FrontendTransmissionMode::hidl_discriminator::dvbt: {
- intTransmissionMode = static_cast<jint>(transmissionMode.dvbt());
+ switch (transmissionMode.getTag()) {
+ case FrontendTransmissionMode::Tag::dvbt: {
+ intTransmissionMode = static_cast<jint>(
+ transmissionMode.get<FrontendTransmissionMode::Tag::dvbt>());
break;
}
- case FrontendTransmissionMode::hidl_discriminator::isdbt: {
- intTransmissionMode = static_cast<jint>(transmissionMode.isdbt());
+ case FrontendTransmissionMode::Tag::isdbt: {
+ intTransmissionMode = static_cast<jint>(
+ transmissionMode.get<FrontendTransmissionMode::Tag::isdbt>());
break;
}
- case FrontendTransmissionMode::hidl_discriminator::dtmb: {
- intTransmissionMode = static_cast<jint>(transmissionMode.dtmb());
+ case FrontendTransmissionMode::Tag::dtmb: {
+ intTransmissionMode = static_cast<jint>(
+ transmissionMode.get<FrontendTransmissionMode::Tag::dtmb>());
break;
}
default:
@@ -2285,44 +2329,48 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::uec: {
+ case FrontendStatus::Tag::uec: {
jfieldID field = env->GetFieldID(clazz, "mUec", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.uec()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::uec>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::systemId: {
+ case FrontendStatus::Tag::systemId: {
jfieldID field = env->GetFieldID(clazz, "mSystemId", "Ljava/lang/Integer;");
- jobject newIntegerObj = env->NewObject(
- intClazz, initInt, static_cast<jint>(s.systemId()));
+ jobject newIntegerObj =
+ env->NewObject(intClazz, initInt,
+ static_cast<jint>(s.get<FrontendStatus::Tag::systemId>()));
env->SetObjectField(statusObj, field, newIntegerObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::interleaving: {
+ case FrontendStatus::Tag::interleaving: {
jfieldID field = env->GetFieldID(clazz, "mInterleaving", "[I");
-
- std::vector<FrontendInterleaveMode> v = s.interleaving();
+ std::vector<FrontendInterleaveMode> v = s.get<FrontendStatus::Tag::interleaving>();
jintArray valObj = env->NewIntArray(v.size());
bool valid = false;
jint in[1];
for (int i = 0; i < v.size(); i++) {
auto interleaving = v[i];
- switch(interleaving.getDiscriminator()) {
- case FrontendInterleaveMode::hidl_discriminator::atsc3: {
- in[0] = static_cast<jint>(interleaving.atsc3());
+ switch (interleaving.getTag()) {
+ case FrontendInterleaveMode::Tag::atsc3: {
+ in[0] = static_cast<jint>(
+ interleaving.get<FrontendInterleaveMode::Tag::atsc3>());
env->SetIntArrayRegion(valObj, i, 1, in);
valid = true;
break;
}
- case FrontendInterleaveMode::hidl_discriminator::dvbc: {
- in[0] = static_cast<jint>(interleaving.dvbc());
+ case FrontendInterleaveMode::Tag::dvbc: {
+ in[0] = static_cast<jint>(
+ interleaving.get<FrontendInterleaveMode::Tag::dvbc>());
env->SetIntArrayRegion(valObj, i, 1, in);
valid = true;
break;
}
- case FrontendInterleaveMode::hidl_discriminator::dtmb: {
- in[0] = static_cast<jint>(interleaving.dtmb());
+ case FrontendInterleaveMode::Tag::dtmb: {
+ in[0] = static_cast<jint>(
+ interleaving.get<FrontendInterleaveMode::Tag::dtmb>());
env->SetIntArrayRegion(valObj, i, 1, in);
valid = true;
break;
@@ -2336,9 +2384,9 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::isdbtSegment: {
+ case FrontendStatus::Tag::isdbtSegment: {
jfieldID field = env->GetFieldID(clazz, "mIsdbtSegment", "[I");
- std::vector<uint8_t> v = s.isdbtSegment();
+ std::vector<uint8_t> v = s.get<FrontendStatus::Tag::isdbtSegment>();
jintArray valObj = env->NewIntArray(v.size());
env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -2346,9 +2394,9 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::tsDataRate: {
+ case FrontendStatus::Tag::tsDataRate: {
jfieldID field = env->GetFieldID(clazz, "mTsDataRate", "[I");
- std::vector<uint32_t> v = s.tsDataRate();
+ std::vector<int32_t> v = s.get<FrontendStatus::Tag::tsDataRate>();
jintArray valObj = env->NewIntArray(v.size());
env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
@@ -2356,22 +2404,22 @@ jobject JTuner::getFrontendStatus(jintArray types) {
env->SetObjectField(statusObj, field, valObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::rollOff: {
+ case FrontendStatus::Tag::rollOff: {
jfieldID field = env->GetFieldID(clazz, "mRollOff", "Ljava/lang/Integer;");
- auto rollOff = s.rollOff();
+ auto rollOff = s.get<FrontendStatus::Tag::rollOff>();
jint intRollOff;
bool valid = true;
- switch(rollOff.getDiscriminator()) {
- case FrontendRollOff::hidl_discriminator::dvbs: {
- intRollOff = static_cast<jint>(rollOff.dvbs());
+ switch (rollOff.getTag()) {
+ case FrontendRollOff::Tag::dvbs: {
+ intRollOff = static_cast<jint>(rollOff.get<FrontendRollOff::Tag::dvbs>());
break;
}
- case FrontendRollOff::hidl_discriminator::isdbs: {
- intRollOff = static_cast<jint>(rollOff.isdbs());
+ case FrontendRollOff::Tag::isdbs: {
+ intRollOff = static_cast<jint>(rollOff.get<FrontendRollOff::Tag::isdbs>());
break;
}
- case FrontendRollOff::hidl_discriminator::isdbs3: {
- intRollOff = static_cast<jint>(rollOff.isdbs3());
+ case FrontendRollOff::Tag::isdbs3: {
+ intRollOff = static_cast<jint>(rollOff.get<FrontendRollOff::Tag::isdbs3>());
break;
}
default:
@@ -2384,24 +2432,29 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::isMiso: {
+ case FrontendStatus::Tag::isMiso: {
jfieldID field = env->GetFieldID(clazz, "mIsMisoEnabled", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isMiso()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(s.get<FrontendStatus::Tag::isMiso>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::isLinear: {
+ case FrontendStatus::Tag::isLinear: {
jfieldID field = env->GetFieldID(clazz, "mIsLinear", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isLinear()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(
+ s.get<FrontendStatus::Tag::isLinear>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
- case FrontendStatusExt1_1::hidl_discriminator::isShortFrames: {
+ case FrontendStatus::Tag::isShortFrames: {
jfieldID field = env->GetFieldID(clazz, "mIsShortFrames", "Ljava/lang/Boolean;");
- jobject newBooleanObj = env->NewObject(
- booleanClazz, initBoolean, static_cast<jboolean>(s.isShortFrames()));
+ jobject newBooleanObj =
+ env->NewObject(booleanClazz, initBoolean,
+ static_cast<jboolean>(
+ s.get<FrontendStatus::Tag::isShortFrames>()));
env->SetObjectField(statusObj, field, newBooleanObj);
break;
}
@@ -2413,33 +2466,28 @@ jobject JTuner::getFrontendStatus(jintArray types) {
return statusObj;
}
-bool JTuner::isV1_1ExtendedStatusType(int type) {
- return (type > static_cast<int>(FrontendStatusType::ATSC3_PLP_INFO)
- && type <= static_cast<int>(FrontendStatusTypeExt1_1::IS_SHORT_FRAMES));
-}
-
jint JTuner::closeFrontend() {
Result r = Result::SUCCESS;
- if (mFeClient != NULL) {
+ if (mFeClient != nullptr) {
r = mFeClient->close();
}
if (r == Result::SUCCESS) {
- mFeClient = NULL;
+ mFeClient = nullptr;
}
- return (jint) r;
+ return (jint)r;
}
jint JTuner::closeDemux() {
Result r = Result::SUCCESS;
- if (mDemuxClient != NULL) {
+ if (mDemuxClient != nullptr) {
r = mDemuxClient->close();
}
if (r == Result::SUCCESS) {
- mDemuxClient = NULL;
+ mDemuxClient = nullptr;
}
- return (jint) r;
+ return (jint)r;
}
} // namespace android
@@ -2450,14 +2498,14 @@ using namespace android;
static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
- if (tuner != NULL) {
+ if (tuner != nullptr) {
tuner->incStrong(thiz);
}
- if (old != NULL) {
+ if (old != nullptr) {
old->decStrong(thiz);
}
- if (tuner != NULL) {
+ if (tuner != nullptr) {
env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get());
}
@@ -2474,25 +2522,25 @@ static sp<DescramblerClient> getDescramblerClient(JNIEnv *env, jobject descrambl
static DemuxPid getDemuxPid(int pidType, int pid) {
DemuxPid demuxPid;
- if ((int)pidType == 1) {
- demuxPid.tPid(static_cast<DemuxTpid>(pid));
- } else if ((int)pidType == 2) {
- demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid));
+ if (pidType == 1) {
+ demuxPid.set<DemuxPid::tPid>(pid);
+ } else if (pidType == 2) {
+ demuxPid.set<DemuxPid::mmtpPid>(pid);
}
return demuxPid;
}
-static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) {
+static int32_t getFrontendSettingsFreq(JNIEnv *env, const jobject &settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
- uint32_t freq = static_cast<uint32_t>(env->GetIntField(settings, freqField));
+ int32_t freq = static_cast<int32_t>(env->GetIntField(settings, freqField));
return freq;
}
-static uint32_t getFrontendSettingsEndFreq(JNIEnv *env, const jobject& settings) {
+static int32_t getFrontendSettingsEndFreq(JNIEnv *env, const jobject &settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
jfieldID endFreqField = env->GetFieldID(clazz, "mEndFrequency", "I");
- uint32_t endFreq = static_cast<uint32_t>(env->GetIntField(settings, endFreqField));
+ int32_t endFreq = static_cast<int32_t>(env->GetIntField(settings, endFreqField));
return endFreq;
}
@@ -2507,7 +2555,9 @@ static FrontendSpectralInversion getFrontendSettingsSpectralInversion(
static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
FrontendAnalogType analogType =
static_cast<FrontendAnalogType>(
@@ -2515,29 +2565,21 @@ static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& se
FrontendAnalogSifStandard sifStandard =
static_cast<FrontendAnalogSifStandard>(
env->GetIntField(settings, env->GetFieldID(clazz, "mSifStandard", "I")));
- FrontendAnalogSettings frontendAnalogSettings {
+ FrontendAnalogAftFlag aftFlag = static_cast<FrontendAnalogAftFlag>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mAftFlag", "I")));
+ FrontendAnalogSettings frontendAnalogSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.type = analogType,
.sifStandard = sifStandard,
+ .aftFlag = aftFlag,
+ .inversion = inversion,
};
- frontendSettings.analog(frontendAnalogSettings);
+ frontendSettings.set<FrontendSettings::Tag::analog>(frontendAnalogSettings);
return frontendSettings;
}
-static void getAnalogFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
- FrontendSettingsExt1_1& settingsExt1_1) {
- jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
- FrontendAnalogAftFlag aftFlag =
- static_cast<FrontendAnalogAftFlag>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mAftFlag", "I")));
- FrontendAnalogSettingsExt1_1 analogExt1_1 {
- .aftFlag = aftFlag,
- };
- settingsExt1_1.settingExt.analog(analogExt1_1);
-}
-
-static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
- JNIEnv *env, const jobject& settings) {
+static vector<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(JNIEnv *env, const jobject &settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
jobjectArray plpSettings =
reinterpret_cast<jobjectArray>(
@@ -2549,13 +2591,12 @@ static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
int len = env->GetArrayLength(plpSettings);
jclass plpClazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3PlpSettings");
- hidl_vec<FrontendAtsc3PlpSettings> plps = hidl_vec<FrontendAtsc3PlpSettings>(len);
+ vector<FrontendAtsc3PlpSettings> plps = vector<FrontendAtsc3PlpSettings>(len);
// parse PLP settings
for (int i = 0; i < len; i++) {
jobject plp = env->GetObjectArrayElement(plpSettings, i);
- uint8_t plpId =
- static_cast<uint8_t>(
- env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I")));
+ int8_t plpId = static_cast<int8_t>(
+ env->GetIntField(plp, env->GetFieldID(plpClazz, "mPlpId", "I")));
FrontendAtsc3Modulation modulation =
static_cast<FrontendAtsc3Modulation>(
env->GetIntField(plp, env->GetFieldID(plpClazz, "mModulation", "I")));
@@ -2583,9 +2624,10 @@ static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings(
static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings");
-
FrontendAtsc3Bandwidth bandwidth =
static_cast<FrontendAtsc3Bandwidth>(
env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
@@ -2593,35 +2635,42 @@ static FrontendSettings getAtsc3FrontendSettings(JNIEnv *env, const jobject& set
static_cast<FrontendAtsc3DemodOutputFormat>(
env->GetIntField(
settings, env->GetFieldID(clazz, "mDemodOutputFormat", "I")));
- hidl_vec<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings);
- FrontendAtsc3Settings frontendAtsc3Settings {
+ vector<FrontendAtsc3PlpSettings> plps = getAtsc3PlpSettings(env, settings);
+ FrontendAtsc3Settings frontendAtsc3Settings{
.frequency = freq,
+ .endFrequency = endFreq,
.bandwidth = bandwidth,
.demodOutputFormat = demod,
.plpSettings = plps,
+ .inversion = inversion,
};
- frontendSettings.atsc3(frontendAtsc3Settings);
+ frontendSettings.set<FrontendSettings::Tag::atsc3>(frontendAtsc3Settings);
return frontendSettings;
}
static FrontendSettings getAtscFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AtscFrontendSettings");
FrontendAtscModulation modulation =
static_cast<FrontendAtscModulation>(
env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
- FrontendAtscSettings frontendAtscSettings {
+ FrontendAtscSettings frontendAtscSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.modulation = modulation,
+ .inversion = inversion,
};
- frontendSettings.atsc(frontendAtscSettings);
+ frontendSettings.set<FrontendSettings::Tag::atsc>(frontendAtscSettings);
return frontendSettings;
}
static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings");
FrontendDvbcModulation modulation =
static_cast<FrontendDvbcModulation>(
@@ -2629,49 +2678,36 @@ static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& sett
FrontendInnerFec innerFec =
static_cast<FrontendInnerFec>(
env->GetLongField(settings, env->GetFieldID(clazz, "mInnerFec", "J")));
- uint32_t symbolRate =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
+ int32_t symbolRate = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
FrontendDvbcOuterFec outerFec =
static_cast<FrontendDvbcOuterFec>(
env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I")));
FrontendDvbcAnnex annex =
static_cast<FrontendDvbcAnnex>(
env->GetIntField(settings, env->GetFieldID(clazz, "mAnnex", "I")));
- FrontendDvbcSpectralInversion spectralInversion =
- static_cast<FrontendDvbcSpectralInversion>(
- env->GetIntField(
- settings, env->GetFieldID(clazz, "mSpectralInversion", "I")));
- FrontendDvbcSettings frontendDvbcSettings {
+ FrontendSpectralInversion spectralInversion = static_cast<FrontendSpectralInversion>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mSpectralInversion", "I")));
+ FrontendCableTimeInterleaveMode interleaveMode = static_cast<FrontendCableTimeInterleaveMode>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I")));
+ FrontendDvbcBandwidth bandwidth = static_cast<FrontendDvbcBandwidth>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
+ FrontendDvbcSettings frontendDvbcSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.modulation = modulation,
.fec = innerFec,
.symbolRate = symbolRate,
.outerFec = outerFec,
.annex = annex,
- .spectralInversion = spectralInversion,
+ .inversion = spectralInversion,
+ .interleaveMode = interleaveMode,
+ .bandwidth = bandwidth,
};
- frontendSettings.dvbc(frontendDvbcSettings);
+ frontendSettings.set<FrontendSettings::Tag::dvbc>(frontendDvbcSettings);
return frontendSettings;
}
-static void getDvbcFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
- FrontendSettingsExt1_1& settingsExt1_1) {
- jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings");
- FrontendCableTimeInterleaveMode interleaveMode =
- static_cast<FrontendCableTimeInterleaveMode>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I")));
- FrontendDvbcBandwidth bandwidth =
- static_cast<FrontendDvbcBandwidth>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
-
- FrontendDvbcSettingsExt1_1 dvbcExt1_1 {
- .interleaveMode = interleaveMode,
- .bandwidth = bandwidth,
- };
- settingsExt1_1.settingExt.dvbc(dvbcExt1_1);
-}
-
static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
jobject jcodeRate =
@@ -2694,11 +2730,8 @@ static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings
static_cast<bool>(
env->GetBooleanField(
jcodeRate, env->GetFieldID(codeRateClazz, "mIsShortFrames", "Z")));
- uint32_t bitsPer1000Symbol =
- static_cast<uint32_t>(
- env->GetIntField(
- jcodeRate, env->GetFieldID(
- codeRateClazz, "mBitsPer1000Symbol", "I")));
+ int32_t bitsPer1000Symbol = static_cast<int32_t>(
+ env->GetIntField(jcodeRate, env->GetFieldID(codeRateClazz, "mBitsPer1000Symbol", "I")));
FrontendDvbsCodeRate coderate {
.fec = innerFec,
.isLinear = isLinear,
@@ -2710,33 +2743,37 @@ static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings
static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
-
FrontendDvbsModulation modulation =
static_cast<FrontendDvbsModulation>(
env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
- uint32_t symbolRate =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
+ int32_t symbolRate = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
FrontendDvbsRolloff rolloff =
static_cast<FrontendDvbsRolloff>(
env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
FrontendDvbsPilot pilot =
static_cast<FrontendDvbsPilot>(
env->GetIntField(settings, env->GetFieldID(clazz, "mPilot", "I")));
- uint32_t inputStreamId =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I")));
+ int32_t inputStreamId = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mInputStreamId", "I")));
FrontendDvbsStandard standard =
static_cast<FrontendDvbsStandard>(
env->GetIntField(settings, env->GetFieldID(clazz, "mStandard", "I")));
FrontendDvbsVcmMode vcmMode =
static_cast<FrontendDvbsVcmMode>(
env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I")));
+ FrontendDvbsScanType scanType = static_cast<FrontendDvbsScanType>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I")));
+ bool isDiseqcRxMessage = static_cast<bool>(
+ env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "Z")));
- FrontendDvbsSettings frontendDvbsSettings {
+ FrontendDvbsSettings frontendDvbsSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.modulation = modulation,
.symbolRate = symbolRate,
.rolloff = rolloff,
@@ -2744,37 +2781,26 @@ static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& sett
.inputStreamId = inputStreamId,
.standard = standard,
.vcmMode = vcmMode,
+ .scanType = scanType,
+ .isDiseqcRxMessage = isDiseqcRxMessage,
+ .inversion = inversion,
};
jobject jcodeRate = env->GetObjectField(settings, env->GetFieldID(clazz, "mCodeRate",
"Landroid/media/tv/tuner/frontend/DvbsCodeRate;"));
- if (jcodeRate != NULL) {
+ if (jcodeRate != nullptr) {
frontendDvbsSettings.coderate = getDvbsCodeRate(env, settings);
}
- frontendSettings.dvbs(frontendDvbsSettings);
+ frontendSettings.set<FrontendSettings::Tag::dvbs>(frontendDvbsSettings);
return frontendSettings;
}
-static void getDvbsFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
- FrontendSettingsExt1_1& settingsExt1_1) {
- jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings");
- FrontendDvbsScanType scanType =
- static_cast<FrontendDvbsScanType>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I")));
- bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField(
- settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "Z")));
-
- FrontendDvbsSettingsExt1_1 dvbsExt1_1 {
- .scanType = scanType,
- .isDiseqcRxMessage = isDiseqcRxMessage,
- };
- settingsExt1_1.settingExt.dvbs(dvbsExt1_1);
-}
-
static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings");
FrontendDvbtTransmissionMode transmissionMode =
static_cast<FrontendDvbtTransmissionMode>(
@@ -2811,15 +2837,14 @@ static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& sett
FrontendDvbtPlpMode plpMode =
static_cast<FrontendDvbtPlpMode>(
env->GetIntField(settings, env->GetFieldID(clazz, "mPlpMode", "I")));
- uint8_t plpId =
- static_cast<uint8_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I")));
- uint8_t plpGroupId =
- static_cast<uint8_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I")));
-
- FrontendDvbtSettings frontendDvbtSettings {
+ int8_t plpId =
+ static_cast<int8_t>(env->GetIntField(settings, env->GetFieldID(clazz, "mPlpId", "I")));
+ int8_t plpGroupId = static_cast<int8_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mPlpGroupId", "I")));
+
+ FrontendDvbtSettings frontendDvbtSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.transmissionMode = transmissionMode,
.bandwidth = bandwidth,
.constellation = constellation,
@@ -2833,33 +2858,16 @@ static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& sett
.plpMode = plpMode,
.plpId = plpId,
.plpGroupId = plpGroupId,
+ .inversion = inversion,
};
- frontendSettings.dvbt(frontendDvbtSettings);
+ frontendSettings.set<FrontendSettings::Tag::dvbt>(frontendDvbtSettings);
return frontendSettings;
}
-static void getDvbtFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
- FrontendSettingsExt1_1& settingsExt1_1) {
- jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings");
-
- FrontendDvbtSettingsExt1_1 dvbtExt1_1;
- int transmissionMode =
- env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I"));
- dvbtExt1_1.transmissionMode = static_cast<
- ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>(
- transmissionMode);
-
- int constellation =
- env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I"));
- dvbtExt1_1.constellation = static_cast<
- ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(constellation);
-
- settingsExt1_1.settingExt.dvbt(dvbtExt1_1);
-}
-
static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbsFrontendSettings");
uint16_t streamId =
static_cast<uint16_t>(
@@ -2873,15 +2881,15 @@ static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& set
FrontendIsdbsCoderate coderate =
static_cast<FrontendIsdbsCoderate>(
env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
- uint32_t symbolRate =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
+ int32_t symbolRate = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
FrontendIsdbsRolloff rolloff =
static_cast<FrontendIsdbsRolloff>(
env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
- FrontendIsdbsSettings frontendIsdbsSettings {
+ FrontendIsdbsSettings frontendIsdbsSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.streamId = streamId,
.streamIdType = streamIdType,
.modulation = modulation,
@@ -2889,13 +2897,14 @@ static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& set
.symbolRate = symbolRate,
.rolloff = rolloff,
};
- frontendSettings.isdbs(frontendIsdbsSettings);
+ frontendSettings.set<FrontendSettings::Tag::isdbs>(frontendIsdbsSettings);
return frontendSettings;
}
static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Isdbs3FrontendSettings");
uint16_t streamId =
static_cast<uint16_t>(
@@ -2909,15 +2918,15 @@ static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& se
FrontendIsdbs3Coderate coderate =
static_cast<FrontendIsdbs3Coderate>(
env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I")));
- uint32_t symbolRate =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
+ int32_t symbolRate = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
FrontendIsdbs3Rolloff rolloff =
static_cast<FrontendIsdbs3Rolloff>(
env->GetIntField(settings, env->GetFieldID(clazz, "mRolloff", "I")));
- FrontendIsdbs3Settings frontendIsdbs3Settings {
+ FrontendIsdbs3Settings frontendIsdbs3Settings{
.frequency = freq,
+ .endFrequency = endFreq,
.streamId = streamId,
.streamIdType = streamIdType,
.modulation = modulation,
@@ -2925,13 +2934,15 @@ static FrontendSettings getIsdbs3FrontendSettings(JNIEnv *env, const jobject& se
.symbolRate = symbolRate,
.rolloff = rolloff,
};
- frontendSettings.isdbs3(frontendIsdbs3Settings);
+ frontendSettings.set<FrontendSettings::Tag::isdbs3>(frontendIsdbs3Settings);
return frontendSettings;
}
static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& settings) {
FrontendSettings frontendSettings;
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IsdbtFrontendSettings");
FrontendIsdbtModulation modulation =
static_cast<FrontendIsdbtModulation>(
@@ -2948,26 +2959,29 @@ static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& set
FrontendIsdbtGuardInterval guardInterval =
static_cast<FrontendIsdbtGuardInterval>(
env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I")));
- uint32_t serviceAreaId =
- static_cast<uint32_t>(
- env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I")));
+ int32_t serviceAreaId = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mServiceAreaId", "I")));
- FrontendIsdbtSettings frontendIsdbtSettings {
+ FrontendIsdbtSettings frontendIsdbtSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.modulation = modulation,
.bandwidth = bandwidth,
.mode = mode,
.coderate = coderate,
.guardInterval = guardInterval,
.serviceAreaId = serviceAreaId,
+ .inversion = inversion,
};
- frontendSettings.isdbt(frontendIsdbtSettings);
+ frontendSettings.set<FrontendSettings::Tag::isdbt>(frontendIsdbtSettings);
return frontendSettings;
}
-static void getDtmbFrontendSettings(JNIEnv *env, const jobject& settings,
- FrontendSettingsExt1_1& settingsExt1_1) {
- uint32_t freq = getFrontendSettingsFreq(env, settings);
+static FrontendSettings getDtmbFrontendSettings(JNIEnv *env, const jobject &settings) {
+ FrontendSettings frontendSettings;
+ int32_t freq = getFrontendSettingsFreq(env, settings);
+ int32_t endFreq = getFrontendSettingsEndFreq(env, settings);
+ FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendSettings");
FrontendDtmbModulation modulation =
static_cast<FrontendDtmbModulation>(
@@ -2988,25 +3002,23 @@ static void getDtmbFrontendSettings(JNIEnv *env, const jobject& settings,
static_cast<FrontendDtmbTimeInterleaveMode>(
env->GetIntField(settings, env->GetFieldID(clazz, "mTimeInterleaveMode", "I")));
- FrontendDtmbSettings frontendDtmbSettings {
+ FrontendDtmbSettings frontendDtmbSettings{
.frequency = freq,
+ .endFrequency = endFreq,
.modulation = modulation,
.bandwidth = bandwidth,
.transmissionMode = transmissionMode,
.codeRate = codeRate,
.guardInterval = guardInterval,
.interleaveMode = interleaveMode,
+ .inversion = inversion,
};
- settingsExt1_1.settingExt.dtmb(frontendDtmbSettings);
+ frontendSettings.set<FrontendSettings::Tag::dtmb>(frontendDtmbSettings);
+ return frontendSettings;
}
static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
- ALOGD("getFrontendSettings %d", type);
-
- if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
- return FrontendSettings();
- }
-
+ ALOGV("getFrontendSettings %d", type);
FrontendType feType = static_cast<FrontendType>(type);
switch(feType) {
case FrontendType::ANALOG:
@@ -3027,6 +3039,8 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti
return getIsdbs3FrontendSettings(env, settings);
case FrontendType::ISDBT:
return getIsdbtFrontendSettings(env, settings);
+ case FrontendType::DTMB:
+ return getDtmbFrontendSettings(env, settings);
default:
// should never happen because a type is associated with a subclass of
// FrontendSettings and not set by users
@@ -3036,64 +3050,6 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti
}
}
-static FrontendSettingsExt1_1 getFrontendSettingsExt1_1(
- JNIEnv *env, int type, jobject settings, int tunerVersion) {
- ALOGD("getFrontendSettingsExt1_1 %d", type);
-
- FrontendSettingsExt1_1 settingsExt1_1 {
- .endFrequency = static_cast<uint32_t>(Constant::INVALID_FRONTEND_SETTING_FREQUENCY),
- .inversion = FrontendSpectralInversion::UNDEFINED,
- };
- settingsExt1_1.settingExt.noinit();
-
- if (tunerVersion < TUNER_VERSION_1_1) {
- return settingsExt1_1;
- }
-
- if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
- getDtmbFrontendSettings(env, settings, settingsExt1_1);
- } else {
- FrontendType feType = static_cast<FrontendType>(type);
- switch(feType) {
- case FrontendType::DVBS:
- getDvbsFrontendSettingsExt1_1(env, settings, settingsExt1_1);
- break;
- case FrontendType::DVBT:
- getDvbtFrontendSettingsExt1_1(env, settings, settingsExt1_1);
- break;
- case FrontendType::ANALOG:
- getAnalogFrontendSettingsExt1_1(env, settings, settingsExt1_1);
- break;
- case FrontendType::ATSC3:
- break;
- case FrontendType::ATSC:
- break;
- case FrontendType::DVBC:
- getDvbcFrontendSettingsExt1_1(env, settings, settingsExt1_1);
- break;
- case FrontendType::ISDBS:
- break;
- case FrontendType::ISDBS3:
- break;
- case FrontendType::ISDBT:
- break;
- default:
- // should never happen because a type is associated with a subclass of
- // FrontendSettings and not set by users
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
- "Unsupported frontend type %d", type);
- return FrontendSettingsExt1_1();
- }
- }
-
- uint32_t endFreq = getFrontendSettingsEndFreq(env, settings);
- FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings);
- settingsExt1_1.endFrequency = endFreq;
- settingsExt1_1.inversion = inversion;
-
- return settingsExt1_1;
-}
-
static sp<FilterClient> getFilterClient(JNIEnv *env, jobject filter) {
return (FilterClient *)env->GetLongField(filter, gFields.filterContext);
}
@@ -3105,18 +3061,14 @@ static sp<LnbClient> getLnbClient(JNIEnv *env, jobject lnb) {
static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) {
DvrSettings dvrSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
- uint32_t statusMask =
- static_cast<uint32_t>(env->GetIntField(
- settings, env->GetFieldID(clazz, "mStatusMask", "I")));
- uint32_t lowThreshold =
- static_cast<uint32_t>(env->GetLongField(
- settings, env->GetFieldID(clazz, "mLowThreshold", "J")));
- uint32_t highThreshold =
- static_cast<uint32_t>(env->GetLongField(
- settings, env->GetFieldID(clazz, "mHighThreshold", "J")));
- uint8_t packetSize =
- static_cast<uint8_t>(env->GetLongField(
- settings, env->GetFieldID(clazz, "mPacketSize", "J")));
+ int32_t statusMask = static_cast<int32_t>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mStatusMask", "I")));
+ int32_t lowThreshold = static_cast<int32_t>(
+ env->GetLongField(settings, env->GetFieldID(clazz, "mLowThreshold", "J")));
+ int32_t highThreshold = static_cast<int32_t>(
+ env->GetLongField(settings, env->GetFieldID(clazz, "mHighThreshold", "J")));
+ int8_t packetSize = static_cast<int8_t>(
+ env->GetLongField(settings, env->GetFieldID(clazz, "mPacketSize", "J")));
DataFormat dataFormat =
static_cast<DataFormat>(env->GetIntField(
settings, env->GetFieldID(clazz, "mDataFormat", "I")));
@@ -3128,7 +3080,7 @@ static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder
.dataFormat = dataFormat,
.packetSize = packetSize,
};
- dvrSettings.record(recordSettings);
+ dvrSettings.set<DvrSettings::Tag::record>(recordSettings);
} else {
PlaybackSettings PlaybackSettings {
.statusMask = statusMask,
@@ -3137,7 +3089,7 @@ static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder
.dataFormat = dataFormat,
.packetSize = packetSize,
};
- dvrSettings.playback(PlaybackSettings);
+ dvrSettings.set<DvrSettings::Tag::playback>(PlaybackSettings);
}
return dvrSettings;
}
@@ -3152,10 +3104,10 @@ static sp<DvrClient> getDvrClient(JNIEnv *env, jobject dvr) {
static void android_media_tv_Tuner_native_init(JNIEnv *env) {
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
- CHECK(clazz != NULL);
+ CHECK(clazz != nullptr);
gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J");
- CHECK(gFields.tunerContext != NULL);
+ CHECK(gFields.tunerContext != nullptr);
gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
@@ -3229,12 +3181,16 @@ static jobject android_media_tv_Tuner_open_frontend_by_handle(
return tuner->openFrontendByHandle(handle);
}
+static int android_media_tv_Tuner_share_frontend(
+ JNIEnv *env, jobject thiz, jint id) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->shareFrontend(id);
+}
+
static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
sp<JTuner> tuner = getTuner(env, thiz);
FrontendSettings setting = getFrontendSettings(env, type, settings);
- FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(
- env, type, settings, tuner->getTunerVersion());
- return tuner->tune(setting, settingExt);
+ return tuner->tune(setting);
}
static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) {
@@ -3246,9 +3202,7 @@ static int android_media_tv_Tuner_scan(
JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
sp<JTuner> tuner = getTuner(env, thiz);
FrontendSettings setting = getFrontendSettings(env, settingsType, settings);
- FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(
- env, settingsType, settings, tuner->getTunerVersion());
- return tuner->scan(setting, static_cast<FrontendScanType>(scanType), settingExt);
+ return tuner->scan(setting, static_cast<FrontendScanType>(scanType));
}
static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) {
@@ -3259,7 +3213,7 @@ static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) {
static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jobject lnb) {
sp<JTuner> tuner = getTuner(env, thiz);
sp<LnbClient> lnbClient = getLnbClient(env, lnb);
- if (lnbClient == NULL) {
+ if (lnbClient == nullptr) {
ALOGE("lnb is not initialized");
return (int)Result::INVALID_STATE;
}
@@ -3280,9 +3234,9 @@ static jobject android_media_tv_Tuner_get_frontend_status(
static jobject android_media_tv_Tuner_get_av_sync_hw_id(
JNIEnv *env, jobject thiz, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to get sync ID. Filter client not found");
- return NULL;
+ return nullptr;
}
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->getAvSyncHwId(filterClient);
@@ -3337,22 +3291,30 @@ static jobject android_media_tv_Tuner_open_filter(
.mainType = mainType,
};
- switch(mainType) {
+ switch (mainType) {
case DemuxFilterMainType::TS:
- filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+ filterType.subType.set<DemuxFilterSubType::Tag::tsFilterType>(
+ static_cast<DemuxTsFilterType>(subType));
break;
case DemuxFilterMainType::MMTP:
- filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
+ filterType.subType.set<DemuxFilterSubType::Tag::mmtpFilterType>(
+ static_cast<DemuxMmtpFilterType>(subType));
break;
case DemuxFilterMainType::IP:
- filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
+ filterType.subType.set<DemuxFilterSubType::Tag::ipFilterType>(
+ static_cast<DemuxIpFilterType>(subType));
break;
case DemuxFilterMainType::TLV:
- filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
+ filterType.subType.set<DemuxFilterSubType::Tag::tlvFilterType>(
+ static_cast<DemuxTlvFilterType>(subType));
break;
case DemuxFilterMainType::ALP:
- filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
+ filterType.subType.set<DemuxFilterSubType::Tag::alpFilterType>(
+ static_cast<DemuxAlpFilterType>(subType));
break;
+ default:
+ ALOGD("Demux Filter Main Type is undefined.");
+ return nullptr;
}
return tuner->openFilter(filterType, bufferSize);
@@ -3392,16 +3354,16 @@ static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& s
return filterSectionBits;
}
-static DemuxFilterSectionSettings::Condition::TableInfo getFilterTableInfo(
- JNIEnv *env, const jobject& settings) {
+static DemuxFilterSectionSettingsConditionTableInfo getFilterTableInfo(JNIEnv *env,
+ const jobject &settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo");
uint16_t tableId = static_cast<uint16_t>(
env->GetIntField(settings, env->GetFieldID(clazz, "mTableId", "I")));
uint16_t version = static_cast<uint16_t>(
env->GetIntField(settings, env->GetFieldID(clazz, "mVersion", "I")));
- DemuxFilterSectionSettings::Condition::TableInfo tableInfo {
- .tableId = tableId,
- .version = version,
+ DemuxFilterSectionSettingsConditionTableInfo tableInfo{
+ .tableId = tableId,
+ .version = version,
};
return tableInfo;
}
@@ -3423,11 +3385,13 @@ static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jo
if (env->IsInstanceOf(
settings,
env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithSectionBits"))) {
- filterSectionSettings.condition.sectionBits(getFilterSectionBits(env, settings));
+ filterSectionSettings.condition.set<DemuxFilterSectionSettingsCondition::Tag::sectionBits>(
+ getFilterSectionBits(env, settings));
} else if (env->IsInstanceOf(
settings,
env->FindClass("android/media/tv/tuner/filter/SectionSettingsWithTableInfo"))) {
- filterSectionSettings.condition.tableInfo(getFilterTableInfo(env, settings));
+ filterSectionSettings.condition.set<DemuxFilterSectionSettingsCondition::Tag::tableInfo>(
+ getFilterTableInfo(env, settings));
}
return filterSectionSettings;
}
@@ -3455,13 +3419,13 @@ static bool getAvStreamType(JNIEnv *env, jobject filterConfigObj, AvStreamType&
AudioStreamType audioStreamType = static_cast<AudioStreamType>(
env->GetIntField(settingsObj, env->GetFieldID(clazz, "mAudioStreamType", "I")));
if (audioStreamType != AudioStreamType::UNDEFINED) {
- type.audio(audioStreamType);
+ type.set<AvStreamType::Tag::audio>(audioStreamType);
return true;
}
VideoStreamType videoStreamType = static_cast<VideoStreamType>(
env->GetIntField(settingsObj, env->GetFieldID(clazz, "mVideoStreamType", "I")));
if (videoStreamType != VideoStreamType::UNDEFINED) {
- type.video(videoStreamType);
+ type.set<AvStreamType::Tag::video>(videoStreamType);
return true;
}
return false;
@@ -3482,7 +3446,7 @@ static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jo
static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobject& settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/RecordSettings");
- hidl_bitfield<DemuxTsIndex> tsIndexMask = static_cast<hidl_bitfield<DemuxTsIndex>>(
+ int32_t tsIndexMask = static_cast<int32_t>(
env->GetIntField(settings, env->GetFieldID(clazz, "mTsIndexMask", "I")));
DemuxRecordScIndexType scIndexType = static_cast<DemuxRecordScIndexType>(
env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I")));
@@ -3493,17 +3457,16 @@ static DemuxFilterRecordSettings getFilterRecordSettings(JNIEnv *env, const jobj
.scIndexType = scIndexType,
};
if (scIndexType == DemuxRecordScIndexType::SC) {
- filterRecordSettings.scIndexMask.sc(static_cast<hidl_bitfield<DemuxScIndex>>(scIndexMask));
+ filterRecordSettings.scIndexMask.set<DemuxFilterScIndexMask::Tag::scIndex>(scIndexMask);
} else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) {
- filterRecordSettings.scIndexMask.scHevc(
- static_cast<hidl_bitfield<DemuxScHevcIndex>>(scIndexMask));
+ filterRecordSettings.scIndexMask.set<DemuxFilterScIndexMask::Tag::scHevc>(scIndexMask);
}
return filterRecordSettings;
}
static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const jobject& settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/DownloadSettings");
- uint32_t downloadId = static_cast<uint32_t>(
+ int32_t downloadId = static_cast<int32_t>(
env->GetIntField(settings, env->GetFieldID(clazz, "mDownloadId", "I")));
DemuxFilterDownloadSettings filterDownloadSettings {
@@ -3532,23 +3495,23 @@ static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) {
}
if (srcSize == IP_V4_LENGTH) {
- uint8_t srcAddr[IP_V4_LENGTH];
- uint8_t dstAddr[IP_V4_LENGTH];
- env->GetByteArrayRegion(
- jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
- env->GetByteArrayRegion(
- jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
- res.srcIpAddress.v4(srcAddr);
- res.dstIpAddress.v4(dstAddr);
+ vector<uint8_t> srcAddr;
+ vector<uint8_t> dstAddr;
+ srcAddr.resize(IP_V4_LENGTH);
+ dstAddr.resize(IP_V4_LENGTH);
+ env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
+ env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
+ res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(srcAddr);
+ res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(dstAddr);
} else if (srcSize == IP_V6_LENGTH) {
- uint8_t srcAddr[IP_V6_LENGTH];
- uint8_t dstAddr[IP_V6_LENGTH];
- env->GetByteArrayRegion(
- jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
- env->GetByteArrayRegion(
- jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
- res.srcIpAddress.v6(srcAddr);
- res.dstIpAddress.v6(dstAddr);
+ vector<uint8_t> srcAddr;
+ vector<uint8_t> dstAddr;
+ srcAddr.resize(IP_V6_LENGTH);
+ dstAddr.resize(IP_V6_LENGTH);
+ env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
+ env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
+ res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(srcAddr);
+ res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(dstAddr);
} else {
// should never happen. Validated on Java size.
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
@@ -3556,10 +3519,10 @@ static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) {
return res;
}
- uint16_t srcPort = static_cast<uint16_t>(
- env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")));
- uint16_t dstPort = static_cast<uint16_t>(
- env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")));
+ int16_t srcPort =
+ static_cast<int16_t>(env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")));
+ int16_t dstPort =
+ static_cast<int16_t>(env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")));
res.srcPort = srcPort;
res.dstPort = dstPort;
@@ -3587,30 +3550,35 @@ static DemuxFilterSettings getFilterConfiguration(
.tpid = tpid,
};
- if (settingsObj != NULL) {
+ if (settingsObj != nullptr) {
DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
switch (tsType) {
case DemuxTsFilterType::SECTION:
- tsFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
+ tsFilterSettings.filterSettings
+ .set<DemuxTsFilterSettingsFilterSettings::Tag::section>(
+ getFilterSectionSettings(env, settingsObj));
break;
case DemuxTsFilterType::AUDIO:
case DemuxTsFilterType::VIDEO:
- tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+ tsFilterSettings.filterSettings
+ .set<DemuxTsFilterSettingsFilterSettings::Tag::av>(
+ getFilterAvSettings(env, settingsObj));
break;
case DemuxTsFilterType::PES:
- tsFilterSettings.filterSettings.pesData(
- getFilterPesDataSettings(env, settingsObj));
+ tsFilterSettings.filterSettings
+ .set<DemuxTsFilterSettingsFilterSettings::Tag::pesData>(
+ getFilterPesDataSettings(env, settingsObj));
break;
case DemuxTsFilterType::RECORD:
- tsFilterSettings.filterSettings.record(
- getFilterRecordSettings(env, settingsObj));
+ tsFilterSettings.filterSettings
+ .set<DemuxTsFilterSettingsFilterSettings::Tag::record>(
+ getFilterRecordSettings(env, settingsObj));
break;
default:
break;
}
}
- filterSettings.ts(tsFilterSettings);
+ filterSettings.set<DemuxFilterSettings::Tag::ts>(tsFilterSettings);
break;
}
case DemuxFilterMainType::MMTP: {
@@ -3621,34 +3589,40 @@ static DemuxFilterSettings getFilterConfiguration(
.mmtpPid = mmtpPid,
};
- if (settingsObj != NULL) {
+ if (settingsObj != nullptr) {
DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
switch (mmtpType) {
case DemuxMmtpFilterType::SECTION:
- mmtpFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
+ mmtpFilterSettings.filterSettings
+ .set<DemuxMmtpFilterSettingsFilterSettings::Tag::section>(
+ getFilterSectionSettings(env, settingsObj));
break;
case DemuxMmtpFilterType::AUDIO:
case DemuxMmtpFilterType::VIDEO:
- mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+ mmtpFilterSettings.filterSettings
+ .set<DemuxMmtpFilterSettingsFilterSettings::Tag::av>(
+ getFilterAvSettings(env, settingsObj));
break;
case DemuxMmtpFilterType::PES:
- mmtpFilterSettings.filterSettings.pesData(
- getFilterPesDataSettings(env, settingsObj));
+ mmtpFilterSettings.filterSettings
+ .set<DemuxMmtpFilterSettingsFilterSettings::Tag::pesData>(
+ getFilterPesDataSettings(env, settingsObj));
break;
case DemuxMmtpFilterType::RECORD:
- mmtpFilterSettings.filterSettings.record(
- getFilterRecordSettings(env, settingsObj));
+ mmtpFilterSettings.filterSettings
+ .set<DemuxMmtpFilterSettingsFilterSettings::Tag::record>(
+ getFilterRecordSettings(env, settingsObj));
break;
case DemuxMmtpFilterType::DOWNLOAD:
- mmtpFilterSettings.filterSettings.download(
- getFilterDownloadSettings(env, settingsObj));
+ mmtpFilterSettings.filterSettings
+ .set<DemuxMmtpFilterSettingsFilterSettings::Tag::download>(
+ getFilterDownloadSettings(env, settingsObj));
break;
default:
break;
}
}
- filterSettings.mmtp(mmtpFilterSettings);
+ filterSettings.set<DemuxFilterSettings::Tag::mmtp>(mmtpFilterSettings);
break;
}
case DemuxFilterMainType::IP: {
@@ -3658,8 +3632,9 @@ static DemuxFilterSettings getFilterConfiguration(
};
DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
- if (ipType == DemuxIpFilterType::SECTION && settingsObj != NULL) {
- ipFilterSettings.filterSettings.section(
+ if (ipType == DemuxIpFilterType::SECTION && settingsObj != nullptr) {
+ ipFilterSettings.filterSettings
+ .set<DemuxIpFilterSettingsFilterSettings::Tag::section>(
getFilterSectionSettings(env, settingsObj));
} else if (ipType == DemuxIpFilterType::IP) {
jclass clazz = env->FindClass(
@@ -3668,14 +3643,15 @@ static DemuxFilterSettings getFilterConfiguration(
env->GetBooleanField(
filterConfigObj, env->GetFieldID(
clazz, "mPassthrough", "Z")));
- ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
+ ipFilterSettings.filterSettings
+ .set<DemuxIpFilterSettingsFilterSettings::Tag::bPassthrough>(bPassthrough);
}
- filterSettings.ip(ipFilterSettings);
+ filterSettings.set<DemuxFilterSettings::Tag::ip>(ipFilterSettings);
break;
}
case DemuxFilterMainType::TLV: {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration");
- uint8_t packetType = static_cast<uint8_t>(
+ int8_t packetType = static_cast<int8_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
bool isCompressedIpPacket = static_cast<bool>(
env->GetBooleanField(
@@ -3687,22 +3663,24 @@ static DemuxFilterSettings getFilterConfiguration(
};
DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
- if (tlvType == DemuxTlvFilterType::SECTION && settingsObj != NULL) {
- tlvFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
+ if (tlvType == DemuxTlvFilterType::SECTION && settingsObj != nullptr) {
+ tlvFilterSettings.filterSettings
+ .set<DemuxTlvFilterSettingsFilterSettings::Tag::section>(
+ getFilterSectionSettings(env, settingsObj));
} else if (tlvType == DemuxTlvFilterType::TLV) {
bool bPassthrough = static_cast<bool>(
env->GetBooleanField(
filterConfigObj, env->GetFieldID(
clazz, "mPassthrough", "Z")));
- tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
+ tlvFilterSettings.filterSettings
+ .set<DemuxTlvFilterSettingsFilterSettings::Tag::bPassthrough>(bPassthrough);
}
- filterSettings.tlv(tlvFilterSettings);
+ filterSettings.set<DemuxFilterSettings::Tag::tlv>(tlvFilterSettings);
break;
}
case DemuxFilterMainType::ALP: {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration");
- uint8_t packetType = static_cast<uint8_t>(
+ int8_t packetType = static_cast<int8_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I")));
@@ -3711,18 +3689,19 @@ static DemuxFilterSettings getFilterConfiguration(
.lengthType = lengthType,
};
- if (settingsObj != NULL) {
+ if (settingsObj != nullptr) {
DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
switch (alpType) {
case DemuxAlpFilterType::SECTION:
- alpFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
+ alpFilterSettings.filterSettings
+ .set<DemuxAlpFilterSettingsFilterSettings::Tag::section>(
+ getFilterSectionSettings(env, settingsObj));
break;
default:
break;
}
}
- filterSettings.alp(alpFilterSettings);
+ filterSettings.set<DemuxFilterSettings::Tag::alp>(alpFilterSettings);
break;
}
default: {
@@ -3743,34 +3722,33 @@ static Result configureIpFilterContextId(
}
static bool isAvFilterSettings(DemuxFilterSettings filterSettings) {
- return (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts
- && filterSettings.ts().filterSettings.getDiscriminator()
- == DemuxTsFilterSettings::FilterSettings::hidl_discriminator::av)
- ||
- (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp
- && filterSettings.mmtp().filterSettings.getDiscriminator()
- == DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::av);
+ return (filterSettings.getTag() == DemuxFilterSettings::Tag::ts &&
+ filterSettings.get<DemuxFilterSettings::Tag::ts>().filterSettings.getTag() ==
+ DemuxTsFilterSettingsFilterSettings::Tag::av) ||
+ (filterSettings.getTag() == DemuxFilterSettings::Tag::mmtp &&
+ filterSettings.get<DemuxFilterSettings::Tag::mmtp>().filterSettings.getTag() ==
+ DemuxMmtpFilterSettingsFilterSettings::Tag::av);
}
static jint android_media_tv_Tuner_configure_filter(
JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
- ALOGD("configure filter type=%d, subtype=%d", type, subtype);
+ ALOGV("configure filter type=%d, subtype=%d", type, subtype);
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to configure filter: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
Result res = filterClient->configure(filterSettings);
if (res != Result::SUCCESS) {
- return (jint) res;
+ return (jint)res;
}
if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) {
res = configureIpFilterContextId(env, filterClient, settings);
if (res != Result::SUCCESS) {
- return (jint) res;
+ return (jint)res;
}
}
@@ -3778,99 +3756,98 @@ static jint android_media_tv_Tuner_configure_filter(
if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) {
res = filterClient->configureAvStreamType(streamType);
}
- return (jint) res;
+ return (jint)res;
}
static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to get filter ID: filter client not found");
return (int) Result::NOT_INITIALIZED;
}
- uint32_t id;
+ int32_t id;
Result res = filterClient->getId(id);
if (res != Result::SUCCESS) {
- return (jint) Constant::INVALID_FILTER_ID;
+ return (jint)Constant::INVALID_FILTER_ID;
}
- return (jint) id;
+ return (jint)id;
}
static jlong android_media_tv_Tuner_get_filter_64bit_id(JNIEnv* env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to get filter ID 64 bit: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
- uint64_t id;
+ int64_t id;
Result res = filterClient->getId64Bit(id);
- return (res == Result::SUCCESS) ?
- static_cast<jlong>(id) : static_cast<jlong>(
- ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
+ return (res == Result::SUCCESS) ? static_cast<jlong>(id)
+ : static_cast<jlong>(Constant64Bit::INVALID_FILTER_ID_64BIT);
}
static jint android_media_tv_Tuner_configure_monitor_event(
JNIEnv* env, jobject filter, int monitorEventType) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to configure scrambling event: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
Result res = filterClient->configureMonitorEvent(monitorEventType);
- return (jint) res;
+ return (jint)res;
}
static jint android_media_tv_Tuner_set_filter_data_source(
JNIEnv* env, jobject filter, jobject srcFilter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to set filter data source: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
Result res;
- if (srcFilter == NULL) {
- res = filterClient->setDataSource(NULL);
+ if (srcFilter == nullptr) {
+ res = filterClient->setDataSource(nullptr);
} else {
sp<FilterClient> srcClient = getFilterClient(env, srcFilter);
- if (srcClient == NULL) {
+ if (srcClient == nullptr) {
ALOGD("Failed to set filter data source: src filter not found");
- return (jint) Result::INVALID_ARGUMENT;
+ return (jint)Result::INVALID_ARGUMENT;
}
res = filterClient->setDataSource(srcClient);
}
- return (jint) res;
+ return (jint)res;
}
static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to start filter: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
- return (jint) filterClient->start();
+ return (jint)filterClient->start();
}
static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to stop filter: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
- return (jint) filterClient->stop();
+ return (jint)filterClient->stop();
}
static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
ALOGD("Failed to flush filter: filter client not found");
- return (int) Result::NOT_INITIALIZED;
+ return (int)Result::NOT_INITIALIZED;
}
- return (jint) filterClient->flush();
+ return (jint)filterClient->flush();
}
static jint android_media_tv_Tuner_read_filter_fmq(
JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to read filter FMQ: filter client not found");
return -1;
@@ -3878,25 +3855,25 @@ static jint android_media_tv_Tuner_read_filter_fmq(
jboolean isCopy;
jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
- ALOGD("copyData, isCopy=%d", isCopy);
+ ALOGV("copyData, isCopy=%d", isCopy);
if (dst == nullptr) {
jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
return -1;
}
int realReadSize = filterClient->read(reinterpret_cast<int8_t*>(dst) + offset, size);
env->ReleaseByteArrayElements(buffer, dst, 0);
- return (jint) realReadSize;
+ return (jint)realReadSize;
}
static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
+ if (filterClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to close filter: filter client not found");
return 0;
}
- return (jint) filterClient->close();
+ return (jint)filterClient->close();
}
static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) {
@@ -3906,33 +3883,31 @@ static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) {
static int android_media_tv_Tuner_time_filter_set_timestamp(
JNIEnv *env, jobject filter, jlong timestamp) {
sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed set timestamp: time filter client not found");
return (int) Result::INVALID_STATE;
}
- Result r = timeFilterClient->setTimeStamp(static_cast<uint64_t>(timestamp));
- return (int) r;
+ return (int)timeFilterClient->setTimeStamp(static_cast<int64_t>(timestamp));
}
static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed clear timestamp: time filter client not found");
return (int) Result::INVALID_STATE;
}
- Result r = timeFilterClient->clearTimeStamp();
- return (int) r;
+ return (int)timeFilterClient->clearTimeStamp();
}
static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed get timestamp: time filter client not found");
- return NULL;
+ return nullptr;
}
- uint64_t timestamp = timeFilterClient->getTimeStamp();
+ int64_t timestamp = timeFilterClient->getTimeStamp();
if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) {
- return NULL;
+ return nullptr;
}
jclass longClazz = env->FindClass("java/lang/Long");
@@ -3944,13 +3919,13 @@ static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, job
static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed get source time: time filter client not found");
- return NULL;
+ return nullptr;
}
- uint64_t timestamp = timeFilterClient->getSourceTime();
+ int64_t timestamp = timeFilterClient->getSourceTime();
if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) {
- return NULL;
+ return nullptr;
}
jclass longClazz = env->FindClass("java/lang/Long");
@@ -3962,7 +3937,7 @@ static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, j
static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
- if (timeFilterClient == NULL) {
+ if (timeFilterClient == nullptr) {
ALOGD("Failed close time filter: time filter client not found");
return (int) Result::INVALID_STATE;
}
@@ -3972,7 +3947,7 @@ static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter)
timeFilterClient->decStrong(filter);
env->SetLongField(filter, gFields.timeFilterContext, 0);
}
- return (int) r;
+ return (int)r;
}
static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz, jint) {
@@ -3983,48 +3958,48 @@ static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz
static jint android_media_tv_Tuner_descrambler_add_pid(
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler);
- if (descramblerClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (descramblerClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
- sp<FilterClient> filterClient = (filter == NULL) ? NULL : getFilterClient(env, filter);
+ sp<FilterClient> filterClient = (filter == nullptr) ? nullptr : getFilterClient(env, filter);
Result result = descramblerClient->addPid(getDemuxPid((int)pidType, (int)pid), filterClient);
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_descrambler_remove_pid(
JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler);
- if (descramblerClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (descramblerClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
- sp<FilterClient> filterClient = (filter == NULL) ? NULL : getFilterClient(env, filter);
+ sp<FilterClient> filterClient = (filter == nullptr) ? nullptr : getFilterClient(env, filter);
Result result = descramblerClient->removePid(getDemuxPid((int)pidType, (int)pid), filterClient);
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_descrambler_set_key_token(
JNIEnv* env, jobject descrambler, jbyteArray keyToken) {
sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler);
- if (descramblerClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (descramblerClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
int size = env->GetArrayLength(keyToken);
std::vector<uint8_t> v(size);
env->GetByteArrayRegion(keyToken, 0, size, reinterpret_cast<jbyte*>(&v[0]));
Result result = descramblerClient->setKeyToken(v);
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_close_descrambler(JNIEnv* env, jobject descrambler) {
sp<DescramblerClient> descramblerClient = getDescramblerClient(env, descrambler);
- if (descramblerClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (descramblerClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
Result r = descramblerClient->close();
if (r == Result::SUCCESS) {
descramblerClient->decStrong(descrambler);
}
- return (jint) r;
+ return (jint)r;
}
static jobject android_media_tv_Tuner_open_dvr_recorder(
@@ -4046,13 +4021,13 @@ static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv* env, jobject thiz)
static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
- return (jint) tuner->openDemux(handle);
+ return (jint)tuner->openDemux(handle);
}
static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
- setTuner(env, thiz, NULL);
- return (jint) tuner->close();
+ setTuner(env, thiz, nullptr);
+ return (jint)tuner->close();
}
static jint android_media_tv_Tuner_close_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
@@ -4067,97 +4042,94 @@ static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jin
static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
- return (jint) Result::INVALID_ARGUMENT;
+ if (filterClient == nullptr) {
+ return (jint)Result::INVALID_ARGUMENT;
}
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (dvrClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
Result result = dvrClient->attachFilter(filterClient);
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<FilterClient> filterClient = getFilterClient(env, filter);
- if (filterClient == NULL) {
- return (jint) Result::INVALID_ARGUMENT;
+ if (filterClient == nullptr) {
+ return (jint)Result::INVALID_ARGUMENT;
}
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
- return (jint) Result::NOT_INITIALIZED;
+ if (dvrClient == nullptr) {
+ return (jint)Result::NOT_INITIALIZED;
}
Result result = dvrClient->detachFilter(filterClient);
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to configure dvr: dvr client not found");
return (int)Result::NOT_INITIALIZED;
}
bool isRecorder =
env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
Result result = dvrClient->configure(getDvrSettings(env, settings, isRecorder));
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to start dvr: dvr client not found");
- return (jint) Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
Result result = dvrClient->start();
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to stop dvr: dvr client not found");
- return (jint) Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
Result result = dvrClient->stop();
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to flush dvr: dvr client not found");
- return (jint) Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
Result result = dvrClient->flush();
- return (jint) result;
+ return (jint)result;
}
static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to close dvr: dvr client not found");
- return (jint) Result::NOT_INITIALIZED;
+ return (jint)Result::NOT_INITIALIZED;
}
- return (jint) dvrClient->close();
+ return (jint)dvrClient->close();
}
static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) {
sp<LnbClient> lnbClient = getLnbClient(env, lnb);
- Result r = lnbClient->setVoltage(static_cast<LnbVoltage>(voltage));
- return (jint) r;
+ return (jint)lnbClient->setVoltage(static_cast<LnbVoltage>(voltage));
}
static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) {
sp<LnbClient> lnbClient = getLnbClient(env, lnb);
- Result r = lnbClient->setTone(static_cast<LnbTone>(tone));
- return (jint) r;
+ return (jint)lnbClient->setTone(static_cast<LnbTone>(tone));
}
static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) {
sp<LnbClient> lnbClient = getLnbClient(env, lnb);
- Result r = lnbClient->setSatellitePosition(static_cast<LnbPosition>(position));
- return (jint) r;
+ return (jint)lnbClient->setSatellitePosition(static_cast<LnbPosition>(position));
}
static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) {
@@ -4165,8 +4137,7 @@ static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb,
int size = env->GetArrayLength(msg);
std::vector<uint8_t> v(size);
env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0]));
- Result r = lnbClient->sendDiseqcMessage(v);
- return (jint) r;
+ return (jint)lnbClient->sendDiseqcMessage(v);
}
static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
@@ -4176,34 +4147,34 @@ static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
lnbClient->decStrong(lnb);
env->SetLongField(lnb, gFields.lnbContext, 0);
}
- return (jint) r;
+ return (jint)r;
}
static void android_media_tv_Tuner_dvr_set_fd(JNIEnv *env, jobject dvr, jint fd) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGD("Failed to set FD for dvr: dvr client not found");
return;
}
dvrClient->setFd((int)fd);
- ALOGD("set fd = %d", fd);
+ ALOGV("set fd = %d", fd);
}
static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to read dvr: dvr client not found");
return -1;
}
- return (jlong) dvrClient->readFromFile(size);
+ return (jlong)dvrClient->readFromFile(size);
}
static jlong android_media_tv_Tuner_read_dvr_from_array(
JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGW("Failed to read dvr: dvr client not found");
return -1;
}
@@ -4216,32 +4187,31 @@ static jlong android_media_tv_Tuner_read_dvr_from_array(
}
long realSize = dvrClient->readFromBuffer(reinterpret_cast<signed char*>(src) + offset, size);
env->ReleaseByteArrayElements(buffer, src, 0);
- return (jlong) realSize;
-
+ return (jlong)realSize;
}
static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to write dvr: dvr client not found");
return -1;
}
- return (jlong) dvrClient->writeToFile(size);
+ return (jlong)dvrClient->writeToFile(size);
}
static jlong android_media_tv_Tuner_write_dvr_to_array(
JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
sp<DvrClient> dvrClient = getDvrClient(env, dvr);
- if (dvrClient == NULL) {
+ if (dvrClient == nullptr) {
ALOGW("Failed to read dvr: dvr client not found");
return -1;
}
jboolean isCopy;
jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
- ALOGD("copyData, isCopy=%d", isCopy);
+ ALOGV("copyData, isCopy=%d", isCopy);
if (dst == nullptr) {
jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
return -1;
@@ -4249,7 +4219,7 @@ static jlong android_media_tv_Tuner_write_dvr_to_array(
long realSize = dvrClient->writeToBuffer(reinterpret_cast<signed char*>(dst) + offset, size);
env->ReleaseByteArrayElements(buffer, dst, 0);
- return (jlong) realSize;
+ return (jlong)realSize;
}
static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) {
@@ -4259,9 +4229,9 @@ static sp<MediaEvent> getMediaEventSp(JNIEnv *env, jobject mediaEventObj) {
static jobject android_media_tv_Tuner_media_event_get_linear_block(
JNIEnv* env, jobject mediaEventObj) {
sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
- if (mediaEventSp == NULL) {
+ if (mediaEventSp == nullptr) {
ALOGD("Failed get MediaEvent");
- return NULL;
+ return nullptr;
}
android::Mutex::Autolock autoLock(mediaEventSp->mLock);
@@ -4271,9 +4241,9 @@ static jobject android_media_tv_Tuner_media_event_get_linear_block(
static jobject android_media_tv_Tuner_media_event_get_audio_handle(
JNIEnv* env, jobject mediaEventObj) {
sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
- if (mediaEventSp == NULL) {
+ if (mediaEventSp == nullptr) {
ALOGD("Failed get MediaEvent");
- return NULL;
+ return nullptr;
}
android::Mutex::Autolock autoLock(mediaEventSp->mLock);
@@ -4287,7 +4257,7 @@ static jobject android_media_tv_Tuner_media_event_get_audio_handle(
static void android_media_tv_Tuner_media_event_finalize(JNIEnv* env, jobject mediaEventObj) {
sp<MediaEvent> mediaEventSp = getMediaEventSp(env, mediaEventObj);
- if (mediaEventSp == NULL) {
+ if (mediaEventSp == nullptr) {
ALOGD("Failed get MediaEvent");
return;
}
@@ -4307,6 +4277,8 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_get_frontend_ids },
{ "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
(void *)android_media_tv_Tuner_open_frontend_by_handle },
+ { "nativeShareFrontend", "(I)I",
+ (void *)android_media_tv_Tuner_share_frontend },
{ "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
@@ -4494,19 +4466,18 @@ static bool register_android_media_tv_Tuner(JNIEnv *env) {
return true;
}
-jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
-{
- JNIEnv* env = NULL;
+jint JNI_OnLoad(JavaVM *vm, void * /* reserved */) {
+ JNIEnv *env = nullptr;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed\n");
+ ALOGE("ERROR: GetEnv failed");
return result;
}
- assert(env != NULL);
+ assert(env != nullptr);
if (!register_android_media_tv_Tuner(env)) {
- ALOGE("ERROR: Tuner native registration failed\n");
+ ALOGE("ERROR: Tuner native registration failed");
return result;
}
return JNI_VERSION_1_4;
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 2a933b207902..02c347ff0229 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -17,18 +17,35 @@
#ifndef _ANDROID_MEDIA_TV_TUNER_H_
#define _ANDROID_MEDIA_TV_TUNER_H_
-#include <android/hardware/tv/tuner/1.1/types.h>
-
#include <C2BlockInternal.h>
#include <C2HandleIonInternal.h>
#include <C2ParamDef.h>
-#include <fmq/MessageQueue.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxPid.h>
+#include <aidl/android/hardware/tv/tuner/DvrType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendCapabilities.h>
+#include <aidl/android/hardware/tv/tuner/FrontendEventType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendInfo.h>
+#include <aidl/android/hardware/tv/tuner/FrontendScanMessage.h>
+#include <aidl/android/hardware/tv/tuner/FrontendScanMessageType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendScanType.h>
+#include <aidl/android/hardware/tv/tuner/FrontendSettings.h>
+#include <aidl/android/hardware/tv/tuner/LnbEventType.h>
+#include <aidl/android/hardware/tv/tuner/PlaybackStatus.h>
+#include <aidl/android/hardware/tv/tuner/RecordStatus.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
+#include <fmq/AidlMessageQueue.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
#include <fstream>
#include <string>
#include <unordered_map>
-#include <utils/Mutex.h>
-#include <utils/RefBase.h>
+#include "jni.h"
#include "tuner/DemuxClient.h"
#include "tuner/DescramblerClient.h"
#include "tuner/FilterClient.h"
@@ -39,48 +56,36 @@
#include "tuner/LnbClientCallback.h"
#include "tuner/TimeFilterClient.h"
#include "tuner/TunerClient.h"
-#include "jni.h"
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMonitorEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxPid;
+using ::aidl::android::hardware::tv::tuner::DvrType;
+using ::aidl::android::hardware::tv::tuner::FrontendCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendEventType;
+using ::aidl::android::hardware::tv::tuner::FrontendInfo;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessage;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanType;
+using ::aidl::android::hardware::tv::tuner::FrontendSettings;
+using ::aidl::android::hardware::tv::tuner::LnbEventType;
+using ::aidl::android::hardware::tv::tuner::PlaybackStatus;
+using ::aidl::android::hardware::tv::tuner::RecordStatus;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::android::hardware::EventFlag;
-using ::android::hardware::MQDescriptorSync;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::kSynchronizedReadWrite;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxPid;
-using ::android::hardware::tv::tuner::V1_0::DvrType;
-using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
-using ::android::hardware::tv::tuner::V1_0::FrontendId;
-using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
-using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
-using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_0::LnbEventType;
-using ::android::hardware::tv::tuner::V1_0::LnbId;
-using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
-using ::android::hardware::tv::tuner::V1_0::RecordStatus;
-using ::android::hardware::tv::tuner::V1_0::Result;
-using ::android::hardware::tv::tuner::V1_1::DemuxFilterEventExt;
-using ::android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEvent;
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
-
-using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-
-const static int TUNER_VERSION_1_1 = ((1 << 16) | 1);
+
+using MQ = MQDescriptor<int8_t, SynchronizedReadWrite>;
namespace android {
struct LnbClientCallbackImpl : public LnbClientCallback {
~LnbClientCallbackImpl();
virtual void onEvent(LnbEventType lnbEventType);
- virtual void onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+ virtual void onDiseqcMessage(const vector<uint8_t>& diseqcMessage);
void setLnb(jweak lnbObj);
private:
@@ -98,8 +103,8 @@ private:
};
struct MediaEvent : public RefBase {
- MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle, uint64_t dataId,
- uint64_t dataSize, jobject obj);
+ MediaEvent(sp<FilterClient> filterClient, native_handle_t* avHandle, uint64_t dataId,
+ uint64_t dataSize, jobject obj);
~MediaEvent();
jobject getLinearBlock();
uint64_t getAudioHandle();
@@ -121,39 +126,24 @@ struct MediaEvent : public RefBase {
struct FilterClientCallbackImpl : public FilterClientCallback {
~FilterClientCallbackImpl();
- virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
- const DemuxFilterEventExt& filterEventExt);
- virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
+ virtual void onFilterEvent(const vector<DemuxFilterEvent>& events);
virtual void onFilterStatus(const DemuxFilterStatus status);
void setFilter(jweak filterObj, sp<FilterClient> filterClient);
private:
jweak mFilterObj;
sp<FilterClient> mFilterClient;
- jobjectArray getSectionEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getMediaEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getPesEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getTsRecordEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>&events,
- const std::vector<DemuxFilterEventExt::Event>& eventsExt);
- jobjectArray getMmtpRecordEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>&events,
- const std::vector<DemuxFilterEventExt::Event>& eventsExt);
- jobjectArray getDownloadEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getIpPayloadEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getTemiEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
- jobjectArray getScramblingStatusEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt);
- jobjectArray getIpCidChangeEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt);
- jobjectArray getRestartEvent(
- jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt);
+ void getSectionEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getMediaEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getPesEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getTsRecordEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getMmtpRecordEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getDownloadEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getIpPayloadEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getTemiEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getScramblingStatusEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getIpCidChangeEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
+ void getRestartEvent(jobjectArray& arr, const int size, const DemuxFilterEvent& event);
};
struct FrontendClientCallbackImpl : public FrontendClientCallback {
@@ -162,8 +152,6 @@ struct FrontendClientCallbackImpl : public FrontendClientCallback {
virtual void onEvent(FrontendEventType frontendEventType);
virtual void onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
- virtual void onScanMessageExt1_1(
- FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
jweak mObject;
};
@@ -179,12 +167,12 @@ struct JTuner : public RefBase {
int unlinkCiCam(jint id);
jobject getFrontendIds();
jobject openFrontendByHandle(int feHandle);
+ int shareFrontend(int feId);
jint closeFrontendById(int id);
jobject getFrontendInfo(int id);
- int tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
+ int tune(const FrontendSettings& settings);
int stopTune();
- int scan(const FrontendSettings& settings, FrontendScanType scanType,
- const FrontendSettingsExt1_1& settingsExt1_1);
+ int scan(const FrontendSettings& settings, FrontendScanType scanType);
int stopScan();
int setLnb(sp<LnbClient> lnbClient);
int setLna(bool enable);
@@ -210,20 +198,19 @@ private:
static sp<TunerClient> mTunerClient;
sp<FrontendClient> mFeClient;
int mFeId;
+ int mSharedFeId;
sp<LnbClient> mLnbClient;
sp<DemuxClient> mDemuxClient;
- static jobject getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getDvbcFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getDvbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getDvbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
- static jobject getDtmbFrontendCaps(JNIEnv *env, int id);
-
- bool isV1_1ExtendedStatusType(jint type);
+ static jobject getAnalogFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getAtsc3FrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getAtscFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getDvbcFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getDvbsFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getDvbtFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getIsdbs3FrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getIsdbsFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getIsdbtFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
+ static jobject getDtmbFrontendCaps(JNIEnv* env, FrontendCapabilities& caps);
};
class C2DataIdInfo : public C2Param {
diff --git a/media/jni/tuner/ClientHelper.h b/media/jni/tuner/ClientHelper.h
index 508dccf36841..d7a847a8f5b8 100644
--- a/media/jni/tuner/ClientHelper.h
+++ b/media/jni/tuner/ClientHelper.h
@@ -17,22 +17,18 @@
#ifndef _ANDROID_MEDIA_TV_CLIENT_HELPER_H_
#define _ANDROID_MEDIA_TV_CLIENT_HELPER_H_
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <android/binder_parcel_utils.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
#include <utils/Log.h>
+using ::aidl::android::hardware::tv::tuner::Result;
using Status = ::ndk::ScopedAStatus;
-using ::android::hardware::tv::tuner::V1_0::Result;
-
-using namespace std;
-
namespace android {
-struct ClientHelper {
-
+class ClientHelper {
public:
- static Result getServiceSpecificErrorCode(Status& s) {
+ static Result getServiceSpecificErrorCode(Status& s) {
if (s.getExceptionCode() == EX_SERVICE_SPECIFIC) {
return static_cast<Result>(s.getServiceSpecificError());
} else if (s.isOk()) {
@@ -42,6 +38,7 @@ public:
return Result::UNKNOWN_ERROR;
}
};
+
} // namespace android
-#endif // _ANDROID_MEDIA_TV_CLIENT_HELPER_H_ \ No newline at end of file
+#endif // _ANDROID_MEDIA_TV_CLIENT_HELPER_H_
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
index 78cb5b003a38..4ee3f4803056 100644
--- a/media/jni/tuner/DemuxClient.cpp
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,295 +16,156 @@
#define LOG_TAG "DemuxClient"
-#include <android-base/logging.h>
-#include <utils/Log.h>
-
#include "DemuxClient.h"
-using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
+#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <aidl/android/hardware/tv/tuner/Constant64Bit.h>
+#include <android-base/logging.h>
+#include <utils/Log.h>
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using ::android::hardware::tv::tuner::V1_0::Result;
+using ::aidl::android::hardware::tv::tuner::Constant;
+using ::aidl::android::hardware::tv::tuner::Constant64Bit;
namespace android {
-
/////////////// DemuxClient ///////////////////////
-
DemuxClient::DemuxClient(shared_ptr<ITunerDemux> tunerDemux) {
mTunerDemux = tunerDemux;
- mId = -1;
}
DemuxClient::~DemuxClient() {
- mTunerDemux = NULL;
- mDemux = NULL;
- mId = -1;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void DemuxClient::setHidlDemux(sp<IDemux> demux) {
- mDemux = demux;
+ mTunerDemux = nullptr;
}
Result DemuxClient::setFrontendDataSource(sp<FrontendClient> frontendClient) {
- if (mTunerDemux != NULL) {
+ if (frontendClient == nullptr) {
+ return Result::INVALID_ARGUMENT;
+ }
+
+ if (mTunerDemux != nullptr) {
Status s = mTunerDemux->setFrontendDataSource(frontendClient->getAidlFrontend());
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDemux != NULL) {
- Result res = mDemux->setFrontendDataSource(frontendClient->getId());
- return res;
+ return Result::INVALID_STATE;
+}
+
+Result DemuxClient::setFrontendDataSourceById(int frontendId) {
+ if (mTunerDemux != nullptr) {
+ Status s = mTunerDemux->setFrontendDataSourceById(frontendId);
+ return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
-sp<FilterClient> DemuxClient::openFilter(DemuxFilterType type, int bufferSize,
- sp<FilterClientCallback> cb) {
- if (mTunerDemux != NULL) {
+sp<FilterClient> DemuxClient::openFilter(const DemuxFilterType& type, int32_t bufferSize,
+ sp<FilterClientCallback> cb) {
+ if (cb == nullptr) {
+ return nullptr;
+ }
+
+ if (mTunerDemux != nullptr) {
shared_ptr<ITunerFilter> tunerFilter;
shared_ptr<TunerFilterCallback> callback =
::ndk::SharedRefBase::make<TunerFilterCallback>(cb);
- Status s = mTunerDemux->openFilter((int)type.mainType, getSubType(type),
- bufferSize, callback, &tunerFilter);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ Status s = mTunerDemux->openFilter(type, bufferSize, callback, &tunerFilter);
+ if (!s.isOk()) {
+ return nullptr;
}
return new FilterClient(type, tunerFilter);
}
- if (mDemux != NULL) {
- sp<HidlFilterCallback> callback = new HidlFilterCallback(cb);
- sp<IFilter> hidlFilter = openHidlFilter(type, bufferSize, callback);
- if (hidlFilter != NULL) {
- sp<FilterClient> filterClient = new FilterClient(type, NULL);
- filterClient->setHidlFilter(hidlFilter);
- return filterClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
sp<TimeFilterClient> DemuxClient::openTimeFilter() {
- if (mTunerDemux != NULL) {
+ if (mTunerDemux != nullptr) {
shared_ptr<ITunerTimeFilter> tunerTimeFilter;
Status s = mTunerDemux->openTimeFilter(&tunerTimeFilter);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
return new TimeFilterClient(tunerTimeFilter);
}
- if (mDemux != NULL) {
- sp<ITimeFilter> hidlTimeFilter = openHidlTimeFilter();
- if (hidlTimeFilter != NULL) {
- sp<TimeFilterClient> timeFilterClient = new TimeFilterClient(NULL);
- timeFilterClient->setHidlTimeFilter(hidlTimeFilter);
- return timeFilterClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
-int DemuxClient::getAvSyncHwId(sp<FilterClient> filterClient) {
- if (mTunerDemux != NULL) {
- int hwId;
- Status s = mTunerDemux->getAvSyncHwId(filterClient->getAidlFilter(), &hwId);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return INVALID_AV_SYNC_HW_ID;
- }
- return hwId;
+int32_t DemuxClient::getAvSyncHwId(sp<FilterClient> filterClient) {
+ if (filterClient == nullptr) {
+ return static_cast<int32_t>(Constant::INVALID_AV_SYNC_ID);
}
- if (mDemux != NULL) {
- uint32_t avSyncHwId;
- Result res;
- sp<IFilter> halFilter = filterClient->getHalFilter();
- mDemux->getAvSyncHwId(halFilter,
- [&](Result r, uint32_t id) {
- res = r;
- avSyncHwId = id;
- });
- if (res == Result::SUCCESS) {
- return (int) avSyncHwId;
+ if (mTunerDemux != nullptr) {
+ int32_t hwId;
+ Status s = mTunerDemux->getAvSyncHwId(filterClient->getAidlFilter(), &hwId);
+ if (!s.isOk()) {
+ return static_cast<int32_t>(Constant::INVALID_AV_SYNC_ID);
}
+ return hwId;
}
- return INVALID_AV_SYNC_HW_ID;
+ return static_cast<int32_t>(Constant::INVALID_AV_SYNC_ID);
}
-long DemuxClient::getAvSyncTime(int avSyncHwId) {
- if (mTunerDemux != NULL) {
+int64_t DemuxClient::getAvSyncTime(int32_t avSyncHwId) {
+ if (mTunerDemux != nullptr) {
int64_t time;
Status s = mTunerDemux->getAvSyncTime(avSyncHwId, &time);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return INVALID_AV_SYNC_TIME;
+ if (!s.isOk()) {
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
return time;
}
- if (mDemux != NULL) {
- uint64_t time;
- Result res;
- mDemux->getAvSyncTime(static_cast<uint32_t>(avSyncHwId),
- [&](Result r, uint64_t ts) {
- res = r;
- time = ts;
- });
- if (res == Result::SUCCESS) {
- return (long) time;
- }
- }
-
- return INVALID_AV_SYNC_TIME;
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
-sp<DvrClient> DemuxClient::openDvr(DvrType dvbType, int bufferSize, sp<DvrClientCallback> cb) {
- if (mTunerDemux != NULL) {
+sp<DvrClient> DemuxClient::openDvr(DvrType dvbType, int32_t bufferSize, sp<DvrClientCallback> cb) {
+ if (cb == nullptr) {
+ return nullptr;
+ }
+
+ if (mTunerDemux != nullptr) {
shared_ptr<ITunerDvr> tunerDvr;
shared_ptr<TunerDvrCallback> callback =
::ndk::SharedRefBase::make<TunerDvrCallback>(cb);
- Status s = mTunerDemux->openDvr((int)dvbType, bufferSize, callback, &tunerDvr);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ Status s = mTunerDemux->openDvr(dvbType, bufferSize, callback, &tunerDvr);
+ if (!s.isOk()) {
+ return nullptr;
}
return new DvrClient(tunerDvr);
}
- if (mDemux != NULL) {
- sp<HidlDvrCallback> callback = new HidlDvrCallback(cb);
- sp<IDvr> hidlDvr = openHidlDvr(dvbType, bufferSize, callback);
- if (hidlDvr != NULL) {
- sp<DvrClient> dvrClient = new DvrClient(NULL);
- dvrClient->setHidlDvr(hidlDvr);
- return dvrClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
-Result DemuxClient::connectCiCam(int ciCamId) {
- if (mTunerDemux != NULL) {
+Result DemuxClient::connectCiCam(int32_t ciCamId) {
+ if (mTunerDemux != nullptr) {
Status s = mTunerDemux->connectCiCam(ciCamId);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDemux != NULL) {
- return mDemux->connectCiCam(static_cast<uint32_t>(ciCamId));
- }
-
return Result::INVALID_STATE;
}
Result DemuxClient::disconnectCiCam() {
- if (mTunerDemux != NULL) {
+ if (mTunerDemux != nullptr) {
Status s = mTunerDemux->disconnectCiCam();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDemux != NULL) {
- return mDemux->disconnectCiCam();
- }
-
return Result::INVALID_STATE;
}
Result DemuxClient::close() {
- if (mTunerDemux != NULL) {
+ if (mTunerDemux != nullptr) {
Status s = mTunerDemux->close();
- mTunerDemux = NULL;
+ mTunerDemux = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDemux != NULL) {
- Result res = mDemux->close();
- mDemux = NULL;
- return res;
- }
-
return Result::INVALID_STATE;
}
-/////////////// DemuxClient Helper Methods ///////////////////////
-
-sp<IFilter> DemuxClient::openHidlFilter(DemuxFilterType type, int bufferSize,
- sp<HidlFilterCallback> callback) {
- if (mDemux == NULL) {
- return NULL;
- }
-
- sp<IFilter> hidlFilter;
- Result res;
- mDemux->openFilter(type, bufferSize, callback,
- [&](Result r, const sp<IFilter>& filter) {
- hidlFilter = filter;
- res = r;
- });
- if (res != Result::SUCCESS || hidlFilter == NULL) {
- return NULL;
- }
-
- return hidlFilter;
-}
-
-sp<ITimeFilter> DemuxClient::openHidlTimeFilter() {
- if (mDemux == NULL) {
- return NULL;
- }
-
- sp<ITimeFilter> timeFilter;
- Result res;
- mDemux->openTimeFilter(
- [&](Result r, const sp<ITimeFilter>& timeFilterSp) {
- timeFilter = timeFilterSp;
- res = r;
- });
-
- if (res != Result::SUCCESS || timeFilter == NULL) {
- return NULL;
- }
-
- return timeFilter;
-}
-
-sp<IDvr> DemuxClient::openHidlDvr(DvrType dvrType, int bufferSize,
- sp<HidlDvrCallback> callback) {
- if (mDemux == NULL) {
- return NULL;
- }
-
- sp<IDvr> hidlDvr;
- Result res;
- mDemux->openDvr(dvrType, bufferSize, callback,
- [&](Result r, const sp<IDvr>& dvr) {
- hidlDvr = dvr;
- res = r;
- });
- if (res != Result::SUCCESS || hidlDvr == NULL) {
- return NULL;
- }
-
- return hidlDvr;
-}
-
-int DemuxClient::getSubType(DemuxFilterType filterType) {
- switch (filterType.mainType) {
- case DemuxFilterMainType::TS:
- return (int)filterType.subType.tsFilterType();
- case DemuxFilterMainType::MMTP:
- return (int)filterType.subType.mmtpFilterType();
- case DemuxFilterMainType::IP:
- return (int)filterType.subType.ipFilterType();
- case DemuxFilterMainType::TLV:
- return (int)filterType.subType.tlvFilterType();
- case DemuxFilterMainType::ALP:
- return (int)filterType.subType.alpFilterType();
- default:
- return -1;
- }
-}
} // namespace android
diff --git a/media/jni/tuner/DemuxClient.h b/media/jni/tuner/DemuxClient.h
index c38a8fa34690..d5f5f2ff0dbf 100644
--- a/media/jni/tuner/DemuxClient.h
+++ b/media/jni/tuner/DemuxClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,12 +17,11 @@
#ifndef _ANDROID_MEDIA_TV_DEMUX_CLIENT_H_
#define _ANDROID_MEDIA_TV_DEMUX_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidl/android/media/tv/tuner/ITunerDemux.h>
-#include <android/hardware/tv/tuner/1.0/IDemux.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
-#include "DvrClient.h"
#include "ClientHelper.h"
+#include "DvrClient.h"
#include "DvrClientCallback.h"
#include "FilterClient.h"
#include "FilterClientCallback.h"
@@ -30,20 +29,14 @@
#include "TimeFilterClient.h"
using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
+using ::aidl::android::hardware::tv::tuner::DvrType;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tuner::ITunerDemux;
using ::aidl::android::media::tv::tuner::ITunerTimeFilter;
-using ::android::hardware::tv::tuner::V1_0::IDemux;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
-using ::android::hardware::tv::tuner::V1_0::DvrType;
-using ::android::hardware::tv::tuner::V1_0::IDemux;
-using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
-
using namespace std;
-const int64_t INVALID_AV_SYNC_TIME = -1;
-const int INVALID_AV_SYNC_HW_ID = -1;
-
namespace android {
struct DemuxClient : public RefBase {
@@ -52,18 +45,21 @@ public:
DemuxClient(shared_ptr<ITunerDemux> tunerDemux);
~DemuxClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlDemux(sp<IDemux> demux);
-
/**
* Set a frontend resource as data input of the demux.
*/
Result setFrontendDataSource(sp<FrontendClient> frontendClient);
/**
+ * Set a frontend resource by handle as data input of the demux.
+ */
+ Result setFrontendDataSourceById(int frontendId);
+
+ /**
* Open a new filter client.
*/
- sp<FilterClient> openFilter(DemuxFilterType type, int bufferSize, sp<FilterClientCallback> cb);
+ sp<FilterClient> openFilter(const DemuxFilterType& type, int32_t bufferSize,
+ sp<FilterClientCallback> cb);
/**
* Open time filter of the demux.
@@ -73,22 +69,22 @@ public:
/**
* Get hardware sync ID for audio and video.
*/
- int getAvSyncHwId(sp<FilterClient> filterClient);
+ int32_t getAvSyncHwId(sp<FilterClient> filterClient);
/**
* Get current time stamp to use for A/V sync.
*/
- long getAvSyncTime(int avSyncHwId);
+ int64_t getAvSyncTime(int32_t avSyncHwId);
/**
* Open a DVR (Digital Video Record) client.
*/
- sp<DvrClient> openDvr(DvrType dvbType, int bufferSize, sp<DvrClientCallback> cb);
+ sp<DvrClient> openDvr(DvrType dvbType, int32_t bufferSize, sp<DvrClientCallback> cb);
/**
* Connect Conditional Access Modules (CAM) through Common Interface (CI).
*/
- Result connectCiCam(int ciCamId);
+ Result connectCiCam(int32_t ciCamId);
/**
* Disconnect Conditional Access Modules (CAM).
@@ -105,29 +101,12 @@ public:
*/
shared_ptr<ITunerDemux> getAidlDemux() { return mTunerDemux; }
- void setId(int id) { mId = id; }
- int getId() { return mId; }
-
private:
- sp<IFilter> openHidlFilter(DemuxFilterType type, int bufferSize, sp<HidlFilterCallback> cb);
- sp<ITimeFilter> openHidlTimeFilter();
- sp<IDvr> openHidlDvr(DvrType type, int bufferSize, sp<HidlDvrCallback> cb);
- int getSubType(DemuxFilterType filterType);
-
/**
* An AIDL Tuner Demux Singleton assigned at the first time the Tuner Client
* opens a demux. Default null when demux is not opened.
*/
shared_ptr<ITunerDemux> mTunerDemux;
-
- /**
- * A Demux HAL interface that is ready before migrating to the TunerDemux.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<IDemux> mDemux;
-
- int mId;
};
} // namespace android
diff --git a/media/jni/tuner/DescramblerClient.cpp b/media/jni/tuner/DescramblerClient.cpp
index 3e4ed8280ee6..052fa7aa6d81 100644
--- a/media/jni/tuner/DescramblerClient.cpp
+++ b/media/jni/tuner/DescramblerClient.cpp
@@ -21,118 +21,69 @@
#include "DescramblerClient.h"
-using ::android::hardware::tv::tuner::V1_0::Result;
-
namespace android {
/////////////// DescramblerClient ///////////////////////
-
DescramblerClient::DescramblerClient(shared_ptr<ITunerDescrambler> tunerDescrambler) {
mTunerDescrambler = tunerDescrambler;
}
DescramblerClient::~DescramblerClient() {
- mTunerDescrambler = NULL;
- mDescrambler = NULL;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void DescramblerClient::setHidlDescrambler(sp<IDescrambler> descrambler) {
- mDescrambler = descrambler;
+ mTunerDescrambler = nullptr;
}
Result DescramblerClient::setDemuxSource(sp<DemuxClient> demuxClient) {
- if (demuxClient == NULL) {
+ if (demuxClient == nullptr) {
return Result::INVALID_ARGUMENT;
}
- if (mTunerDescrambler != NULL) {
+ if (mTunerDescrambler != nullptr) {
Status s = mTunerDescrambler->setDemuxSource(demuxClient->getAidlDemux());
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDescrambler != NULL) {
- return mDescrambler->setDemuxSource(demuxClient->getId());
- }
-
return Result::INVALID_STATE;
}
Result DescramblerClient::setKeyToken(vector<uint8_t> keyToken) {
- if (mTunerDescrambler != NULL) {
+ if (mTunerDescrambler != nullptr) {
Status s = mTunerDescrambler->setKeyToken(keyToken);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDescrambler != NULL) {
- return mDescrambler->setKeyToken(keyToken);
- }
-
return Result::INVALID_STATE;
}
Result DescramblerClient::addPid(DemuxPid pid, sp<FilterClient> optionalSourceFilter) {
- if (mTunerDescrambler != NULL) {
- shared_ptr<ITunerFilter> aidlFilter = (optionalSourceFilter == NULL)
- ? NULL : optionalSourceFilter->getAidlFilter();
- Status s = mTunerDescrambler->addPid(getAidlDemuxPid(pid), aidlFilter);
+ if (mTunerDescrambler != nullptr) {
+ shared_ptr<ITunerFilter> aidlFilter =
+ (optionalSourceFilter == nullptr) ? nullptr : optionalSourceFilter->getAidlFilter();
+ Status s = mTunerDescrambler->addPid(pid, aidlFilter);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDescrambler != NULL) {
- sp<IFilter> halFilter = (optionalSourceFilter == NULL)
- ? NULL : optionalSourceFilter->getHalFilter();
- return mDescrambler->addPid(pid, halFilter);
- }
-
return Result::INVALID_STATE;
}
Result DescramblerClient::removePid(DemuxPid pid, sp<FilterClient> optionalSourceFilter) {
- if (mTunerDescrambler != NULL) {
- shared_ptr<ITunerFilter> aidlFilter = (optionalSourceFilter == NULL)
- ? NULL : optionalSourceFilter->getAidlFilter();
- Status s = mTunerDescrambler->removePid(getAidlDemuxPid(pid), aidlFilter);
+ if (mTunerDescrambler != nullptr) {
+ shared_ptr<ITunerFilter> aidlFilter =
+ (optionalSourceFilter == nullptr) ? nullptr : optionalSourceFilter->getAidlFilter();
+ Status s = mTunerDescrambler->removePid(pid, aidlFilter);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDescrambler != NULL) {
- sp<IFilter> halFilter = (optionalSourceFilter == NULL)
- ? NULL : optionalSourceFilter->getHalFilter();
- return mDescrambler->removePid(pid, halFilter);
- }
-
return Result::INVALID_STATE;
}
Result DescramblerClient::close() {
- if (mTunerDescrambler != NULL) {
+ if (mTunerDescrambler != nullptr) {
Status s = mTunerDescrambler->close();
- mTunerDescrambler = NULL;
+ mTunerDescrambler = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDescrambler != NULL) {
- Result res = mDescrambler->close();
- mDescrambler = NULL;
- return res;
- }
-
return Result::INVALID_STATE;
}
-/////////////// DescramblerClient Helper Methods ///////////////////////
-
-TunerDemuxPid DescramblerClient::getAidlDemuxPid(DemuxPid& pid) {
- TunerDemuxPid aidlPid;
- switch (pid.getDiscriminator()) {
- case DemuxPid::hidl_discriminator::tPid:
- aidlPid.set<TunerDemuxPid::tPid>((int)pid.tPid());
- break;
- case DemuxPid::hidl_discriminator::mmtpPid:
- aidlPid.set<TunerDemuxPid::mmtpPid>((int)pid.mmtpPid());
- break;
- }
- return aidlPid;
-}
} // namespace android
diff --git a/media/jni/tuner/DescramblerClient.h b/media/jni/tuner/DescramblerClient.h
index a8fa1e2e0497..c851e841b2c0 100644
--- a/media/jni/tuner/DescramblerClient.h
+++ b/media/jni/tuner/DescramblerClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,19 +17,15 @@
#ifndef _ANDROID_MEDIA_TV_DESCRAMBLER_CLIENT_H_
#define _ANDROID_MEDIA_TV_DESCRAMBLER_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidl/android/media/tv/tuner/ITunerDescrambler.h>
-#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
#include "DemuxClient.h"
#include "FilterClient.h"
+using ::aidl::android::hardware::tv::tuner::DemuxPid;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tuner::ITunerDescrambler;
-using ::aidl::android::media::tv::tuner::TunerDemuxPid;
-
-using ::android::hardware::tv::tuner::V1_0::IDescrambler;
-using ::android::hardware::tv::tuner::V1_0::Result;
-using ::android::hardware::tv::tuner::V1_0::DemuxPid;
using namespace std;
@@ -41,9 +37,6 @@ public:
DescramblerClient(shared_ptr<ITunerDescrambler> tunerDescrambler);
~DescramblerClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlDescrambler(sp<IDescrambler> descrambler);
-
/**
* Set a demux as source of the descrambler.
*/
@@ -70,20 +63,11 @@ public:
Result close();
private:
- TunerDemuxPid getAidlDemuxPid(DemuxPid& pid);
-
/**
* An AIDL Tuner Descrambler Singleton assigned at the first time the Tuner Client
* opens a descrambler. Default null when descrambler is not opened.
*/
shared_ptr<ITunerDescrambler> mTunerDescrambler;
-
- /**
- * A Descrambler HAL interface that is ready before migrating to the TunerDescrambler.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<IDescrambler> mDescrambler;
};
} // namespace android
diff --git a/media/jni/tuner/DvrClient.cpp b/media/jni/tuner/DvrClient.cpp
index 0476216dcbed..052b465f7b84 100644
--- a/media/jni/tuner/DvrClient.cpp
+++ b/media/jni/tuner/DvrClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,48 +14,42 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
#define LOG_TAG "DvrClient"
+#include "DvrClient.h"
+
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
#include <android-base/logging.h>
-#include <fmq/ConvertMQDescriptors.h>
+#include <inttypes.h>
#include <utils/Log.h>
#include "ClientHelper.h"
-#include "DvrClient.h"
-using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
-using ::android::hardware::tv::tuner::V1_0::Result;
+using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
namespace android {
-
/////////////// DvrClient ///////////////////////
-
DvrClient::DvrClient(shared_ptr<ITunerDvr> tunerDvr) {
mTunerDvr = tunerDvr;
mFd = -1;
- mDvrMQ = NULL;
- mDvrMQEventFlag = NULL;
+ mDvrMQ = nullptr;
+ mDvrMQEventFlag = nullptr;
}
DvrClient::~DvrClient() {
- mTunerDvr = NULL;
- mDvr = NULL;
+ mTunerDvr = nullptr;
mFd = -1;
- mDvrMQ = NULL;
- mDvrMQEventFlag = NULL;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void DvrClient::setHidlDvr(sp<IDvr> dvr) {
- mDvr = dvr;
+ mDvrMQ = nullptr;
+ mDvrMQEventFlag = nullptr;
}
-void DvrClient::setFd(int fd) {
+void DvrClient::setFd(int32_t fd) {
mFd = fd;
}
-long DvrClient::readFromFile(long size) {
- if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
+int64_t DvrClient::readFromFile(int64_t size) {
+ if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
ALOGE("Failed to readFromFile. DVR mq is not configured");
return -1;
}
@@ -64,16 +58,16 @@ long DvrClient::readFromFile(long size) {
return -1;
}
- long available = mDvrMQ->availableToWrite();
- long write = min(size, available);
+ int64_t available = mDvrMQ->availableToWrite();
+ int64_t write = min(size, available);
AidlMQ::MemTransaction tx;
- long ret = 0;
+ int64_t ret = 0;
if (mDvrMQ->beginWrite(write, &tx)) {
auto first = tx.getFirstRegion();
auto data = first.getAddress();
- long length = first.getLength();
- long firstToWrite = min(length, write);
+ int64_t length = first.getLength();
+ int64_t firstToWrite = min(length, write);
ret = read(mFd, data, firstToWrite);
if (ret < 0) {
@@ -81,17 +75,20 @@ long DvrClient::readFromFile(long size) {
return -1;
}
if (ret < firstToWrite) {
- ALOGW("file to MQ, first region: %ld bytes to write, but %ld bytes written",
- firstToWrite, ret);
+ ALOGW("file to MQ, first region: %" PRIu64 " bytes to write, but %" PRIu64
+ " bytes written",
+ firstToWrite, ret);
} else if (firstToWrite < write) {
- ALOGD("write second region: %ld bytes written, %ld bytes in total", ret, write);
+ ALOGV("write second region: %" PRIu64 " bytes written, %" PRIu64 " bytes in total", ret,
+ write);
auto second = tx.getSecondRegion();
data = second.getAddress();
length = second.getLength();
- int secondToWrite = std::min(length, write - firstToWrite);
+ int64_t secondToWrite = std::min(length, write - firstToWrite);
ret += read(mFd, data, secondToWrite);
}
- ALOGD("file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
+ ALOGV("file to MQ: %" PRIu64 " bytes need to be written, %" PRIu64 " bytes written", write,
+ ret);
if (!mDvrMQ->commitWrite(ret)) {
ALOGE("Error: failed to commit write!");
return -1;
@@ -106,8 +103,8 @@ long DvrClient::readFromFile(long size) {
return ret;
}
-long DvrClient::readFromBuffer(int8_t* buffer, long size) {
- if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
+int64_t DvrClient::readFromBuffer(int8_t* buffer, int64_t size) {
+ if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
ALOGE("Failed to readFromBuffer. DVR mq is not configured");
return -1;
}
@@ -116,7 +113,7 @@ long DvrClient::readFromBuffer(int8_t* buffer, long size) {
return -1;
}
- long available = mDvrMQ->availableToWrite();
+ int64_t available = mDvrMQ->availableToWrite();
size = min(size, available);
if (mDvrMQ->write(buffer, size)) {
@@ -128,8 +125,8 @@ long DvrClient::readFromBuffer(int8_t* buffer, long size) {
return size;
}
-long DvrClient::writeToFile(long size) {
- if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
+int64_t DvrClient::writeToFile(int64_t size) {
+ if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
ALOGE("Failed to writeToFile. DVR mq is not configured");
return -1;
}
@@ -138,16 +135,16 @@ long DvrClient::writeToFile(long size) {
return -1;
}
- long available = mDvrMQ->availableToRead();
- long toRead = min(size, available);
+ int64_t available = mDvrMQ->availableToRead();
+ int64_t toRead = min(size, available);
- long ret = 0;
+ int64_t ret = 0;
AidlMQ::MemTransaction tx;
if (mDvrMQ->beginRead(toRead, &tx)) {
auto first = tx.getFirstRegion();
auto data = first.getAddress();
- long length = first.getLength();
- long firstToRead = std::min(length, toRead);
+ int64_t length = first.getLength();
+ int64_t firstToRead = std::min(length, toRead);
ret = write(mFd, data, firstToRead);
if (ret < 0) {
@@ -155,16 +152,18 @@ long DvrClient::writeToFile(long size) {
return -1;
}
if (ret < firstToRead) {
- ALOGW("MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
+ ALOGW("MQ to file: %" PRIu64 " bytes read, but %" PRIu64 " bytes written", firstToRead,
+ ret);
} else if (firstToRead < toRead) {
- ALOGD("read second region: %ld bytes read, %ld bytes in total", ret, toRead);
+ ALOGV("read second region: %" PRIu64 " bytes read, %" PRIu64 " bytes in total", ret,
+ toRead);
auto second = tx.getSecondRegion();
data = second.getAddress();
length = second.getLength();
- int secondToRead = toRead - firstToRead;
+ int32_t secondToRead = toRead - firstToRead;
ret += write(mFd, data, secondToRead);
}
- ALOGD("MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
+ ALOGV("MQ to file: %" PRIu64 " bytes to be read, %" PRIu64 " bytes written", toRead, ret);
if (!mDvrMQ->commitRead(ret)) {
ALOGE("Error: failed to commit read!");
return 0;
@@ -179,8 +178,8 @@ long DvrClient::writeToFile(long size) {
return ret;
}
-long DvrClient::writeToBuffer(int8_t* buffer, long size) {
- if (mDvrMQ == NULL || mDvrMQEventFlag == NULL) {
+int64_t DvrClient::writeToBuffer(int8_t* buffer, int64_t size) {
+ if (mDvrMQ == nullptr || mDvrMQEventFlag == nullptr) {
ALOGE("Failed to writetoBuffer. DVR mq is not configured");
return -1;
}
@@ -189,7 +188,7 @@ long DvrClient::writeToBuffer(int8_t* buffer, long size) {
return -1;
}
- long available = mDvrMQ->availableToRead();
+ int64_t available = mDvrMQ->availableToRead();
size = min(size, available);
if (mDvrMQ->read(buffer, size)) {
@@ -202,9 +201,8 @@ long DvrClient::writeToBuffer(int8_t* buffer, long size) {
}
Result DvrClient::configure(DvrSettings settings) {
- if (mTunerDvr != NULL) {
- TunerDvrSettings dvrSettings = getAidlDvrSettingsFromHidl(settings);
- Status s = mTunerDvr->configure(dvrSettings);
+ if (mTunerDvr != nullptr) {
+ Status s = mTunerDvr->configure(settings);
Result res = ClientHelper::getServiceSpecificErrorCode(s);
if (res != Result::SUCCESS) {
return res;
@@ -221,196 +219,95 @@ Result DvrClient::configure(DvrSettings settings) {
return res;
}
- if (mDvr != NULL) {
- Result res = mDvr->configure(settings);
- if (res == Result::SUCCESS) {
- MQDescriptorSync<uint8_t> dvrMQDesc;
- res = getQueueDesc(dvrMQDesc);
- if (res == Result::SUCCESS) {
- AidlMQDesc aidlMQDesc;
- unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
- dvrMQDesc, &aidlMQDesc);
- mDvrMQ = new (nothrow) AidlMessageQueue(aidlMQDesc);
- EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrMQEventFlag);
- }
- }
- return res;
- }
-
return Result::INVALID_STATE;
}
Result DvrClient::attachFilter(sp<FilterClient> filterClient) {
- if (mTunerDvr != NULL) {
- Status s = mTunerDvr->attachFilter(filterClient->getAidlFilter());
- return ClientHelper::getServiceSpecificErrorCode(s);
+ if (filterClient == nullptr) {
+ return Result::INVALID_ARGUMENT;
}
- if (mDvr != NULL) {
- sp<IFilter> hidlFilter = filterClient->getHalFilter();
- if (hidlFilter == NULL) {
- return Result::INVALID_ARGUMENT;
- }
- return mDvr->attachFilter(hidlFilter);
+ if (mTunerDvr != nullptr) {
+ Status s = mTunerDvr->attachFilter(filterClient->getAidlFilter());
+ return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result DvrClient::detachFilter(sp<FilterClient> filterClient) {
- if (mTunerDvr != NULL) {
- Status s = mTunerDvr->detachFilter(filterClient->getAidlFilter());
- return ClientHelper::getServiceSpecificErrorCode(s);
+ if (filterClient == nullptr) {
+ return Result::INVALID_ARGUMENT;
}
- if (mDvr != NULL) {
- sp<IFilter> hidlFilter = filterClient->getHalFilter();
- if (hidlFilter == NULL) {
- return Result::INVALID_ARGUMENT;
- }
- return mDvr->detachFilter(hidlFilter);
+ if (mTunerDvr != nullptr) {
+ Status s = mTunerDvr->detachFilter(filterClient->getAidlFilter());
+ return ClientHelper::getServiceSpecificErrorCode(s);
}
return Result::INVALID_STATE;
}
Result DvrClient::start() {
- if (mTunerDvr != NULL) {
+ if (mTunerDvr != nullptr) {
Status s = mTunerDvr->start();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDvr != NULL) {
- return mDvr->start();
- }
-
return Result::INVALID_STATE;
}
Result DvrClient::stop() {
- if (mTunerDvr != NULL) {
+ if (mTunerDvr != nullptr) {
Status s = mTunerDvr->stop();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDvr != NULL) {
- return mDvr->stop();
- }
-
return Result::INVALID_STATE;
}
Result DvrClient::flush() {
- if (mTunerDvr != NULL) {
+ if (mTunerDvr != nullptr) {
Status s = mTunerDvr->flush();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDvr != NULL) {
- return mDvr->flush();
- }
-
return Result::INVALID_STATE;
}
Result DvrClient::close() {
- if (mDvrMQEventFlag != NULL) {
+ if (mDvrMQEventFlag != nullptr) {
EventFlag::deleteEventFlag(&mDvrMQEventFlag);
}
- mDvrMQ = NULL;
+ mDvrMQ = nullptr;
- if (mTunerDvr != NULL) {
+ if (mTunerDvr != nullptr) {
Status s = mTunerDvr->close();
- mTunerDvr = NULL;
+ mTunerDvr = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mDvr != NULL) {
- Result res = mDvr->close();
- mDvr = NULL;
- return res;
- }
-
return Result::INVALID_STATE;
}
-/////////////// IDvrCallback ///////////////////////
-
-HidlDvrCallback::HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback)
- : mDvrClientCallback(dvrClientCallback) {}
-
-Return<void> HidlDvrCallback::onRecordStatus(const RecordStatus status) {
- if (mDvrClientCallback != NULL) {
- mDvrClientCallback->onRecordStatus(status);
- }
- return Void();
-}
-
-Return<void> HidlDvrCallback::onPlaybackStatus(const PlaybackStatus status) {
- if (mDvrClientCallback != NULL) {
- mDvrClientCallback->onPlaybackStatus(status);
- }
- return Void();
-}
-
/////////////// TunerDvrCallback ///////////////////////
-
TunerDvrCallback::TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback)
: mDvrClientCallback(dvrClientCallback) {}
-Status TunerDvrCallback::onRecordStatus(int status) {
- if (mDvrClientCallback != NULL) {
- mDvrClientCallback->onRecordStatus(static_cast<RecordStatus>(status));
+Status TunerDvrCallback::onRecordStatus(RecordStatus status) {
+ if (mDvrClientCallback != nullptr) {
+ mDvrClientCallback->onRecordStatus(status);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-Status TunerDvrCallback::onPlaybackStatus(int status) {
- if (mDvrClientCallback != NULL) {
- mDvrClientCallback->onPlaybackStatus(static_cast<PlaybackStatus>(status));
+Status TunerDvrCallback::onPlaybackStatus(PlaybackStatus status) {
+ if (mDvrClientCallback != nullptr) {
+ mDvrClientCallback->onPlaybackStatus(status);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-/////////////// DvrClient Helper Methods ///////////////////////
-
-Result DvrClient::getQueueDesc(MQDesc& dvrMQDesc) {
- if (mDvr != NULL) {
- Result res = Result::UNKNOWN_ERROR;
- mDvr->getQueueDesc([&](Result r, const MQDesc& desc) {
- dvrMQDesc = desc;
- res = r;
- });
- return res;
- }
-
- return Result::INVALID_STATE;
-}
-
-TunerDvrSettings DvrClient::getAidlDvrSettingsFromHidl(DvrSettings settings) {
- TunerDvrSettings s;
- switch (settings.getDiscriminator()) {
- case DvrSettings::hidl_discriminator::record: {
- s.statusMask = static_cast<int>(settings.record().statusMask);
- s.lowThreshold = static_cast<int>(settings.record().lowThreshold);
- s.highThreshold = static_cast<int>(settings.record().highThreshold);
- s.dataFormat = static_cast<int>(settings.record().dataFormat);
- s.packetSize = static_cast<int>(settings.record().packetSize);
- return s;
- }
- case DvrSettings::hidl_discriminator::playback: {
- s.statusMask = static_cast<int>(settings.playback().statusMask);
- s.lowThreshold = static_cast<int>(settings.playback().lowThreshold);
- s.highThreshold = static_cast<int>(settings.playback().highThreshold);
- s.dataFormat = static_cast<int>(settings.playback().dataFormat);
- s.packetSize = static_cast<int>(settings.playback().packetSize);
- return s;
- }
- default:
- break;
- }
- return s;
-}
} // namespace android
diff --git a/media/jni/tuner/DvrClient.h b/media/jni/tuner/DvrClient.h
index 252554e7fc9e..9080c7288f76 100644
--- a/media/jni/tuner/DvrClient.h
+++ b/media/jni/tuner/DvrClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,36 +17,29 @@
#ifndef _ANDROID_MEDIA_TV_DVR_CLIENT_H_
#define _ANDROID_MEDIA_TV_DVR_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/DvrSettings.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidl/android/media/tv/tuner/BnTunerDvrCallback.h>
#include <aidl/android/media/tv/tuner/ITunerDvr.h>
-#include <android/hardware/tv/tuner/1.0/IDvr.h>
-#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
#include <fmq/AidlMessageQueue.h>
-#include <fmq/MessageQueue.h>
#include "DvrClientCallback.h"
#include "FilterClient.h"
using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::tv::tuner::DvrSettings;
+using ::aidl::android::hardware::tv::tuner::PlaybackStatus;
+using ::aidl::android::hardware::tv::tuner::RecordStatus;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tuner::BnTunerDvrCallback;
using ::aidl::android::media::tv::tuner::ITunerDvr;
-using ::aidl::android::media::tv::tuner::TunerDvrSettings;
-
-using ::android::hardware::EventFlag;
-using ::android::hardware::MQDescriptorSync;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::tv::tuner::V1_0::DvrSettings;
-using ::android::hardware::tv::tuner::V1_0::IDvr;
-using ::android::hardware::tv::tuner::V1_0::IDvrCallback;
using namespace std;
namespace android {
-using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using MQDesc = MQDescriptorSync<uint8_t>;
using AidlMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
@@ -55,19 +48,8 @@ class TunerDvrCallback : public BnTunerDvrCallback {
public:
TunerDvrCallback(sp<DvrClientCallback> dvrClientCallback);
- Status onRecordStatus(int status);
- Status onPlaybackStatus(int status);
-
-private:
- sp<DvrClientCallback> mDvrClientCallback;
-};
-
-struct HidlDvrCallback : public IDvrCallback {
-
-public:
- HidlDvrCallback(sp<DvrClientCallback> dvrClientCallback);
- virtual Return<void> onRecordStatus(const RecordStatus status);
- virtual Return<void> onPlaybackStatus(const PlaybackStatus status);
+ Status onRecordStatus(RecordStatus status);
+ Status onPlaybackStatus(PlaybackStatus status);
private:
sp<DvrClientCallback> mDvrClientCallback;
@@ -79,33 +61,30 @@ public:
DvrClient(shared_ptr<ITunerDvr> tunerDvr);
~DvrClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlDvr(sp<IDvr> dvr);
-
/**
* Set the DVR file descriptor.
*/
- void setFd(int fd);
+ void setFd(int32_t fd);
/**
* Read data from file with given size. Return the actual read size.
*/
- long readFromFile(long size);
+ int64_t readFromFile(int64_t size);
/**
* Read data from the given buffer with given size. Return the actual read size.
*/
- long readFromBuffer(int8_t* buffer, long size);
+ int64_t readFromBuffer(int8_t* buffer, int64_t size);
/**
* Write data to file with given size. Return the actual write size.
*/
- long writeToFile(long size);
+ int64_t writeToFile(int64_t size);
/**
* Write data to the given buffer with given size. Return the actual write size.
*/
- long writeToBuffer(int8_t* buffer, long size);
+ int64_t writeToBuffer(int8_t* buffer, int64_t size);
/**
* Configure the DVR.
@@ -143,26 +122,16 @@ public:
Result close();
private:
- Result getQueueDesc(MQDesc& dvrMQDesc);
- TunerDvrSettings getAidlDvrSettingsFromHidl(DvrSettings settings);
-
/**
* An AIDL Tuner Dvr Singleton assigned at the first time the Tuner Client
* opens a dvr. Default null when dvr is not opened.
*/
shared_ptr<ITunerDvr> mTunerDvr;
- /**
- * A Dvr HAL interface that is ready before migrating to the TunerDvr.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<IDvr> mDvr;
-
AidlMQ* mDvrMQ;
EventFlag* mDvrMQEventFlag;
string mFilePath;
- int mFd;
+ int32_t mFd;
};
} // namespace android
diff --git a/media/jni/tuner/DvrClientCallback.h b/media/jni/tuner/DvrClientCallback.h
index 66844249cc05..a75f199961a7 100644
--- a/media/jni/tuner/DvrClientCallback.h
+++ b/media/jni/tuner/DvrClientCallback.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,12 @@
#ifndef _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
#define _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
-using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
-using ::android::hardware::tv::tuner::V1_0::RecordStatus;
+#include <aidl/android/hardware/tv/tuner/PlaybackStatus.h>
+#include <aidl/android/hardware/tv/tuner/RecordStatus.h>
+#include <utils/RefBase.h>
+
+using ::aidl::android::hardware::tv::tuner::PlaybackStatus;
+using ::aidl::android::hardware::tv::tuner::RecordStatus;
using namespace std;
@@ -30,4 +34,4 @@ struct DvrClientCallback : public RefBase {
};
} // namespace android
-#endif // _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_ \ No newline at end of file
+#endif // _ANDROID_MEDIA_TV_DVR_CLIENT_CALLBACK_H_
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index 324c09a94b63..eea27ea34cb3 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,65 +16,43 @@
#define LOG_TAG "FilterClient"
+#include "FilterClient.h"
+
+#include <aidl/android/hardware/tv/tuner/DemuxFilterMainType.h>
+#include <aidl/android/hardware/tv/tuner/DemuxQueueNotifyBits.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
-#include <fmq/ConvertMQDescriptors.h>
#include <utils/Log.h>
-#include "FilterClient.h"
-
-using ::aidl::android::media::tv::tuner::TunerDemuxIpAddressSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterAlpConfiguration;
-using ::aidl::android::media::tv::tuner::TunerFilterIpConfiguration;
-using ::aidl::android::media::tv::tuner::TunerFilterMmtpConfiguration;
-using ::aidl::android::media::tv::tuner::TunerFilterMonitorEvent;
-using ::aidl::android::media::tv::tuner::TunerFilterScIndexMask;
-using ::aidl::android::media::tv::tuner::TunerFilterSectionBits;
-using ::aidl::android::media::tv::tuner::TunerFilterSectionCondition;
-using ::aidl::android::media::tv::tuner::TunerFilterSectionTableInfo;
-using ::aidl::android::media::tv::tuner::TunerFilterSharedHandleInfo;
-using ::aidl::android::media::tv::tuner::TunerFilterTlvConfiguration;
-using ::aidl::android::media::tv::tuner::TunerFilterTsConfiguration;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
-using ::android::hardware::tv::tuner::V1_0::DemuxStreamId;
-using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
-using ::android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEvent;
-using ::android::hardware::tv::tuner::V1_1::ScramblingStatus;
+using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterMainType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSubType;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxMmtpFilterType;
+using ::aidl::android::hardware::tv::tuner::DemuxQueueNotifyBits;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterSettingsFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxTsFilterType;
+using ::aidl::android::hardware::tv::tuner::ScramblingStatus;
namespace android {
-
/////////////// FilterClient ///////////////////////
-
FilterClient::FilterClient(DemuxFilterType type, shared_ptr<ITunerFilter> tunerFilter) {
mTunerFilter = tunerFilter;
- mAvSharedHandle = NULL;
+ mAvSharedHandle = nullptr;
checkIsMediaFilter(type);
}
FilterClient::~FilterClient() {
- mTunerFilter = NULL;
- mFilter = NULL;
- mFilter_1_1 = NULL;
- mAvSharedHandle = NULL;
+ mTunerFilter = nullptr;
+ mAvSharedHandle = nullptr;
mAvSharedMemSize = 0;
mIsMediaFilter = false;
mIsPassthroughFilter = false;
- mFilterMQ = NULL;
- mFilterMQEventFlag = NULL;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void FilterClient::setHidlFilter(sp<IFilter> filter) {
- mFilter = filter;
- mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter);
+ mFilterMQ = nullptr;
+ mFilterMQEventFlag = nullptr;
}
-int FilterClient::read(int8_t* buffer, int size) {
+int64_t FilterClient::read(int8_t* buffer, int64_t size) {
Result res = getFilterMq();
if (res != Result::SUCCESS) {
return -1;
@@ -85,8 +63,8 @@ int FilterClient::read(int8_t* buffer, int size) {
SharedHandleInfo FilterClient::getAvSharedHandleInfo() {
handleAvShareMemory();
SharedHandleInfo info{
- .sharedHandle = (mIsMediaFilter && !mIsPassthroughFilter) ? mAvSharedHandle : NULL,
- .size = mAvSharedMemSize,
+ .sharedHandle = (mIsMediaFilter && !mIsPassthroughFilter) ? mAvSharedHandle : nullptr,
+ .size = mAvSharedMemSize,
};
return info;
@@ -96,8 +74,8 @@ Result FilterClient::configure(DemuxFilterSettings configure) {
Result res;
checkIsPassthroughFilter(configure);
- if (mTunerFilter != NULL) {
- Status s = mTunerFilter->configure(getAidlFilterSettings(configure));
+ if (mTunerFilter != nullptr) {
+ Status s = mTunerFilter->configure(configure);
res = ClientHelper::getServiceSpecificErrorCode(s);
if (res == Result::SUCCESS) {
getAvSharedHandleInfo();
@@ -105,171 +83,96 @@ Result FilterClient::configure(DemuxFilterSettings configure) {
return res;
}
- if (mFilter != NULL) {
- res = mFilter->configure(configure);
- if (res == Result::SUCCESS) {
- getAvSharedHandleInfo();
- }
- return res;
- }
-
return Result::INVALID_STATE;
}
-Result FilterClient::configureMonitorEvent(int monitorEventType) {
- if (mTunerFilter != NULL) {
+Result FilterClient::configureMonitorEvent(int32_t monitorEventType) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureMonitorEvent(monitorEventType);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter_1_1 != NULL) {
- return mFilter_1_1->configureMonitorEvent(monitorEventType);
- }
-
return Result::INVALID_STATE;
}
-Result FilterClient::configureIpFilterContextId(int cid) {
- if (mTunerFilter != NULL) {
+Result FilterClient::configureIpFilterContextId(int32_t cid) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureIpFilterContextId(cid);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter_1_1 != NULL) {
- return mFilter_1_1->configureIpCid(cid);
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::configureAvStreamType(AvStreamType avStreamType) {
- if (mTunerFilter != NULL) {
- int type;
- switch (avStreamType.getDiscriminator()) {
- case AvStreamType::hidl_discriminator::audio:
- type = (int)avStreamType.audio();
- break;
- case AvStreamType::hidl_discriminator::video:
- type = (int)avStreamType.video();
- break;
- }
- Status s = mTunerFilter->configureAvStreamType(type);
+ if (mTunerFilter != nullptr) {
+ Status s = mTunerFilter->configureAvStreamType(avStreamType);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter_1_1 != NULL) {
- return mFilter_1_1->configureAvStreamType(avStreamType);
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::start() {
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->start();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- return mFilter->start();
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::stop() {
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->stop();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- return mFilter->stop();
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::flush() {
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->flush();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- return mFilter->flush();
- }
-
return Result::INVALID_STATE;
}
-Result FilterClient::getId(uint32_t& id) {
- if (mTunerFilter != NULL) {
- int32_t id32Bit;
- Status s = mTunerFilter->getId(&id32Bit);
- id = static_cast<uint32_t>(id32Bit);
+Result FilterClient::getId(int32_t& id) {
+ if (mTunerFilter != nullptr) {
+ Status s = mTunerFilter->getId(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- Result res;
- mFilter->getId([&](Result r, uint32_t filterId) {
- res = r;
- id = filterId;
- });
- return res;
- }
-
return Result::INVALID_STATE;
}
-Result FilterClient::getId64Bit(uint64_t& id) {
- if (mTunerFilter != NULL) {
- int64_t id64Bit;
- Status s = mTunerFilter->getId64Bit(&id64Bit);
- id = static_cast<uint64_t>(id64Bit);
+Result FilterClient::getId64Bit(int64_t& id) {
+ if (mTunerFilter != nullptr) {
+ Status s = mTunerFilter->getId64Bit(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter_1_1 != NULL) {
- Result res;
- mFilter_1_1->getId64Bit([&](Result r, uint64_t filterId) {
- res = r;
- id = filterId;
- });
- return res;
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::releaseAvHandle(native_handle_t* handle, uint64_t avDataId) {
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->releaseAvHandle(makeToAidl(handle), avDataId);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- return mFilter->releaseAvHandle(hidl_handle(handle), avDataId);
- }
-
return Result::INVALID_STATE;
}
Result FilterClient::setDataSource(sp<FilterClient> filterClient){
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->setDataSource(filterClient->getAidlFilter());
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- sp<IFilter> sourceFilter = filterClient->getHalFilter();
- if (sourceFilter == NULL) {
- return Result::INVALID_ARGUMENT;
- }
- return mFilter->setDataSource(sourceFilter);
- }
-
return Result::INVALID_STATE;
}
@@ -277,648 +180,38 @@ Result FilterClient::close() {
if (mFilterMQEventFlag) {
EventFlag::deleteEventFlag(&mFilterMQEventFlag);
}
- mFilterMQEventFlag = NULL;
- mFilterMQ = NULL;
+ mFilterMQEventFlag = nullptr;
+ mFilterMQ = nullptr;
- if (mTunerFilter != NULL) {
+ if (mTunerFilter != nullptr) {
Status s = mTunerFilter->close();
closeAvSharedMemory();
- mTunerFilter = NULL;
+ mTunerFilter = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFilter != NULL) {
- Result res = mFilter->close();
- mFilter = NULL;
- mFilter_1_1 = NULL;
- closeAvSharedMemory();
- return res;
- }
-
return Result::INVALID_STATE;
}
-/////////////// IFilterCallback ///////////////////////
-
-HidlFilterCallback::HidlFilterCallback(sp<FilterClientCallback> filterClientCallback)
- : mFilterClientCallback(filterClientCallback) {}
-
-Return<void> HidlFilterCallback::onFilterStatus(const DemuxFilterStatus status) {
- if (mFilterClientCallback != NULL) {
- mFilterClientCallback->onFilterStatus(status);
- }
- return Void();
-}
-
-Return<void> HidlFilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
- if (mFilterClientCallback != NULL) {
- mFilterClientCallback->onFilterEvent(filterEvent);
- }
- return Void();
-}
-
-Return<void> HidlFilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
- const DemuxFilterEventExt& filterEventExt) {
- if (mFilterClientCallback != NULL) {
- mFilterClientCallback->onFilterEvent_1_1(filterEvent, filterEventExt);
- }
- return Void();
-}
-
/////////////// TunerFilterCallback ///////////////////////
TunerFilterCallback::TunerFilterCallback(sp<FilterClientCallback> filterClientCallback)
: mFilterClientCallback(filterClientCallback) {}
-Status TunerFilterCallback::onFilterStatus(int status) {
- if (mFilterClientCallback != NULL) {
- mFilterClientCallback->onFilterStatus(static_cast<DemuxFilterStatus>(status));
+Status TunerFilterCallback::onFilterStatus(DemuxFilterStatus status) {
+ if (mFilterClientCallback != nullptr) {
+ mFilterClientCallback->onFilterStatus(status);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-Status TunerFilterCallback::onFilterEvent(const vector<TunerFilterEvent>& filterEvents) {
- if (mFilterClientCallback == NULL) {
- return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
- }
-
- if (filterEvents.size() == 0) {
- return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_ARGUMENT));
- }
-
- DemuxFilterEvent event;
- DemuxFilterEventExt eventExt;
- getHidlFilterEvent(filterEvents, event, eventExt);
- if (eventExt.events.size() > 0) {
- mFilterClientCallback->onFilterEvent_1_1(event, eventExt);
- } else {
- mFilterClientCallback->onFilterEvent(event);
- }
-
- return Status::ok();
-}
-
-/////////////// FilterClient Helper Methods ///////////////////////
-
-TunerFilterConfiguration FilterClient::getAidlFilterSettings(DemuxFilterSettings configure) {
- TunerFilterConfiguration config;
- switch (configure.getDiscriminator()) {
- case DemuxFilterSettings::hidl_discriminator::ts:
- return getAidlTsSettings(configure.ts());
- case DemuxFilterSettings::hidl_discriminator::mmtp:
- return getAidlMmtpSettings(configure.mmtp());
- case DemuxFilterSettings::hidl_discriminator::ip:
- return getAidlIpSettings(configure.ip());
- case DemuxFilterSettings::hidl_discriminator::tlv:
- return getAidlTlvSettings(configure.tlv());
- case DemuxFilterSettings::hidl_discriminator::alp:
- return getAidlAlpSettings(configure.alp());
- default:
- break;
- }
- ALOGE("Wrong DemuxFilterSettings union.");
- return config;
-}
-
-TunerFilterConfiguration FilterClient::getAidlTsSettings(DemuxTsFilterSettings ts) {
- TunerFilterConfiguration config;
- TunerFilterSettings filterSettings;
- switch (ts.filterSettings.getDiscriminator()) {
- case DemuxTsFilterSettings::FilterSettings::hidl_discriminator::av: {
- filterSettings.set<TunerFilterSettings::av>(
- getAidlAvSettings(ts.filterSettings.av()));
- break;
- }
- case DemuxTsFilterSettings::FilterSettings::hidl_discriminator::section: {
- filterSettings.set<TunerFilterSettings::section>(
- getAidlSectionSettings(ts.filterSettings.section()));
- break;
- }
- case DemuxTsFilterSettings::FilterSettings::hidl_discriminator::pesData: {
- filterSettings.set<TunerFilterSettings::pesData>(
- getAidlPesDataSettings(ts.filterSettings.pesData()));
- break;
- }
- case DemuxTsFilterSettings::FilterSettings::hidl_discriminator::record: {
- filterSettings.set<TunerFilterSettings::record>(
- getAidlRecordSettings(ts.filterSettings.record()));
- break;
- }
- default:
- filterSettings.set<TunerFilterSettings::nothing>(true);
- break;
- }
-
- TunerFilterTsConfiguration aidlTs{
- .tpid = static_cast<char16_t>(ts.tpid),
- .filterSettings = filterSettings,
- };
- config.set<TunerFilterConfiguration::ts>(aidlTs);
-
- return config;
-}
-
-TunerFilterConfiguration FilterClient::getAidlMmtpSettings(DemuxMmtpFilterSettings mmtp) {
- TunerFilterConfiguration config;
- TunerFilterSettings filterSettings;
- switch (mmtp.filterSettings.getDiscriminator()) {
- case DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::av: {
- filterSettings.set<TunerFilterSettings::av>(
- getAidlAvSettings(mmtp.filterSettings.av()));
- break;
- }
- case DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::section: {
- filterSettings.set<TunerFilterSettings::section>(
- getAidlSectionSettings(mmtp.filterSettings.section()));
- break;
- }
- case DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::pesData: {
- filterSettings.set<TunerFilterSettings::pesData>(
- getAidlPesDataSettings(mmtp.filterSettings.pesData()));
- break;
- }
- case DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::record: {
- filterSettings.set<TunerFilterSettings::record>(
- getAidlRecordSettings(mmtp.filterSettings.record()));
- break;
- }
- case DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::download: {
- filterSettings.set<TunerFilterSettings::download>(
- getAidlDownloadSettings(mmtp.filterSettings.download()));
- break;
- }
- default:
- filterSettings.set<TunerFilterSettings::nothing>(true);
- break;
- }
-
- TunerFilterMmtpConfiguration aidlMmtp{
- .mmtpPid = static_cast<char16_t>(mmtp.mmtpPid),
- .filterSettings = filterSettings,
- };
- config.set<TunerFilterConfiguration::mmtp>(aidlMmtp);
-
- return config;
-}
-
-TunerFilterConfiguration FilterClient::getAidlIpSettings(DemuxIpFilterSettings ip) {
- TunerFilterConfiguration config;
- TunerFilterSettings filterSettings;
- switch (ip.filterSettings.getDiscriminator()) {
- case DemuxIpFilterSettings::FilterSettings::hidl_discriminator::section: {
- filterSettings.set<TunerFilterSettings::section>(
- getAidlSectionSettings(ip.filterSettings.section()));
- break;
- }
- case DemuxIpFilterSettings::FilterSettings::hidl_discriminator::bPassthrough: {
- filterSettings.set<TunerFilterSettings::isPassthrough>(
- ip.filterSettings.bPassthrough());
- break;
- }
- default:
- filterSettings.set<TunerFilterSettings::nothing>(true);
- break;
- }
-
- TunerDemuxIpAddressSettings ipAddr{
- .srcPort = static_cast<char16_t>(ip.ipAddr.srcPort),
- .dstPort = static_cast<char16_t>(ip.ipAddr.dstPort),
- };
- getAidlIpAddress(ip.ipAddr, ipAddr.srcIpAddress, ipAddr.dstIpAddress);
-
- TunerFilterIpConfiguration aidlIp{
- .ipAddr = ipAddr,
- .filterSettings = filterSettings,
- };
- config.set<TunerFilterConfiguration::ip>(aidlIp);
-
- return config;
-}
-
-void FilterClient::getAidlIpAddress(DemuxIpAddress ipAddr,
- TunerDemuxIpAddress& srcIpAddress, TunerDemuxIpAddress& dstIpAddress) {
- switch (ipAddr.srcIpAddress.getDiscriminator()) {
- case DemuxIpAddress::SrcIpAddress::hidl_discriminator::v4: {
- int size = ipAddr.srcIpAddress.v4().size();
- srcIpAddress.isIpV6 = false;
- srcIpAddress.addr.resize(size);
- copy(&ipAddr.srcIpAddress.v4()[0], &ipAddr.srcIpAddress.v4()[size],
- srcIpAddress.addr.begin());
- break;
- }
- case DemuxIpAddress::SrcIpAddress::hidl_discriminator::v6: {
- int size = ipAddr.srcIpAddress.v6().size();
- srcIpAddress.isIpV6 = true;
- srcIpAddress.addr.resize(size);
- copy(&ipAddr.srcIpAddress.v6()[0], &ipAddr.srcIpAddress.v6()[size],
- srcIpAddress.addr.begin());
- break;
- }
- }
- switch (ipAddr.dstIpAddress.getDiscriminator()) {
- case DemuxIpAddress::DstIpAddress::hidl_discriminator::v4: {
- int size = ipAddr.dstIpAddress.v4().size();
- dstIpAddress.isIpV6 = false;
- dstIpAddress.addr.resize(size);
- copy(&ipAddr.dstIpAddress.v4()[0], &ipAddr.dstIpAddress.v4()[size],
- dstIpAddress.addr.begin());
- break;
- }
- case DemuxIpAddress::DstIpAddress::hidl_discriminator::v6: {
- int size = ipAddr.dstIpAddress.v6().size();
- dstIpAddress.isIpV6 = true;
- dstIpAddress.addr.resize(size);
- copy(&ipAddr.dstIpAddress.v6()[0], &ipAddr.dstIpAddress.v6()[size],
- dstIpAddress.addr.begin());
- break;
- }
- }
-}
-
-TunerFilterConfiguration FilterClient::getAidlTlvSettings(DemuxTlvFilterSettings tlv) {
- TunerFilterConfiguration config;
- TunerFilterSettings filterSettings;
- switch (tlv.filterSettings.getDiscriminator()) {
- case DemuxTlvFilterSettings::FilterSettings::hidl_discriminator::section: {
- filterSettings.set<TunerFilterSettings::section>(
- getAidlSectionSettings(tlv.filterSettings.section()));
- break;
- }
- case DemuxTlvFilterSettings::FilterSettings::hidl_discriminator::bPassthrough: {
- filterSettings.set<TunerFilterSettings::isPassthrough>(
- tlv.filterSettings.bPassthrough());
- break;
- }
- default:
- filterSettings.set<TunerFilterSettings::nothing>(true);
- break;
- }
-
- TunerFilterTlvConfiguration aidlTlv{
- .packetType = static_cast<int8_t>(tlv.packetType),
- .isCompressedIpPacket = tlv.isCompressedIpPacket,
- .filterSettings = filterSettings,
- };
- config.set<TunerFilterConfiguration::tlv>(aidlTlv);
-
- return config;
-}
-
-TunerFilterConfiguration FilterClient::getAidlAlpSettings(DemuxAlpFilterSettings alp) {
- TunerFilterConfiguration config;
- TunerFilterSettings filterSettings;
- switch (alp.filterSettings.getDiscriminator()) {
- case DemuxAlpFilterSettings::FilterSettings::hidl_discriminator::section: {
- filterSettings.set<TunerFilterSettings::section>(
- getAidlSectionSettings(alp.filterSettings.section()));
- break;
- }
- default:
- filterSettings.set<TunerFilterSettings::nothing>(true);
- break;
- }
-
- TunerFilterAlpConfiguration aidlAlp{
- .packetType = static_cast<int8_t>(alp.packetType),
- .lengthType = static_cast<int8_t>(alp.lengthType),
- .filterSettings = filterSettings,
- };
- config.set<TunerFilterConfiguration::alp>(aidlAlp);
-
- return config;
-}
-
-TunerFilterAvSettings FilterClient::getAidlAvSettings(DemuxFilterAvSettings hidlAv) {
- TunerFilterAvSettings aidlAv{
- .isPassthrough = hidlAv.isPassthrough,
- };
- return aidlAv;
-}
-
-TunerFilterSectionSettings FilterClient::getAidlSectionSettings(
- DemuxFilterSectionSettings hidlSection) {
- TunerFilterSectionSettings aidlSection;
-
- switch (hidlSection.condition.getDiscriminator()) {
- case DemuxFilterSectionSettings::Condition::hidl_discriminator::sectionBits: {
- TunerFilterSectionBits sectionBits;
- auto hidlSectionBits = hidlSection.condition.sectionBits();
- sectionBits.filter.resize(hidlSectionBits.filter.size());
- sectionBits.mask.resize(hidlSectionBits.mask.size());
- sectionBits.mode.resize(hidlSectionBits.mode.size());
- copy(hidlSectionBits.filter.begin(), hidlSectionBits.filter.end(),
- sectionBits.filter.begin());
- copy(hidlSectionBits.mask.begin(), hidlSectionBits.mask.end(),
- sectionBits.mask.begin());
- copy(hidlSectionBits.mode.begin(), hidlSectionBits.mode.end(),
- sectionBits.mode.begin());
- aidlSection.condition.set<TunerFilterSectionCondition::sectionBits>(sectionBits);
- break;
- }
- case DemuxFilterSectionSettings::Condition::hidl_discriminator::tableInfo: {
- TunerFilterSectionTableInfo tableInfo{
- .tableId = static_cast<char16_t>(hidlSection.condition.tableInfo().tableId),
- .version = static_cast<char16_t>(hidlSection.condition.tableInfo().version),
- };
- aidlSection.condition.set<TunerFilterSectionCondition::tableInfo>(tableInfo);
- break;
- }
- }
- aidlSection.isCheckCrc = hidlSection.isCheckCrc;
- aidlSection.isRepeat = hidlSection.isRepeat;
- aidlSection.isRaw = hidlSection.isRaw;
- return aidlSection;
-}
-
-TunerFilterPesDataSettings FilterClient::getAidlPesDataSettings(
- DemuxFilterPesDataSettings hidlPesData) {
- TunerFilterPesDataSettings aidlPesData{
- .streamId = static_cast<char16_t>(hidlPesData.streamId),
- .isRaw = hidlPesData.isRaw,
- };
- return aidlPesData;
-}
-
-TunerFilterRecordSettings FilterClient::getAidlRecordSettings(
- DemuxFilterRecordSettings hidlRecord) {
- TunerFilterScIndexMask mask;
- switch (hidlRecord.scIndexMask.getDiscriminator()) {
- case DemuxFilterRecordSettings::ScIndexMask::hidl_discriminator::sc: {
- mask.set<TunerFilterScIndexMask::sc>(hidlRecord.scIndexMask.sc());
- break;
- }
- case DemuxFilterRecordSettings::ScIndexMask::hidl_discriminator::scHevc: {
- mask.set<TunerFilterScIndexMask::scHevc>(hidlRecord.scIndexMask.scHevc());
- break;
- }
- default:
- break;
- }
- TunerFilterRecordSettings aidlRecord{
- .tsIndexMask = static_cast<int32_t>(hidlRecord.tsIndexMask),
- .scIndexType = static_cast<int32_t>(hidlRecord.scIndexType),
- .scIndexMask = mask,
- };
- return aidlRecord;
-}
-
-TunerFilterDownloadSettings FilterClient::getAidlDownloadSettings(
- DemuxFilterDownloadSettings hidlDownload) {
- TunerFilterDownloadSettings aidlDownload{
- .downloadId = static_cast<int32_t>(hidlDownload.downloadId),
- };
- return aidlDownload;
-}
-
-void TunerFilterCallback::getHidlFilterEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt) {
- switch (filterEvents[0].getTag()) {
- case TunerFilterEvent::media: {
- getHidlMediaEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::section: {
- getHidlSectionEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::pes: {
- getHidlPesEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::tsRecord: {
- getHidlTsRecordEvent(filterEvents, event, eventExt);
- break;
- }
- case TunerFilterEvent::mmtpRecord: {
- getHidlMmtpRecordEvent(filterEvents, event, eventExt);
- break;
- }
- case TunerFilterEvent::download: {
- getHidlDownloadEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::ipPayload: {
- getHidlIpPayloadEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::temi: {
- getHidlTemiEvent(filterEvents, event);
- break;
- }
- case TunerFilterEvent::monitor: {
- getHidlMonitorEvent(filterEvents, eventExt);
- break;
- }
- case TunerFilterEvent::startId: {
- getHidlRestartEvent(filterEvents, eventExt);
- break;
- }
- }
-}
-
-void TunerFilterCallback::getHidlMediaEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- hidl_handle handle = hidl_handle(makeFromAidl(filterEvents[i]
- .get<TunerFilterEvent::media>().avMemory));
- event.events[i].media({
- .avMemory = handle,
- .streamId = static_cast<DemuxStreamId>(filterEvents[i]
- .get<TunerFilterEvent::media>().streamId),
- .isPtsPresent = filterEvents[i]
- .get<TunerFilterEvent::media>().isPtsPresent,
- .pts = static_cast<uint64_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().pts),
- .dataLength = static_cast<uint32_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().dataLength),
- .offset = static_cast<uint32_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().offset),
- .isSecureMemory = filterEvents[i]
- .get<TunerFilterEvent::media>().isSecureMemory,
- .avDataId = static_cast<uint64_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().avDataId),
- .mpuSequenceNumber = static_cast<uint32_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().offset),
- .isPesPrivateData = filterEvents[i]
- .get<TunerFilterEvent::media>().isPesPrivateData,
- });
-
- if (filterEvents[i].get<TunerFilterEvent::media>().isAudioExtraMetaData) {
- event.events[i].media().extraMetaData.audio({
- .adFade = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.adFade),
- .adPan = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.adPan),
- .versionTextTag = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.versionTextTag),
- .adGainCenter = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.adGainCenter),
- .adGainFront = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.adGainFront),
- .adGainSurround = static_cast<uint8_t>(filterEvents[i]
- .get<TunerFilterEvent::media>().audio.adGainSurround),
- });
- } else {
- event.events[i].media().extraMetaData.noinit();
- }
- }
-}
-
-void TunerFilterCallback::getHidlSectionEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto section = filterEvents[i].get<TunerFilterEvent::section>();
- event.events[i].section({
- .tableId = static_cast<uint16_t>(section.tableId),
- .version = static_cast<uint16_t>(section.version),
- .sectionNum = static_cast<uint16_t>(section.sectionNum),
- .dataLength = static_cast<uint16_t>(section.dataLength),
- });
- }
-}
-
-void TunerFilterCallback::getHidlPesEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto pes = filterEvents[i].get<TunerFilterEvent::pes>();
- event.events[i].pes({
- .streamId = static_cast<DemuxStreamId>(pes.streamId),
- .dataLength = static_cast<uint16_t>(pes.dataLength),
- .mpuSequenceNumber = static_cast<uint32_t>(pes.mpuSequenceNumber),
- });
- }
-}
-
-void TunerFilterCallback::getHidlTsRecordEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt) {
- event.events.resize(filterEvents.size());
- eventExt.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto ts = filterEvents[i].get<TunerFilterEvent::tsRecord>();
- event.events[i].tsRecord({
- .tsIndexMask = static_cast<uint32_t>(ts.tsIndexMask),
- .byteNumber = static_cast<uint64_t>(ts.byteNumber),
- });
- event.events[i].tsRecord().pid.tPid(static_cast<DemuxTpid>(ts.pid));
-
- switch (ts.scIndexMask.getTag()) {
- case TunerFilterScIndexMask::sc: {
- event.events[i].tsRecord().scIndexMask.sc(
- ts.scIndexMask.get<TunerFilterScIndexMask::sc>());
- break;
- }
- case TunerFilterScIndexMask::scHevc: {
- event.events[i].tsRecord().scIndexMask.scHevc(
- ts.scIndexMask.get<TunerFilterScIndexMask::scHevc>());
- break;
- }
- default:
- break;
- }
-
- if (ts.isExtended) {
- eventExt.events[i].tsRecord({
- .pts = static_cast<uint64_t>(ts.pts),
- .firstMbInSlice = static_cast<uint32_t>(ts.firstMbInSlice),
- });
- } else {
- eventExt.events[i].noinit();
- }
- }
-}
-
-void TunerFilterCallback::getHidlMmtpRecordEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt) {
- event.events.resize(filterEvents.size());
- eventExt.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto mmtp = filterEvents[i].get<TunerFilterEvent::mmtpRecord>();
- event.events[i].mmtpRecord({
- .scHevcIndexMask = static_cast<uint32_t>(mmtp.scHevcIndexMask),
- .byteNumber = static_cast<uint64_t>(mmtp.byteNumber),
- });
-
- if (mmtp.isExtended) {
- eventExt.events[i].mmtpRecord({
- .pts = static_cast<uint64_t>(mmtp.pts),
- .mpuSequenceNumber = static_cast<uint32_t>(mmtp.mpuSequenceNumber),
- .firstMbInSlice = static_cast<uint32_t>(mmtp.firstMbInSlice),
- .tsIndexMask = static_cast<uint32_t>(mmtp.tsIndexMask),
- });
- } else {
- eventExt.events[i].noinit();
- }
- }
-}
-
-void TunerFilterCallback::getHidlDownloadEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto download = filterEvents[i].get<TunerFilterEvent::download>();
- event.events[i].download({
- .itemId = static_cast<uint32_t>(download.itemId),
- .mpuSequenceNumber = static_cast<uint32_t>(download.mpuSequenceNumber),
- .itemFragmentIndex = static_cast<uint32_t>(download.itemFragmentIndex),
- .lastItemFragmentIndex = static_cast<uint32_t>(download.lastItemFragmentIndex),
- .dataLength = static_cast<uint16_t>(download.dataLength),
- });
- }
-}
-
-void TunerFilterCallback::getHidlIpPayloadEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto ip = filterEvents[i].get<TunerFilterEvent::ipPayload>();
- event.events[i].ipPayload({
- .dataLength = static_cast<uint16_t>(ip.dataLength),
- });
- }
-}
-
-void TunerFilterCallback::getHidlTemiEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event) {
- event.events.resize(filterEvents.size());
- for (int i = 0; i < filterEvents.size(); i++) {
- auto temi = filterEvents[i].get<TunerFilterEvent::temi>();
- event.events[i].temi({
- .pts = static_cast<uint64_t>(temi.pts),
- .descrTag = static_cast<uint8_t>(temi.descrTag),
- });
- hidl_vec<uint8_t> descrData(temi.descrData.begin(), temi.descrData.end());
- event.events[i].temi().descrData = descrData;
- }
-}
-
-void TunerFilterCallback::getHidlMonitorEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEventExt& eventExt) {
- auto monitor = filterEvents[0].get<TunerFilterEvent::monitor>();
- eventExt.events.resize(1);
- DemuxFilterMonitorEvent monitorEvent;
- switch (monitor.getTag()) {
- case TunerFilterMonitorEvent::scramblingStatus: {
- monitorEvent.scramblingStatus(static_cast<ScramblingStatus>(monitor.scramblingStatus));
- eventExt.events[0].monitorEvent(monitorEvent);
- break;
- }
- case TunerFilterMonitorEvent::cid: {
- monitorEvent.cid(static_cast<uint32_t>(monitor.cid));
- eventExt.events[0].monitorEvent(monitorEvent);
- break;
- }
+Status TunerFilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& filterEvents) {
+ if (mFilterClientCallback != nullptr) {
+ mFilterClientCallback->onFilterEvent(filterEvents);
+ return Status::ok();
}
-}
-
-void TunerFilterCallback::getHidlRestartEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEventExt& eventExt) {
- uint32_t startId = filterEvents[0].get<TunerFilterEvent::startId>();
- eventExt.events.resize(1);
- eventExt.events[0].startId(static_cast<uint32_t>(startId));
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
Result FilterClient::getFilterMq() {
@@ -931,39 +224,21 @@ Result FilterClient::getFilterMq() {
if (mTunerFilter != NULL) {
Status s = mTunerFilter->getQueueDesc(&aidlMqDesc);
- res = ClientHelper::getServiceSpecificErrorCode(s);
- if (res == Result::SUCCESS) {
+ if (s.isOk()) {
mFilterMQ = new (nothrow) AidlMQ(aidlMqDesc, false/*resetPointer*/);
EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag);
}
- return res;
- }
-
- if (mFilter != NULL) {
- MQDescriptorSync<uint8_t> filterMQDesc;
- mFilter->getQueueDesc(
- [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
- filterMQDesc = desc;
- res = r;
- });
- if (res == Result::SUCCESS) {
- AidlMQDesc aidlMQDesc;
- unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(
- filterMQDesc, &aidlMQDesc);
- mFilterMQ = new (nothrow) AidlMessageQueue(aidlMQDesc, false/*resetPointer*/);
- EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag);
- }
}
return res;
}
-int FilterClient::copyData(int8_t* buffer, int size) {
- if (mFilterMQ == NULL || mFilterMQEventFlag == NULL) {
+int64_t FilterClient::copyData(int8_t* buffer, int64_t size) {
+ if (mFilterMQ == nullptr || mFilterMQEventFlag == nullptr) {
return -1;
}
- int available = mFilterMQ->availableToRead();
+ int64_t available = mFilterMQ->availableToRead();
size = min(size, available);
if (mFilterMQ->read(buffer, size)) {
@@ -977,16 +252,18 @@ int FilterClient::copyData(int8_t* buffer, int size) {
void FilterClient::checkIsMediaFilter(DemuxFilterType type) {
if (type.mainType == DemuxFilterMainType::MMTP) {
- if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
- type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+ if (type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+ DemuxMmtpFilterType::AUDIO ||
+ type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>() ==
+ DemuxMmtpFilterType::VIDEO) {
mIsMediaFilter = true;
return;
}
}
if (type.mainType == DemuxFilterMainType::TS) {
- if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
- type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+ if (type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() == DemuxTsFilterType::AUDIO ||
+ type.subType.get<DemuxFilterSubType::Tag::tsFilterType>() == DemuxTsFilterType::VIDEO) {
mIsMediaFilter = true;
return;
}
@@ -1001,15 +278,19 @@ void FilterClient::checkIsPassthroughFilter(DemuxFilterSettings configure) {
return;
}
- if (configure.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts) {
- if (configure.ts().filterSettings.av().isPassthrough) {
+ if (configure.getTag() == DemuxFilterSettings::Tag::ts) {
+ if (configure.get<DemuxFilterSettings::Tag::ts>()
+ .filterSettings.get<DemuxTsFilterSettingsFilterSettings::Tag::av>()
+ .isPassthrough) {
mIsPassthroughFilter = true;
return;
}
}
- if (configure.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp) {
- if (configure.mmtp().filterSettings.av().isPassthrough) {
+ if (configure.getTag() == DemuxFilterSettings::Tag::mmtp) {
+ if (configure.get<DemuxFilterSettings::Tag::mmtp>()
+ .filterSettings.get<DemuxMmtpFilterSettingsFilterSettings::Tag::av>()
+ .isPassthrough) {
mIsPassthroughFilter = true;
return;
}
@@ -1019,37 +300,28 @@ void FilterClient::checkIsPassthroughFilter(DemuxFilterSettings configure) {
}
void FilterClient::handleAvShareMemory() {
- if (mAvSharedHandle != NULL) {
+ if (mAvSharedHandle != nullptr) {
return;
}
- if (mTunerFilter != NULL && mIsMediaFilter && !mIsPassthroughFilter) {
- TunerFilterSharedHandleInfo aidlHandleInfo;
- Status s = mTunerFilter->getAvSharedHandleInfo(&aidlHandleInfo);
- if (ClientHelper::getServiceSpecificErrorCode(s) == Result::SUCCESS) {
- mAvSharedHandle = native_handle_clone(makeFromAidl(aidlHandleInfo.handle));
- mAvSharedMemSize = aidlHandleInfo.size;
+ if (mTunerFilter != nullptr && mIsMediaFilter && !mIsPassthroughFilter) {
+ int64_t size;
+ NativeHandle avMemory;
+ Status s = mTunerFilter->getAvSharedHandle(&avMemory, &size);
+ if (s.isOk()) {
+ mAvSharedHandle = native_handle_clone(makeFromAidl(avMemory));
+ mAvSharedMemSize = size;
}
- return;
- }
-
- if (mFilter_1_1 != NULL && mIsMediaFilter && !mIsPassthroughFilter) {
- mFilter_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
- if (r == Result::SUCCESS) {
- mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
- mAvSharedMemSize = avMemSize;
- }
- });
}
}
void FilterClient::closeAvSharedMemory() {
- if (mAvSharedHandle == NULL) {
+ if (mAvSharedHandle == nullptr) {
mAvSharedMemSize = 0;
return;
}
native_handle_close(mAvSharedHandle);
native_handle_delete(mAvSharedHandle);
mAvSharedMemSize = 0;
- mAvSharedHandle = NULL;
+ mAvSharedHandle = nullptr;
}
} // namespace android
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index 5d78bfdb2349..136d1f58b205 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,64 +17,30 @@
#ifndef _ANDROID_MEDIA_TV_FILTER_CLIENT_H_
#define _ANDROID_MEDIA_TV_FILTER_CLIENT_H_
-#include <aidl/android/media/tv/tuner/ITunerFilter.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterType.h>
#include <aidl/android/media/tv/tuner/BnTunerFilterCallback.h>
-#include <aidl/android/media/tv/tuner/TunerFilterEvent.h>
-#include <aidl/android/media/tv/tuner/TunerFilterSettings.h>
-#include <aidlcommonsupport/NativeHandle.h>
-#include <android/hardware/tv/tuner/1.1/IFilter.h>
-#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
+#include <aidl/android/media/tv/tuner/ITunerFilter.h>
#include <fmq/AidlMessageQueue.h>
-#include <fmq/MessageQueue.h>
#include "ClientHelper.h"
#include "FilterClientCallback.h"
using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::tv::tuner::AvStreamType;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterSettings;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
using ::aidl::android::media::tv::tuner::BnTunerFilterCallback;
using ::aidl::android::media::tv::tuner::ITunerFilter;
-using ::aidl::android::media::tv::tuner::TunerDemuxIpAddress;
-using ::aidl::android::media::tv::tuner::TunerFilterAvSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterConfiguration;
-using ::aidl::android::media::tv::tuner::TunerFilterDownloadSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterEvent;
-using ::aidl::android::media::tv::tuner::TunerFilterPesDataSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterRecordSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterSectionSettings;
-using ::aidl::android::media::tv::tuner::TunerFilterSettings;
-
using ::android::hardware::EventFlag;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::MQDescriptorSync;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
-using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
-using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
-using ::android::hardware::tv::tuner::V1_0::IFilter;
-using ::android::hardware::tv::tuner::V1_0::Result;
-using ::android::hardware::tv::tuner::V1_1::AvStreamType;
-using ::android::hardware::tv::tuner::V1_1::IFilterCallback;
using namespace std;
namespace android {
-using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using MQDesc = MQDescriptorSync<uint8_t>;
using AidlMQ = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
using AidlMQDesc = MQDescriptor<int8_t, SynchronizedReadWrite>;
@@ -84,47 +50,10 @@ struct SharedHandleInfo {
};
class TunerFilterCallback : public BnTunerFilterCallback {
-
public:
TunerFilterCallback(sp<FilterClientCallback> filterClientCallback);
- Status onFilterStatus(int status);
- Status onFilterEvent(const vector<TunerFilterEvent>& filterEvents);
-
-private:
- void getHidlFilterEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt);
- void getHidlMediaEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlSectionEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlPesEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlTsRecordEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt);
- void getHidlMmtpRecordEvent(const vector<TunerFilterEvent>& filterEvents,
- DemuxFilterEvent& event, DemuxFilterEventExt& eventExt);
- void getHidlDownloadEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlIpPayloadEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlTemiEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEvent& event);
- void getHidlMonitorEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEventExt& eventExt);
- void getHidlRestartEvent(
- const vector<TunerFilterEvent>& filterEvents, DemuxFilterEventExt& eventExt);
-
- sp<FilterClientCallback> mFilterClientCallback;
-};
-
-struct HidlFilterCallback : public IFilterCallback {
-
-public:
- HidlFilterCallback(sp<FilterClientCallback> filterClientCallback);
- virtual Return<void> onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
- const DemuxFilterEventExt& filterEventExt);
- virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
- virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+ Status onFilterStatus(DemuxFilterStatus status);
+ Status onFilterEvent(const vector<DemuxFilterEvent>& filterEvents);
private:
sp<FilterClientCallback> mFilterClientCallback;
@@ -136,15 +65,12 @@ public:
FilterClient(DemuxFilterType type, shared_ptr<ITunerFilter> tunerFilter);
~FilterClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlFilter(sp<IFilter> filter);
-
/**
* Read size of data from filter FMQ into buffer.
*
* @return the actual reading size. -1 if failed to read.
*/
- int read(int8_t* buffer, int size);
+ int64_t read(int8_t* buffer, int64_t size);
/**
* Get the a/v shared memory handle information
@@ -159,12 +85,12 @@ public:
/**
* Configure the monitor event of the Filter.
*/
- Result configureMonitorEvent(int monitorEventType);
+ Result configureMonitorEvent(int32_t monitorEventType);
/**
* Configure the context id of the IP Filter.
*/
- Result configureIpFilterContextId(int cid);
+ Result configureIpFilterContextId(int32_t cid);
/**
* Configure the stream type of the media Filter.
@@ -189,12 +115,12 @@ public:
/**
* Get the 32-bit filter Id.
*/
- Result getId(uint32_t& id);
+ Result getId(int32_t& id);
/**
* Get the 64-bit filter Id.
*/
- Result getId64Bit(uint64_t& id);
+ Result getId64Bit(int64_t& id);
/**
* Release the handle reported by the HAL for AV memory.
@@ -207,11 +133,6 @@ public:
Result setDataSource(sp<FilterClient> filterClient);
/**
- * Get the Hal filter to build up filter linkage.
- */
- sp<IFilter> getHalFilter() { return mFilter; }
-
- /**
* Get the Aidl filter to build up filter linkage.
*/
shared_ptr<ITunerFilter> getAidlFilter() { return mTunerFilter; }
@@ -222,24 +143,8 @@ public:
Result close();
private:
- TunerFilterConfiguration getAidlFilterSettings(DemuxFilterSettings configure);
-
- TunerFilterConfiguration getAidlTsSettings(DemuxTsFilterSettings configure);
- TunerFilterConfiguration getAidlMmtpSettings(DemuxMmtpFilterSettings mmtp);
- TunerFilterConfiguration getAidlIpSettings(DemuxIpFilterSettings ip);
- TunerFilterConfiguration getAidlTlvSettings(DemuxTlvFilterSettings tlv);
- TunerFilterConfiguration getAidlAlpSettings(DemuxAlpFilterSettings alp);
-
- TunerFilterAvSettings getAidlAvSettings(DemuxFilterAvSettings hidlAv);
- TunerFilterSectionSettings getAidlSectionSettings(DemuxFilterSectionSettings hidlSection);
- TunerFilterPesDataSettings getAidlPesDataSettings(DemuxFilterPesDataSettings hidlPesData);
- TunerFilterRecordSettings getAidlRecordSettings(DemuxFilterRecordSettings hidlRecord);
- TunerFilterDownloadSettings getAidlDownloadSettings(DemuxFilterDownloadSettings hidlDownload);
-
- void getAidlIpAddress(DemuxIpAddress ipAddr,
- TunerDemuxIpAddress& srcIpAddress, TunerDemuxIpAddress& dstIpAddress);
Result getFilterMq();
- int copyData(int8_t* buffer, int size);
+ int64_t copyData(int8_t* buffer, int64_t size);
void checkIsMediaFilter(DemuxFilterType type);
void checkIsPassthroughFilter(DemuxFilterSettings configure);
void handleAvShareMemory();
@@ -251,22 +156,8 @@ private:
*/
shared_ptr<ITunerFilter> mTunerFilter;
- /**
- * A 1.0 Filter HAL interface that is ready before migrating to the TunerFilter.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<IFilter> mFilter;
-
- /**
- * A 1.1 Filter HAL interface that is ready before migrating to the TunerFilter.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<::android::hardware::tv::tuner::V1_1::IFilter> mFilter_1_1;
-
- AidlMQ* mFilterMQ = NULL;
- EventFlag* mFilterMQEventFlag = NULL;
+ AidlMQ* mFilterMQ = nullptr;
+ EventFlag* mFilterMQEventFlag = nullptr;
native_handle_t* mAvSharedHandle;
uint64_t mAvSharedMemSize;
diff --git a/media/jni/tuner/FilterClientCallback.h b/media/jni/tuner/FilterClientCallback.h
index 94b7821a8db7..05e7ff08f68e 100644
--- a/media/jni/tuner/FilterClientCallback.h
+++ b/media/jni/tuner/FilterClientCallback.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,20 +17,21 @@
#ifndef _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
#define _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
-using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
-using ::android::hardware::tv::tuner::V1_1::DemuxFilterEventExt;
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
+#include <utils/RefBase.h>
+
+using ::aidl::android::hardware::tv::tuner::DemuxFilterEvent;
+using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
using namespace std;
namespace android {
struct FilterClientCallback : public RefBase {
- virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
- const DemuxFilterEventExt& filterEventExt);
- virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
+ virtual void onFilterEvent(const vector<DemuxFilterEvent>& filterEvents);
virtual void onFilterStatus(const DemuxFilterStatus status);
};
} // namespace android
-#endif // _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_ \ No newline at end of file
+#endif // _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 5d9b12d59482..70309a087163 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,1235 +16,168 @@
#define LOG_TAG "FrontendClient"
-#include <android-base/logging.h>
-#include <utils/Log.h>
-
#include "FrontendClient.h"
-using ::aidl::android::media::tv::tuner::TunerFrontendScanAtsc3PlpInfo;
-using ::aidl::android::media::tv::tuner::TunerFrontendUnionSettings;
+#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <android-base/logging.h>
+#include <utils/Log.h>
-using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Bandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3TimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbcSpectralInversion;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbsRolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
-using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
-using ::android::hardware::tv::tuner::V1_0::FrontendInnerFec;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsRolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Rolloff;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtBandwidth;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtGuardInterval;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtMode;
-using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
-using ::android::hardware::tv::tuner::V1_0::FrontendModulationStatus;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatusAtsc3PlpInfo;
-using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
-using ::android::hardware::tv::tuner::V1_1::Constant;
-using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation;
-using ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval;
-using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
-using ::android::hardware::tv::tuner::V1_1::FrontendRollOff;
-using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
-using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode;
-using ::android::hardware::tv::tuner::V1_1::FrontendType;
+using ::aidl::android::hardware::tv::tuner::Constant;
namespace android {
-
/////////////// FrontendClient ///////////////////////
-
-FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int type) {
+FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, FrontendType type) {
mTunerFrontend = tunerFrontend;
mType = type;
}
FrontendClient::~FrontendClient() {
- mTunerFrontend = NULL;
- mFrontend = NULL;
- mFrontend_1_1 = NULL;
- mId = -1;
- mType = -1;
+ mTunerFrontend = nullptr;
+ mType = FrontendType::UNDEFINED;
}
Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
shared_ptr<TunerFrontendCallback> aidlCallback =
::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
- aidlCallback->setFrontendType(mType);
Status s = mTunerFrontend->setCallback(aidlCallback);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- sp<HidlFrontendCallback> hidlCallback = new HidlFrontendCallback(frontendClientCallback);
- return mFrontend->setCallback(hidlCallback);
-}
-
-void FrontendClient::setHidlFrontend(sp<IFrontend> frontend) {
- mFrontend = frontend;
- mFrontend_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
-}
-
-// TODO: move after migration is done
-void FrontendClient::setId(int id) {
- mId = id;
+ return Result::INVALID_STATE;
}
-Result FrontendClient::tune(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- if (mTunerFrontend != NULL) {
- TunerFrontendSettings tunerFeSettings = getAidlFrontendSettings(settings, settingsExt1_1);
- Status s = mTunerFrontend->tune(tunerFeSettings);
+Result FrontendClient::tune(const FrontendSettings& settings) {
+ if (mTunerFrontend != nullptr) {
+ Status s = mTunerFrontend->tune(settings);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- Result result;
- if (mFrontend_1_1 != NULL && validateExtendedSettings(settingsExt1_1)) {
- result = mFrontend_1_1->tune_1_1(settings, settingsExt1_1);
- return result;
- }
-
- if (mFrontend != NULL) {
- result = mFrontend->tune(settings);
- return result;
- }
-
return Result::INVALID_STATE;
}
Result FrontendClient::stopTune() {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->stopTune();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend != NULL) {
- Result result = mFrontend->stopTune();
- return result;
- }
-
return Result::INVALID_STATE;
}
-Result FrontendClient::scan(const FrontendSettings& settings, FrontendScanType type,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- if (mTunerFrontend != NULL) {
- TunerFrontendSettings tunerFeSettings = getAidlFrontendSettings(settings, settingsExt1_1);
- Status s = mTunerFrontend->scan(tunerFeSettings, (int)type);
+Result FrontendClient::scan(const FrontendSettings& settings, FrontendScanType type) {
+ if (mTunerFrontend != nullptr) {
+ Status s = mTunerFrontend->scan(settings, type);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- Result result;
- if (mFrontend_1_1 != NULL && validateExtendedSettings(settingsExt1_1)) {
- result = mFrontend_1_1->scan_1_1(settings, type, settingsExt1_1);
- return result;
- }
-
- if (mFrontend != NULL) {
- result = mFrontend->scan(settings, type);
- return result;
- }
-
return Result::INVALID_STATE;
}
Result FrontendClient::stopScan() {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->stopScan();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend != NULL) {
- Result result = mFrontend->stopScan();
- return result;
- }
-
return Result::INVALID_STATE;
}
vector<FrontendStatus> FrontendClient::getStatus(vector<FrontendStatusType> statusTypes) {
vector<FrontendStatus> status;
- if (mTunerFrontend != NULL) {
- vector<TunerFrontendStatus> aidlStatus;
- vector<int> types;
- for (auto t : statusTypes) {
- types.push_back((int)t);
- }
- Status s = mTunerFrontend->getStatus(types, &aidlStatus);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return status;
- }
- return getHidlStatus(aidlStatus);
- }
-
- if (mFrontend != NULL && statusTypes.size() > 0) {
- Result res;
- mFrontend->getStatus(statusTypes,
- [&](Result r, const hidl_vec<FrontendStatus>& s) {
- res = r;
- status = s;
- });
- if (res != Result::SUCCESS) {
- status.clear();
- return status;
- }
- }
-
- return status;
-}
-
-vector<FrontendStatusExt1_1> FrontendClient::getStatusExtended_1_1(
- vector<FrontendStatusTypeExt1_1> statusTypes) {
- vector<FrontendStatusExt1_1> status;
-
- if (mTunerFrontend != NULL) {
- vector<TunerFrontendStatus> aidlStatus;
- vector<int> types;
- for (auto t : statusTypes) {
- types.push_back((int)t);
- }
- Status s = mTunerFrontend->getStatusExtended_1_1(types, &aidlStatus);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return status;
- }
- return getHidlStatusExt(aidlStatus);
- }
-
- if (mFrontend_1_1 != NULL && statusTypes.size() > 0) {
- Result res;
- mFrontend_1_1->getStatusExt1_1(statusTypes,
- [&](Result r, const hidl_vec<FrontendStatusExt1_1>& s) {
- res = r;
- status = s;
- });
- if (res != Result::SUCCESS) {
- status.clear();
- return status;
- }
+ if (mTunerFrontend != nullptr) {
+ mTunerFrontend->getStatus(statusTypes, &status);
}
return status;
}
Result FrontendClient::setLnb(sp<LnbClient> lnbClient) {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->setLnb(lnbClient->getAidlLnb());
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend != NULL) {
- Result result = mFrontend->setLnb(lnbClient->getId());
- return result;
- }
-
return Result::INVALID_STATE;
}
Result FrontendClient::setLna(bool bEnable) {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->setLna(bEnable);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend != NULL) {
- Result result = mFrontend->setLna(bEnable);
- return result;
- }
-
return Result::INVALID_STATE;
}
-int FrontendClient::linkCiCamToFrontend(int ciCamId) {
- int ltsId = (int)Constant::INVALID_LTS_ID;
+int32_t FrontendClient::linkCiCamToFrontend(int32_t ciCamId) {
+ int32_t ltsId = static_cast<int32_t>(Constant::INVALID_LTS_ID);
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->linkCiCamToFrontend(ciCamId, &ltsId);
- if (ClientHelper::getServiceSpecificErrorCode(s) == Result::SUCCESS) {
- return ltsId;
- }
- return (int)Constant::INVALID_LTS_ID;
- }
-
- if (mFrontend_1_1 != NULL) {
- Result res;
- mFrontend_1_1->linkCiCam(static_cast<uint32_t>(ciCamId),
- [&](Result r, uint32_t id) {
- res = r;
- ltsId = id;
- });
- if (res != Result::SUCCESS) {
- return (int)Constant::INVALID_LTS_ID;
+ if (!s.isOk()) {
+ return static_cast<int32_t>(Constant::INVALID_LTS_ID);
}
}
return ltsId;
}
-Result FrontendClient::unlinkCiCamToFrontend(int ciCamId) {
- if (mTunerFrontend != NULL) {
+Result FrontendClient::unlinkCiCamToFrontend(int32_t ciCamId) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->unlinkCiCamToFrontend(ciCamId);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend_1_1 != NULL) {
- return mFrontend_1_1->unlinkCiCam(static_cast<uint32_t>(ciCamId));
- }
-
return Result::INVALID_STATE;
}
Result FrontendClient::close() {
- if (mTunerFrontend != NULL) {
+ if (mTunerFrontend != nullptr) {
Status s = mTunerFrontend->close();
- mTunerFrontend = NULL;
+ mTunerFrontend = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mFrontend != NULL) {
- Result result = mFrontend->close();
- mFrontend = NULL;
- mFrontend_1_1 = NULL;
- return result;
- }
-
return Result::INVALID_STATE;
}
-/////////////// TunerFrontend Helper Methods ///////////////////////
-
shared_ptr<ITunerFrontend> FrontendClient::getAidlFrontend() {
return mTunerFrontend;
}
-int FrontendClient::getId() {
- if (mTunerFrontend != NULL) {
- Status s = mTunerFrontend->getFrontendId(&mId);
- if (ClientHelper::getServiceSpecificErrorCode(s) == Result::SUCCESS) {
- return mId;
- }
- ALOGE("Failed to getFrontendId from Tuner Frontend");
- return -1;
- }
-
- if (mFrontend != NULL) {
- return mId;
- }
-
- return -1;
-}
-
-vector<FrontendStatus> FrontendClient::getHidlStatus(vector<TunerFrontendStatus>& aidlStatus) {
- vector<FrontendStatus> hidlStatus;
- for (TunerFrontendStatus s : aidlStatus) {
- FrontendStatus status = FrontendStatus();
- switch (s.getTag()) {
- case TunerFrontendStatus::isDemodLocked: {
- status.isDemodLocked(s.get<TunerFrontendStatus::isDemodLocked>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::snr: {
- status.snr(s.get<TunerFrontendStatus::snr>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::ber: {
- status.ber((uint32_t)s.get<TunerFrontendStatus::ber>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::per: {
- status.per((uint32_t)s.get<TunerFrontendStatus::per>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::preBer: {
- status.preBer((uint32_t)s.get<TunerFrontendStatus::preBer>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::signalQuality: {
- status.signalQuality((uint32_t)s.get<TunerFrontendStatus::signalQuality>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::signalStrength: {
- status.signalStrength(s.get<TunerFrontendStatus::signalStrength>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::symbolRate: {
- status.symbolRate((uint32_t)s.get<TunerFrontendStatus::symbolRate>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::innerFec: {
- status.innerFec(static_cast<FrontendInnerFec>(
- s.get<TunerFrontendStatus::innerFec>()));
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::modulation: {
- auto aidlMod = s.get<TunerFrontendStatus::modulation>();
- FrontendModulationStatus modulation;
- switch (mType) {
- case (int)FrontendType::DVBC:
- modulation.dvbc(static_cast<FrontendDvbcModulation>(aidlMod));
- status.modulation(modulation);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DVBS:
- modulation.dvbs(static_cast<FrontendDvbsModulation>(aidlMod));
- status.modulation(modulation);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBS:
- modulation.isdbs(static_cast<FrontendIsdbsModulation>(aidlMod));
- status.modulation(modulation);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBS3:
- modulation.isdbs3(static_cast<FrontendIsdbs3Modulation>(aidlMod));
- status.modulation(modulation);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBT:
- modulation.isdbt(static_cast<FrontendIsdbtModulation>(aidlMod));
- status.modulation(modulation);
- hidlStatus.push_back(status);
- break;
- default:
- break;
- }
- break;
- }
- case TunerFrontendStatus::inversion: {
- status.inversion(static_cast<FrontendDvbcSpectralInversion>(
- s.get<TunerFrontendStatus::inversion>()));
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::lnbVoltage: {
- status.lnbVoltage(static_cast<LnbVoltage>(
- s.get<TunerFrontendStatus::lnbVoltage>()));
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::plpId: {
- status.plpId((uint8_t)s.get<TunerFrontendStatus::plpId>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isEWBS: {
- status.isEWBS(s.get<TunerFrontendStatus::isEWBS>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::agc: {
- status.agc((uint8_t)s.get<TunerFrontendStatus::agc>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isLnaOn: {
- status.isLnaOn(s.get<TunerFrontendStatus::isLnaOn>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isLayerError: {
- auto aidlE = s.get<TunerFrontendStatus::isLayerError>();
- hidl_vec<bool> e(aidlE.begin(), aidlE.end());
- status.isLayerError(e);
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::mer: {
- status.mer(s.get<TunerFrontendStatus::mer>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::freqOffset: {
- status.freqOffset(s.get<TunerFrontendStatus::freqOffset>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::hierarchy: {
- status.hierarchy(static_cast<FrontendDvbtHierarchy>(
- s.get<TunerFrontendStatus::hierarchy>()));
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isRfLocked: {
- status.isRfLocked(s.get<TunerFrontendStatus::isRfLocked>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::plpInfo: {
- int size = s.get<TunerFrontendStatus::plpInfo>().size();
- hidl_vec<FrontendStatusAtsc3PlpInfo> info(size);
- for (int i = 0; i < size; i++) {
- auto aidlInfo = s.get<TunerFrontendStatus::plpInfo>()[i];
- info[i] = {
- .plpId = (uint8_t)aidlInfo.plpId,
- .isLocked = aidlInfo.isLocked,
- .uec = (uint32_t)aidlInfo.uec,
- };
- }
- status.plpInfo(info);
- hidlStatus.push_back(status);
- break;
- }
- default:
- break;
- }
- }
- return hidlStatus;
-}
-
-vector<FrontendStatusExt1_1> FrontendClient::getHidlStatusExt(
- vector<TunerFrontendStatus>& aidlStatus) {
- vector<FrontendStatusExt1_1> hidlStatus;
- for (TunerFrontendStatus s : aidlStatus) {
- FrontendStatusExt1_1 status;
- switch (s.getTag()) {
- case TunerFrontendStatus::modulations: {
- vector<FrontendModulation> ms;
- for (auto aidlMod : s.get<TunerFrontendStatus::modulations>()) {
- FrontendModulation m;
- switch (mType) {
- case (int)FrontendType::DVBC:
- m.dvbc(static_cast<FrontendDvbcModulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::DVBS:
- m.dvbs(static_cast<FrontendDvbsModulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::DVBT:
- m.dvbt(static_cast<FrontendDvbtConstellation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::ISDBS:
- m.isdbs(static_cast<FrontendIsdbsModulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::ISDBS3:
- m.isdbs3(static_cast<FrontendIsdbs3Modulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::ISDBT:
- m.isdbt(static_cast<FrontendIsdbtModulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::ATSC:
- m.atsc(static_cast<FrontendAtscModulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::ATSC3:
- m.atsc3(static_cast<FrontendAtsc3Modulation>(aidlMod));
- ms.push_back(m);
- break;
- case (int)FrontendType::DTMB:
- m.dtmb(static_cast<FrontendDtmbModulation>(aidlMod));
- ms.push_back(m);
- break;
- default:
- break;
- }
- }
- if (ms.size() > 0) {
- status.modulations(ms);
- hidlStatus.push_back(status);
- }
- break;
- }
- case TunerFrontendStatus::bers: {
- auto aidlB = s.get<TunerFrontendStatus::bers>();
- hidl_vec<uint32_t> b(aidlB.begin(), aidlB.end());
- status.bers(b);
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::codeRates: {
- vector<hardware::tv::tuner::V1_1::FrontendInnerFec> codeRates;
- for (auto aidlCodeRate : s.get<TunerFrontendStatus::codeRates>()) {
- codeRates.push_back(
- static_cast<hardware::tv::tuner::V1_1::FrontendInnerFec>(aidlCodeRate));
- }
- if (codeRates.size() > 0) {
- status.codeRates(codeRates);
- hidlStatus.push_back(status);
- }
- break;
- }
- case TunerFrontendStatus::bandwidth: {
- auto aidlBand = s.get<TunerFrontendStatus::bandwidth>();
- FrontendBandwidth band;
- switch (mType) {
- case (int)FrontendType::ATSC3:
- band.atsc3(static_cast<FrontendAtsc3Bandwidth>(aidlBand));
- status.bandwidth(band);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DVBC:
- band.dvbc(static_cast<FrontendDvbcBandwidth>(aidlBand));
- status.bandwidth(band);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DVBT:
- band.dvbt(static_cast<FrontendDvbtBandwidth>(aidlBand));
- status.bandwidth(band);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBT:
- band.isdbt(static_cast<FrontendIsdbtBandwidth>(aidlBand));
- status.bandwidth(band);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DTMB:
- band.dtmb(static_cast<FrontendDtmbBandwidth>(aidlBand));
- status.bandwidth(band);
- hidlStatus.push_back(status);
- break;
- default:
- break;
- }
- break;
- }
- case TunerFrontendStatus::interval: {
- auto aidlInter = s.get<TunerFrontendStatus::interval>();
- FrontendGuardInterval inter;
- switch (mType) {
- case (int)FrontendType::DVBT:
- inter.dvbt(static_cast<FrontendDvbtGuardInterval>(aidlInter));
- status.interval(inter);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBT:
- inter.isdbt(static_cast<FrontendIsdbtGuardInterval>(aidlInter));
- status.interval(inter);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DTMB:
- inter.dtmb(static_cast<FrontendDtmbGuardInterval>(aidlInter));
- status.interval(inter);
- hidlStatus.push_back(status);
- break;
- default:
- break;
- }
- break;
- }
- case TunerFrontendStatus::transmissionMode: {
- auto aidlTran = s.get<TunerFrontendStatus::transmissionMode>();
- FrontendTransmissionMode trans;
- switch (mType) {
- case (int)FrontendType::DVBT:
- trans.dvbt(static_cast<FrontendDvbtTransmissionMode>(aidlTran));
- status.transmissionMode(trans);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBT:
- trans.isdbt(static_cast<FrontendIsdbtMode>(aidlTran));
- status.transmissionMode(trans);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::DTMB:
- trans.dtmb(static_cast<FrontendDtmbTransmissionMode>(aidlTran));
- status.transmissionMode(trans);
- hidlStatus.push_back(status);
- break;
- default:
- break;
- }
- break;
- }
- case TunerFrontendStatus::uec: {
- status.uec((uint32_t)s.get<TunerFrontendStatus::uec>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::systemId: {
- status.systemId((uint16_t)s.get<TunerFrontendStatus::systemId>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::interleaving: {
- vector<FrontendInterleaveMode> modes;
- for (auto aidlInter : s.get<TunerFrontendStatus::interleaving>()) {
- FrontendInterleaveMode mode;
- switch (mType) {
- case (int)FrontendType::DVBC:
- mode.dvbc(static_cast<FrontendCableTimeInterleaveMode>(aidlInter));
- modes.push_back(mode);
- break;
- case (int)FrontendType::ATSC3:
- mode.atsc3(static_cast<FrontendAtsc3TimeInterleaveMode>(aidlInter));
- modes.push_back(mode);
- break;
- case (int)FrontendType::DTMB:
- mode.dtmb(static_cast<FrontendDtmbTimeInterleaveMode>(aidlInter));
- modes.push_back(mode);
- break;
- default:
- break;
- }
- }
- if (modes.size() > 0) {
- status.interleaving(modes);
- hidlStatus.push_back(status);
- }
- break;
- }
- case TunerFrontendStatus::isdbtSegment: {
- auto aidlSeg = s.get<TunerFrontendStatus::isdbtSegment>();
- hidl_vec<uint8_t> s(aidlSeg.begin(), aidlSeg.end());
- status.isdbtSegment(s);
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::tsDataRate: {
- auto aidlTs = s.get<TunerFrontendStatus::tsDataRate>();
- hidl_vec<uint32_t> ts(aidlTs.begin(), aidlTs.end());
- status.tsDataRate(ts);
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::rollOff: {
- auto aidlRoll = s.get<TunerFrontendStatus::rollOff>();
- FrontendRollOff roll;
- switch (mType) {
- case (int)FrontendType::DVBS:
- roll.dvbs(static_cast<FrontendDvbsRolloff>(aidlRoll));
- status.rollOff(roll);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBS:
- roll.isdbs(static_cast<FrontendIsdbsRolloff>(aidlRoll));
- status.rollOff(roll);
- hidlStatus.push_back(status);
- break;
- case (int)FrontendType::ISDBS3:
- roll.isdbs3(static_cast<FrontendIsdbs3Rolloff>(aidlRoll));
- status.rollOff(roll);
- hidlStatus.push_back(status);
- break;
- default:
- break;
- }
- break;
- }
- case TunerFrontendStatus::isMiso: {
- status.isMiso(s.get<TunerFrontendStatus::isMiso>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isLinear: {
- status.isLinear(s.get<TunerFrontendStatus::isLinear>());
- hidlStatus.push_back(status);
- break;
- }
- case TunerFrontendStatus::isShortFrames: {
- status.isShortFrames(s.get<TunerFrontendStatus::isShortFrames>());
- hidlStatus.push_back(status);
- break;
- }
- default:
- break;
- }
- }
- return hidlStatus;
-}
-
-TunerFrontendSettings FrontendClient::getAidlFrontendSettings(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- bool isExtended = validateExtendedSettings(settingsExt1_1);
- TunerFrontendSettings s{
- .isExtended = isExtended,
- .endFrequency = (int) settingsExt1_1.endFrequency,
- .inversion = (int) settingsExt1_1.inversion,
- };
-
- if (settingsExt1_1.settingExt.getDiscriminator()
- == FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::dtmb) {
- s.settings.set<TunerFrontendUnionSettings::dtmb>(getAidlDtmbSettings(settingsExt1_1));
- return s;
- }
-
- switch (settings.getDiscriminator()) {
- case FrontendSettings::hidl_discriminator::analog: {
- s.settings.set<TunerFrontendUnionSettings::analog>(
- getAidlAnalogSettings(settings, settingsExt1_1));
- break;
- }
- case FrontendSettings::hidl_discriminator::atsc: {
- s.settings.set<TunerFrontendUnionSettings::atsc>(getAidlAtscSettings(settings));
- break;
- }
- case FrontendSettings::hidl_discriminator::atsc3: {
- s.settings.set<TunerFrontendUnionSettings::atsc3>(getAidlAtsc3Settings(settings));
- break;
- }
- case FrontendSettings::hidl_discriminator::dvbs: {
- s.settings.set<TunerFrontendUnionSettings::dvbs>(
- getAidlDvbsSettings(settings, settingsExt1_1));
- break;
- }
- case FrontendSettings::hidl_discriminator::dvbc: {
- s.settings.set<TunerFrontendUnionSettings::cable>(
- getAidlCableSettings(settings, settingsExt1_1));
- break;
- }
- case FrontendSettings::hidl_discriminator::dvbt: {
- s.settings.set<TunerFrontendUnionSettings::dvbt>(
- getAidlDvbtSettings(settings, settingsExt1_1));
- break;
- }
- case FrontendSettings::hidl_discriminator::isdbs: {
- s.settings.set<TunerFrontendUnionSettings::isdbs>(getAidlIsdbsSettings(settings));
- break;
- }
- case FrontendSettings::hidl_discriminator::isdbs3: {
- s.settings.set<TunerFrontendUnionSettings::isdbs3>(getAidlIsdbs3Settings(settings));
- break;
- }
- case FrontendSettings::hidl_discriminator::isdbt: {
- s.settings.set<TunerFrontendUnionSettings::isdbt>(getAidlIsdbtSettings(settings));
- break;
+int32_t FrontendClient::getId() {
+ if (mTunerFrontend != nullptr) {
+ int32_t id;
+ Status s = mTunerFrontend->getFrontendId(&id);
+ if (s.isOk()) {
+ return id;
}
- default:
- break;
- }
- return s;
-}
-
-TunerFrontendAnalogSettings FrontendClient::getAidlAnalogSettings(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- TunerFrontendAnalogSettings analogSettings{
- .frequency = (int)settings.analog().frequency,
- .signalType = (int)settings.analog().type,
- .sifStandard = (int)settings.analog().sifStandard,
- };
- if (settingsExt1_1.settingExt.getDiscriminator()
- == FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::analog) {
- analogSettings.isExtended = true;
- analogSettings.aftFlag = (int)settingsExt1_1.settingExt.analog().aftFlag;
- } else {
- analogSettings.isExtended = false;
- }
- return analogSettings;
-}
-
-TunerFrontendDvbsSettings FrontendClient::getAidlDvbsSettings(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- TunerFrontendDvbsSettings dvbsSettings{
- .frequency = (int)settings.dvbs().frequency,
- .modulation = (int)settings.dvbs().modulation,
- .codeRate = {
- .fec = (long)settings.dvbs().coderate.fec,
- .isLinear = settings.dvbs().coderate.isLinear,
- .isShortFrames = settings.dvbs().coderate.isShortFrames,
- .bitsPer1000Symbol = (int)settings.dvbs().coderate.bitsPer1000Symbol,
- },
- .symbolRate = (int)settings.dvbs().symbolRate,
- .rolloff = (int)settings.dvbs().rolloff,
- .pilot = (int)settings.dvbs().pilot,
- .inputStreamId = (int)settings.dvbs().inputStreamId,
- .standard = (int)settings.dvbs().standard,
- .vcm = (int)settings.dvbs().vcmMode,
- };
- if (settingsExt1_1.settingExt.getDiscriminator()
- == FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::dvbs) {
- dvbsSettings.isExtended = true;
- dvbsSettings.scanType = (int)settingsExt1_1.settingExt.dvbs().scanType;
- dvbsSettings.isDiseqcRxMessage = settingsExt1_1.settingExt.dvbs().isDiseqcRxMessage;
- } else {
- dvbsSettings.isExtended = false;
- }
- return dvbsSettings;
-}
-
-TunerFrontendCableSettings FrontendClient::getAidlCableSettings(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- TunerFrontendCableSettings cableSettings{
- .frequency = (int)settings.dvbc().frequency,
- .modulation = (int)settings.dvbc().modulation,
- .innerFec = (long)settings.dvbc().fec,
- .symbolRate = (int)settings.dvbc().symbolRate,
- .outerFec = (int)settings.dvbc().outerFec,
- .annex = (int)settings.dvbc().annex,
- .spectralInversion = (int)settings.dvbc().spectralInversion,
- };
- if (settingsExt1_1.settingExt.getDiscriminator()
- == FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::dvbc) {
- cableSettings.isExtended = true;
- cableSettings.interleaveMode = (int)settingsExt1_1.settingExt.dvbc().interleaveMode;
- cableSettings.bandwidth = (int)settingsExt1_1.settingExt.dvbc().bandwidth;
- } else {
- cableSettings.isExtended = false;
}
- return cableSettings;
-}
-
-TunerFrontendDvbtSettings FrontendClient::getAidlDvbtSettings(const FrontendSettings& settings,
- const FrontendSettingsExt1_1& settingsExt1_1) {
- TunerFrontendDvbtSettings dvbtSettings{
- .frequency = (int)settings.dvbt().frequency,
- .transmissionMode = (int)settings.dvbt().transmissionMode,
- .bandwidth = (int)settings.dvbt().bandwidth,
- .constellation = (int)settings.dvbt().constellation,
- .hierarchy = (int)settings.dvbt().hierarchy,
- .hpCodeRate = (int)settings.dvbt().hpCoderate,
- .lpCodeRate = (int)settings.dvbt().lpCoderate,
- .guardInterval = (int)settings.dvbt().guardInterval,
- .isHighPriority = settings.dvbt().isHighPriority,
- .standard = (int)settings.dvbt().standard,
- .isMiso = settings.dvbt().isMiso,
- .plpMode = (int)settings.dvbt().plpMode,
- .plpId = (int)settings.dvbt().plpId,
- .plpGroupId = (int)settings.dvbt().plpGroupId,
- };
- if (settingsExt1_1.settingExt.getDiscriminator()
- == FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::dvbt) {
- dvbtSettings.isExtended = true;
- dvbtSettings.constellation = (int)settingsExt1_1.settingExt.dvbt().constellation;
- dvbtSettings.transmissionMode =
- (int)settingsExt1_1.settingExt.dvbt().transmissionMode;
- } else {
- dvbtSettings.isExtended = false;
- }
- return dvbtSettings;
-}
-
-TunerFrontendDtmbSettings FrontendClient::getAidlDtmbSettings(
- const FrontendSettingsExt1_1& settingsExt1_1) {
- TunerFrontendDtmbSettings dtmbSettings{
- .frequency = (int)settingsExt1_1.settingExt.dtmb().frequency,
- .transmissionMode = (int)settingsExt1_1.settingExt.dtmb().transmissionMode,
- .bandwidth = (int)settingsExt1_1.settingExt.dtmb().bandwidth,
- .modulation = (int)settingsExt1_1.settingExt.dtmb().modulation,
- .codeRate = (int)settingsExt1_1.settingExt.dtmb().codeRate,
- .guardInterval = (int)settingsExt1_1.settingExt.dtmb().guardInterval,
- .interleaveMode = (int)settingsExt1_1.settingExt.dtmb().interleaveMode,
- };
- return dtmbSettings;
-}
-
-TunerFrontendAtscSettings FrontendClient::getAidlAtscSettings(const FrontendSettings& settings) {
- TunerFrontendAtscSettings atscSettings{
- .frequency = (int)settings.atsc().frequency,
- .modulation = (int)settings.atsc().modulation,
- };
- return atscSettings;
-}
-
-TunerFrontendAtsc3Settings FrontendClient::getAidlAtsc3Settings(const FrontendSettings& settings) {
- TunerFrontendAtsc3Settings atsc3Settings{
- .frequency = (int)settings.atsc3().frequency,
- .bandwidth = (int)settings.atsc3().bandwidth,
- .demodOutputFormat = (int)settings.atsc3().demodOutputFormat,
- };
- atsc3Settings.plpSettings.resize(settings.atsc3().plpSettings.size());
- for (auto plpSetting : settings.atsc3().plpSettings) {
- atsc3Settings.plpSettings.push_back({
- .plpId = (int)plpSetting.plpId,
- .modulation = (int)plpSetting.modulation,
- .interleaveMode = (int)plpSetting.interleaveMode,
- .codeRate = (int)plpSetting.codeRate,
- .fec = (int)plpSetting.fec,
- });
- }
- return atsc3Settings;
-}
-
-TunerFrontendIsdbsSettings FrontendClient::getAidlIsdbsSettings(const FrontendSettings& settings) {
- TunerFrontendIsdbsSettings isdbsSettings{
- .frequency = (int)settings.isdbs().frequency,
- .streamId = (char16_t)settings.isdbs().streamId,
- .streamIdType = (int)settings.isdbs().streamIdType,
- .modulation = (int)settings.isdbs().modulation,
- .codeRate = (int)settings.isdbs().coderate,
- .symbolRate = (int)settings.isdbs().symbolRate,
- .rolloff = (int)settings.isdbs().rolloff,
- };
- return isdbsSettings;
-}
-
-TunerFrontendIsdbs3Settings FrontendClient::getAidlIsdbs3Settings(
- const FrontendSettings& settings) {
- TunerFrontendIsdbs3Settings isdbs3Settings{
- .frequency = (int)settings.isdbs3().frequency,
- .streamId = (char16_t)settings.isdbs3().streamId,
- .streamIdType = (int)settings.isdbs3().streamIdType,
- .modulation = (int)settings.isdbs3().modulation,
- .codeRate = (int)settings.isdbs3().coderate,
- .symbolRate = (int)settings.isdbs3().symbolRate,
- .rolloff = (int)settings.isdbs3().rolloff,
- };
- return isdbs3Settings;
-}
-
-TunerFrontendIsdbtSettings FrontendClient::getAidlIsdbtSettings(const FrontendSettings& settings) {
- TunerFrontendIsdbtSettings isdbtSettings{
- .frequency = (int)settings.isdbt().frequency,
- .modulation = (int)settings.isdbt().modulation,
- .bandwidth = (int)settings.isdbt().bandwidth,
- .mode = (int)settings.isdbt().mode,
- .codeRate = (int)settings.isdbt().coderate,
- .guardInterval = (int)settings.isdbt().guardInterval,
- .serviceAreaId = (int)settings.isdbt().serviceAreaId,
- };
- return isdbtSettings;
-}
-bool FrontendClient::validateExtendedSettings(const FrontendSettingsExt1_1& settingsExt1_1) {
- return settingsExt1_1.endFrequency != (uint32_t)Constant::INVALID_FRONTEND_SETTING_FREQUENCY
- || settingsExt1_1.inversion != FrontendSpectralInversion::UNDEFINED
- || settingsExt1_1.settingExt.getDiscriminator()
- != FrontendSettingsExt1_1::SettingsExt::hidl_discriminator::noinit;
+ return static_cast<int32_t>(Constant::INVALID_FRONTEND_ID);
}
-/////////////// TunerFrontendCallback ///////////////////////
-
+/////////////// IFrontendCallback ///////////////////////
TunerFrontendCallback::TunerFrontendCallback(sp<FrontendClientCallback> frontendClientCallback)
: mFrontendClientCallback(frontendClientCallback) {}
-Status TunerFrontendCallback::onEvent(int frontendEventType) {
- if (mFrontendClientCallback != NULL) {
- mFrontendClientCallback->onEvent(static_cast<FrontendEventType>(frontendEventType));
+Status TunerFrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ if (mFrontendClientCallback != nullptr) {
+ mFrontendClientCallback->onEvent(frontendEventType);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-Status TunerFrontendCallback::onScanMessage(int messageType,
- const TunerFrontendScanMessage& message) {
- if (mFrontendClientCallback != NULL) {
- if (!is1_1ExtendedScanMessage(messageType)) {
- mFrontendClientCallback->onScanMessage(
- static_cast<FrontendScanMessageType>(messageType),
- getHalScanMessage(messageType, message));
- } else {
- mFrontendClientCallback->onScanMessageExt1_1(
- static_cast<FrontendScanMessageTypeExt1_1>(messageType),
- getHalScanMessageExt1_1(messageType, message));
- }
+Status TunerFrontendCallback::onScanMessage(FrontendScanMessageType messageType,
+ const FrontendScanMessage& message) {
+ if (mFrontendClientCallback != nullptr) {
+ mFrontendClientCallback->onScanMessage(messageType, message);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-/////////////// IFrontendCallback ///////////////////////
-
-HidlFrontendCallback::HidlFrontendCallback(sp<FrontendClientCallback> frontendClientCallback)
- : mFrontendClientCallback(frontendClientCallback) {}
-
-Return<void> HidlFrontendCallback::onEvent(FrontendEventType frontendEventType) {
- if (mFrontendClientCallback != NULL) {
- mFrontendClientCallback->onEvent(frontendEventType);
- }
- return Void();
-}
-
-Return<void> HidlFrontendCallback::onScanMessage(FrontendScanMessageType type,
- const FrontendScanMessage& message) {
- if (mFrontendClientCallback != NULL) {
- mFrontendClientCallback->onScanMessage(type, message);
- }
- return Void();
-}
-
-Return<void> HidlFrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
- const FrontendScanMessageExt1_1& message) {
- if (mFrontendClientCallback != NULL) {
- mFrontendClientCallback->onScanMessageExt1_1(type, message);
- }
- return Void();
-}
-
-/////////////// FrontendClientCallback Helper Methods ///////////////////////
-
-FrontendScanMessage TunerFrontendCallback::getHalScanMessage(
- int messageType, const TunerFrontendScanMessage& message) {
- FrontendScanMessage scanMessage;
- switch (messageType) {
- case (int) FrontendScanMessageType::LOCKED:
- scanMessage.isLocked(message.get<TunerFrontendScanMessage::isLocked>());
- break;
- case (int) FrontendScanMessageType::END:
- scanMessage.isEnd(message.get<TunerFrontendScanMessage::isEnd>());
- break;
- case (int) FrontendScanMessageType::PROGRESS_PERCENT:
- scanMessage.progressPercent(message.get<TunerFrontendScanMessage::progressPercent>());
- break;
- case (int) FrontendScanMessageType::FREQUENCY: {
- vector<int> f = message.get<TunerFrontendScanMessage::frequencies>();
- hidl_vec<uint32_t> frequencies(begin(f), end(f));
- scanMessage.frequencies(frequencies);
- break;
- }
- case (int) FrontendScanMessageType::SYMBOL_RATE: {
- vector<int> s = message.get<TunerFrontendScanMessage::symbolRates>();
- hidl_vec<uint32_t> symbolRates(begin(s), end(s));
- scanMessage.symbolRates(symbolRates);
- break;
- }
- case (int) FrontendScanMessageType::HIERARCHY:
- scanMessage.hierarchy(static_cast<FrontendDvbtHierarchy>(
- message.get<TunerFrontendScanMessage::hierarchy>()));
- break;
- case (int) FrontendScanMessageType::ANALOG_TYPE:
- scanMessage.analogType(static_cast<FrontendAnalogType>(
- message.get<TunerFrontendScanMessage::analogType>()));
- break;
- case (int) FrontendScanMessageType::PLP_IDS: {
- vector<uint8_t> p = message.get<TunerFrontendScanMessage::plpIds>();
- hidl_vec<uint8_t> plpIds(begin(p), end(p));
- scanMessage.plpIds(plpIds);
- break;
- }
- case (int) FrontendScanMessageType::GROUP_IDS: {
- vector<uint8_t> g = message.get<TunerFrontendScanMessage::groupIds>();
- hidl_vec<uint8_t> groupIds(begin(g), end(g));
- scanMessage.groupIds(groupIds);
- break;
- }
- case (int) FrontendScanMessageType::INPUT_STREAM_IDS: {
- vector<char16_t> i = message.get<TunerFrontendScanMessage::inputStreamIds>();
- hidl_vec<uint16_t> inputStreamIds(begin(i), end(i));
- scanMessage.inputStreamIds(inputStreamIds);
- break;
- }
- case (int) FrontendScanMessageType::STANDARD: {
- FrontendScanMessage::Standard std;
- int standard = message.get<TunerFrontendScanMessage::std>();
- switch (mType) {
- case (int) FrontendType::DVBS:
- std.sStd(static_cast<FrontendDvbsStandard>(standard));
- scanMessage.std(std);
- break;
- case (int) FrontendType::DVBT:
- std.tStd(static_cast<FrontendDvbtStandard>(standard));
- scanMessage.std(std);
- break;
- case (int) FrontendType::ANALOG:
- std.sifStd(static_cast<FrontendAnalogSifStandard>(standard));
- scanMessage.std(std);
- break;
- default:
- break;
- }
- break;
- }
- case (int) FrontendScanMessageType::ATSC3_PLP_INFO: {
- vector<TunerFrontendScanAtsc3PlpInfo> plp =
- message.get<TunerFrontendScanMessage::atsc3PlpInfos>();
- hidl_vec<FrontendScanAtsc3PlpInfo> plpInfo;
- int size = plp.size();
- plpInfo.resize(size);
- for (int i = 0; i < size; i++) {
- auto info = message.get<TunerFrontendScanMessage::atsc3PlpInfos>()[i];
- FrontendScanAtsc3PlpInfo p{
- .plpId = static_cast<uint8_t>(info.plpId),
- .bLlsFlag = info.llsFlag,
- };
- plpInfo[i] = p;
- }
- scanMessage.atsc3PlpInfos(plpInfo);
- break;
- }
- default:
- break;
- }
- return scanMessage;
-}
-
-FrontendScanMessageExt1_1 TunerFrontendCallback::getHalScanMessageExt1_1(
- int messageType, const TunerFrontendScanMessage& message) {
- FrontendScanMessageExt1_1 scanMessage;
- switch (messageType) {
- case (int) FrontendScanMessageTypeExt1_1::HIGH_PRIORITY:
- scanMessage.isHighPriority(message.get<TunerFrontendScanMessage::isHighPriority>());
- break;
- case (int) FrontendScanMessageTypeExt1_1::DVBC_ANNEX:
- scanMessage.annex(static_cast<FrontendDvbcAnnex>(
- message.get<TunerFrontendScanMessage::annex>()));
- break;
- case (int) FrontendScanMessageTypeExt1_1::MODULATION: {
- FrontendModulation m;
- int modulation = message.get<TunerFrontendScanMessage::modulation>();
- switch (mType) {
- case (int) FrontendType::DVBC:
- m.dvbc(static_cast<FrontendDvbcModulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::DVBS:
- m.dvbs(static_cast<FrontendDvbsModulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::DVBT:
- m.dvbt(static_cast<FrontendDvbtConstellation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::ISDBS:
- m.isdbs(static_cast<FrontendIsdbsModulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::ISDBS3:
- m.isdbs3(static_cast<FrontendIsdbs3Modulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::ISDBT:
- m.isdbt(static_cast<FrontendIsdbtModulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::ATSC:
- m.atsc(static_cast<FrontendAtscModulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) FrontendType::ATSC3:
- m.atsc3(static_cast<FrontendAtsc3Modulation>(modulation));
- scanMessage.modulation(m);
- break;
- case (int) hardware::tv::tuner::V1_1::FrontendType::DTMB:
- m.dtmb(static_cast<FrontendDtmbModulation>(modulation));
- scanMessage.modulation(m);
- break;
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
- return scanMessage;
-}
-
-bool TunerFrontendCallback::is1_1ExtendedScanMessage(int messageType) {
- return messageType >= (int)FrontendScanMessageTypeExt1_1::MODULATION
- && messageType <= (int)FrontendScanMessageTypeExt1_1::HIGH_PRIORITY;
-}
} // namespace android
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index 1dd950eee9e1..08c0b20d18ed 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,53 +17,29 @@
#ifndef _ANDROID_MEDIA_TV_FRONTEND_CLIENT_H_
#define _ANDROID_MEDIA_TV_FRONTEND_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/DemuxFilterSettings.h>
+#include <aidl/android/hardware/tv/tuner/FrontendType.h>
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidl/android/media/tv/tuner/BnTunerFrontendCallback.h>
#include <aidl/android/media/tv/tuner/ITunerFrontend.h>
-#include <android/hardware/tv/tuner/1.1/IFrontend.h>
-#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
+#include <utils/RefBase.h>
#include "ClientHelper.h"
#include "FrontendClientCallback.h"
#include "LnbClient.h"
using Status = ::ndk::ScopedAStatus;
-
+using ::aidl::android::hardware::tv::tuner::FrontendEventType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessage;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanType;
+using ::aidl::android::hardware::tv::tuner::FrontendSettings;
+using ::aidl::android::hardware::tv::tuner::FrontendStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
+using ::aidl::android::hardware::tv::tuner::FrontendType;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tuner::BnTunerFrontendCallback;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
-using ::aidl::android::media::tv::tuner::TunerFrontendAnalogSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendAtscSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Settings;
-using ::aidl::android::media::tv::tuner::TunerFrontendCableSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendDvbsSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendDvbtSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendDtmbSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendIsdbsSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendIsdbs3Settings;
-using ::aidl::android::media::tv::tuner::TunerFrontendIsdbtSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendScanMessage;
-using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
-using ::aidl::android::media::tv::tuner::TunerFrontendStatus;
-
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
-using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
-using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatus;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
-using ::android::hardware::tv::tuner::V1_0::IFrontend;
-using ::android::hardware::tv::tuner::V1_0::Result;
-
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
-using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
using namespace std;
@@ -74,32 +50,8 @@ class TunerFrontendCallback : public BnTunerFrontendCallback {
public:
TunerFrontendCallback(sp<FrontendClientCallback> frontendClientCallback);
- Status onEvent(int frontendEventType);
-
- Status onScanMessage(int messageType, const TunerFrontendScanMessage& message);
-
- void setFrontendType(int frontendType) { mType = frontendType; }
-
-private:
- FrontendScanMessage getHalScanMessage(int messageType, const TunerFrontendScanMessage& message);
- FrontendScanMessageExt1_1 getHalScanMessageExt1_1(int messageType,
- const TunerFrontendScanMessage& message);
- bool is1_1ExtendedScanMessage(int messageType);
-
- sp<FrontendClientCallback> mFrontendClientCallback;
- int mType;
-};
-
-struct HidlFrontendCallback : public IFrontendCallback {
-
-public:
- HidlFrontendCallback(sp<FrontendClientCallback> frontendClientCallback);
-
- virtual Return<void> onEvent(FrontendEventType frontendEventType);
- virtual Return<void> onScanMessage(
- FrontendScanMessageType type, const FrontendScanMessage& message);
- virtual Return<void> onScanMessageExt1_1(
- FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
+ Status onEvent(FrontendEventType frontendEventType);
+ Status onScanMessage(FrontendScanMessageType messageType, const FrontendScanMessage& message);
private:
sp<FrontendClientCallback> mFrontendClientCallback;
@@ -108,7 +60,7 @@ private:
struct FrontendClient : public RefBase {
public:
- FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int type);
+ FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, FrontendType type);
~FrontendClient();
/**
@@ -116,13 +68,10 @@ public:
*/
Result setCallback(sp<FrontendClientCallback> frontendClientCallback);
- // TODO: remove after migration to Tuner Service is done.
- void setHidlFrontend(sp<IFrontend> frontend);
-
/**
* Tuner Frontend with Frontend Settings.
*/
- Result tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
+ Result tune(const FrontendSettings& settings);
/**
* Stop tune Frontend.
@@ -132,8 +81,7 @@ public:
/**
* Scan the frontend to use the settings given.
*/
- Result scan(const FrontendSettings& settings, FrontendScanType frontendScanType,
- const FrontendSettingsExt1_1& settingsExt1_1);
+ Result scan(const FrontendSettings& settings, FrontendScanType frontendScanType);
/**
* Stop the previous scanning.
@@ -146,12 +94,6 @@ public:
vector<FrontendStatus> getStatus(vector<FrontendStatusType> statusTypes);
/**
- * Gets the 1.1 extended statuses of the frontend.
- */
- vector<FrontendStatusExt1_1> getStatusExtended_1_1(
- vector<FrontendStatusTypeExt1_1> statusTypes);
-
- /**
* Sets Low-Noise Block downconverter (LNB) for satellite frontend.
*/
Result setLnb(sp<LnbClient> lnbClient);
@@ -166,68 +108,28 @@ public:
*
* @return lts id
*/
- int linkCiCamToFrontend(int ciCamId);
+ int32_t linkCiCamToFrontend(int32_t ciCamId);
/**
* Unink Frontend to the cicam with given id.
*/
- Result unlinkCiCamToFrontend(int ciCamId);
+ Result unlinkCiCamToFrontend(int32_t ciCamId);
/**
* Close Frontend.
*/
Result close();
+ int32_t getId();
shared_ptr<ITunerFrontend> getAidlFrontend();
-
- void setId(int id);
- int getId();
-
private:
- vector<FrontendStatus> getHidlStatus(vector<TunerFrontendStatus>& aidlStatus);
- vector<FrontendStatusExt1_1> getHidlStatusExt(vector<TunerFrontendStatus>& aidlStatus);
-
- TunerFrontendSettings getAidlFrontendSettings(
- const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendAnalogSettings getAidlAnalogSettings(
- const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendDvbsSettings getAidlDvbsSettings(
- const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendCableSettings getAidlCableSettings(
- const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendDvbtSettings getAidlDvbtSettings(
- const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendDtmbSettings getAidlDtmbSettings(const FrontendSettingsExt1_1& settingsExt1_1);
- TunerFrontendAtscSettings getAidlAtscSettings(const FrontendSettings& settings);
- TunerFrontendAtsc3Settings getAidlAtsc3Settings(const FrontendSettings& settings);
- TunerFrontendIsdbsSettings getAidlIsdbsSettings(const FrontendSettings& settings);
- TunerFrontendIsdbs3Settings getAidlIsdbs3Settings(const FrontendSettings& settings);
- TunerFrontendIsdbtSettings getAidlIsdbtSettings(const FrontendSettings& settings);
-
- bool validateExtendedSettings(const FrontendSettingsExt1_1& settingsExt1_1);
-
/**
* An AIDL Tuner Frontend Singleton assigned at the first time when the Tuner Client
* opens a frontend cient. Default null when the service does not exist.
*/
shared_ptr<ITunerFrontend> mTunerFrontend;
- /**
- * A Frontend 1.0 HAL interface as a fall back interface when the Tuner Service does not exist.
- * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
- * Default null.
- */
- sp<IFrontend> mFrontend;
-
- /**
- * A Frontend 1.1 HAL interface as a fall back interface when the Tuner Service does not exist.
- * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
- * Default null.
- */
- sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
-
- int mId;
- int mType;
+ FrontendType mType;
};
} // namespace android
diff --git a/media/jni/tuner/FrontendClientCallback.h b/media/jni/tuner/FrontendClientCallback.h
index 94f8c406688e..15b08ef673cb 100644
--- a/media/jni/tuner/FrontendClientCallback.h
+++ b/media/jni/tuner/FrontendClientCallback.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,11 +17,11 @@
#ifndef _ANDROID_MEDIA_TV_FRONTEND_CLIENT_CALLBACK_H_
#define _ANDROID_MEDIA_TV_FRONTEND_CLIENT_CALLBACK_H_
-using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
-using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
-using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+#include <utils/RefBase.h>
+
+using ::aidl::android::hardware::tv::tuner::FrontendEventType;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessage;
+using ::aidl::android::hardware::tv::tuner::FrontendScanMessageType;
using namespace std;
@@ -30,8 +30,6 @@ namespace android {
struct FrontendClientCallback : public RefBase {
virtual void onEvent(FrontendEventType frontendEventType);
virtual void onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message);
- virtual void onScanMessageExt1_1(
- FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
};
} // namespace android
diff --git a/media/jni/tuner/LnbClient.cpp b/media/jni/tuner/LnbClient.cpp
index 073c49a2d6ac..43198e3a3fc6 100644
--- a/media/jni/tuner/LnbClient.cpp
+++ b/media/jni/tuner/LnbClient.cpp
@@ -21,148 +21,89 @@
#include "LnbClient.h"
-using ::android::hardware::tv::tuner::V1_0::Result;
-
namespace android {
/////////////// LnbClient ///////////////////////
-
LnbClient::LnbClient(shared_ptr<ITunerLnb> tunerLnb) {
mTunerLnb = tunerLnb;
- mId = -1;
}
LnbClient::~LnbClient() {
- mTunerLnb = NULL;
- mLnb = NULL;
- mId = -1;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void LnbClient::setHidlLnb(sp<ILnb> lnb) {
- mLnb = lnb;
+ mTunerLnb = nullptr;
}
Result LnbClient::setCallback(sp<LnbClientCallback> cb) {
- if (mTunerLnb != NULL) {
+ if (mTunerLnb != nullptr) {
shared_ptr<TunerLnbCallback> aidlCallback =
::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
Status s = mTunerLnb->setCallback(aidlCallback);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- sp<HidlLnbCallback> hidlCallback = new HidlLnbCallback(cb);
- return mLnb->setCallback(hidlCallback);
- }
-
return Result::INVALID_STATE;
}
Result LnbClient::setVoltage(LnbVoltage voltage) {
- if (mTunerLnb != NULL) {
- Status s = mTunerLnb->setVoltage((int)voltage);
+ if (mTunerLnb != nullptr) {
+ Status s = mTunerLnb->setVoltage(voltage);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- return mLnb->setVoltage(voltage);
- }
-
return Result::INVALID_STATE;
}
Result LnbClient::setTone(LnbTone tone) {
- if (mTunerLnb != NULL) {
- Status s = mTunerLnb->setTone((int)tone);
+ if (mTunerLnb != nullptr) {
+ Status s = mTunerLnb->setTone(tone);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- return mLnb->setTone(tone);
- }
-
return Result::INVALID_STATE;
}
Result LnbClient::setSatellitePosition(LnbPosition position) {
- if (mTunerLnb != NULL) {
- Status s = mTunerLnb->setSatellitePosition((int)position);
+ if (mTunerLnb != nullptr) {
+ Status s = mTunerLnb->setSatellitePosition(position);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- return mLnb->setSatellitePosition(position);
- }
-
return Result::INVALID_STATE;
}
Result LnbClient::sendDiseqcMessage(vector<uint8_t> diseqcMessage) {
- if (mTunerLnb != NULL) {
+ if (mTunerLnb != nullptr) {
Status s = mTunerLnb->sendDiseqcMessage(diseqcMessage);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- return mLnb->sendDiseqcMessage(diseqcMessage);
- }
-
return Result::INVALID_STATE;
}
Result LnbClient::close() {
- if (mTunerLnb != NULL) {
+ if (mTunerLnb != nullptr) {
Status s = mTunerLnb->close();
- mTunerLnb = NULL;
+ mTunerLnb = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mLnb != NULL) {
- Result res = mLnb->close();
- mLnb = NULL;
- return res;
- }
-
return Result::INVALID_STATE;
}
-/////////////// ILnbCallback ///////////////////////
-
-HidlLnbCallback::HidlLnbCallback(sp<LnbClientCallback> lnbClientCallback)
- : mLnbClientCallback(lnbClientCallback) {}
-
-Return<void> HidlLnbCallback::onEvent(const LnbEventType lnbEventType) {
- if (mLnbClientCallback != NULL) {
- mLnbClientCallback->onEvent(lnbEventType);
- }
- return Void();
-}
-
-Return<void> HidlLnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
- if (mLnbClientCallback != NULL) {
- mLnbClientCallback->onDiseqcMessage(diseqcMessage);
- }
- return Void();
-}
-
/////////////// TunerLnbCallback ///////////////////////
-
TunerLnbCallback::TunerLnbCallback(sp<LnbClientCallback> lnbClientCallback)
: mLnbClientCallback(lnbClientCallback) {}
-Status TunerLnbCallback::onEvent(int lnbEventType) {
- if (mLnbClientCallback != NULL) {
- mLnbClientCallback->onEvent(static_cast<LnbEventType>(lnbEventType));
+Status TunerLnbCallback::onEvent(LnbEventType lnbEventType) {
+ if (mLnbClientCallback != nullptr) {
+ mLnbClientCallback->onEvent(lnbEventType);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
Status TunerLnbCallback::onDiseqcMessage(const vector<uint8_t>& diseqcMessage) {
- if (mLnbClientCallback != NULL) {
- hidl_vec<uint8_t> msg(begin(diseqcMessage), end(diseqcMessage));
- mLnbClientCallback->onDiseqcMessage(msg);
+ if (mLnbClientCallback != nullptr) {
+ mLnbClientCallback->onDiseqcMessage(diseqcMessage);
return Status::ok();
}
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
diff --git a/media/jni/tuner/LnbClient.h b/media/jni/tuner/LnbClient.h
index 7c6118c98eb5..86e3f679576d 100644
--- a/media/jni/tuner/LnbClient.h
+++ b/media/jni/tuner/LnbClient.h
@@ -17,31 +17,24 @@
#ifndef _ANDROID_MEDIA_TV_LNB_CLIENT_H_
#define _ANDROID_MEDIA_TV_LNB_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/LnbPosition.h>
+#include <aidl/android/hardware/tv/tuner/LnbTone.h>
+#include <aidl/android/hardware/tv/tuner/LnbVoltage.h>
#include <aidl/android/media/tv/tuner/BnTunerLnbCallback.h>
#include <aidl/android/media/tv/tuner/ITunerLnb.h>
-#include <android/hardware/tv/tuner/1.0/ILnb.h>
-#include <android/hardware/tv/tuner/1.0/ILnbCallback.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
+#include <utils/RefBase.h>
#include "ClientHelper.h"
#include "LnbClientCallback.h"
using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::hardware::tv::tuner::LnbPosition;
+using ::aidl::android::hardware::tv::tuner::LnbTone;
+using ::aidl::android::hardware::tv::tuner::LnbVoltage;
using ::aidl::android::media::tv::tuner::BnTunerLnbCallback;
using ::aidl::android::media::tv::tuner::ITunerLnb;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::tv::tuner::V1_0::ILnb;
-using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
-using ::android::hardware::tv::tuner::V1_0::LnbId;
-using ::android::hardware::tv::tuner::V1_0::LnbPosition;
-using ::android::hardware::tv::tuner::V1_0::LnbTone;
-using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
-using ::android::hardware::tv::tuner::V1_0::Result;
-
using namespace std;
namespace android {
@@ -51,33 +44,19 @@ class TunerLnbCallback : public BnTunerLnbCallback {
public:
TunerLnbCallback(sp<LnbClientCallback> lnbClientCallback);
- Status onEvent(int lnbEventType);
+ Status onEvent(LnbEventType lnbEventType);
Status onDiseqcMessage(const vector<uint8_t>& diseqcMessage);
private:
sp<LnbClientCallback> mLnbClientCallback;
};
-struct HidlLnbCallback : public ILnbCallback {
-
-public:
- HidlLnbCallback(sp<LnbClientCallback> lnbClientCallback);
- virtual Return<void> onEvent(const LnbEventType lnbEventType);
- virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
-
-private:
- sp<LnbClientCallback> mLnbClientCallback;
-};
-
struct LnbClient : public RefBase {
public:
LnbClient(shared_ptr<ITunerLnb> tunerLnb);
~LnbClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlLnb(sp<ILnb> lnb);
-
/**
* Set the lnb callback.
*/
@@ -109,8 +88,6 @@ public:
Result close();
shared_ptr<ITunerLnb> getAidlLnb() { return mTunerLnb; }
- void setId(LnbId id) { mId = id; }
- LnbId getId() { return mId; }
private:
/**
@@ -118,15 +95,6 @@ private:
* opens an Lnb. Default null when lnb is not opened.
*/
shared_ptr<ITunerLnb> mTunerLnb;
-
- /**
- * A Lnb HAL interface that is ready before migrating to the TunerLnb.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<ILnb> mLnb;
-
- LnbId mId;
};
} // namespace android
diff --git a/media/jni/tuner/LnbClientCallback.h b/media/jni/tuner/LnbClientCallback.h
index 253d7ef110e3..612514f60fef 100644
--- a/media/jni/tuner/LnbClientCallback.h
+++ b/media/jni/tuner/LnbClientCallback.h
@@ -17,8 +17,9 @@
#ifndef _ANDROID_MEDIA_TV_LNB_CLIENT_CALLBACK_H_
#define _ANDROID_MEDIA_TV_LNB_CLIENT_CALLBACK_H_
-using ::android::hardware::hidl_vec;
-using ::android::hardware::tv::tuner::V1_0::LnbEventType;
+#include <utils/RefBase.h>
+
+using ::aidl::android::hardware::tv::tuner::LnbEventType;
using namespace std;
@@ -26,8 +27,8 @@ namespace android {
struct LnbClientCallback : public RefBase {
virtual void onEvent(const LnbEventType lnbEventType);
- virtual void onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+ virtual void onDiseqcMessage(const vector<uint8_t>& diseqcMessage);
};
} // namespace android
-#endif // _ANDROID_MEDIA_TV_LNB_CLIENT_CALLBACK_H_ \ No newline at end of file
+#endif // _ANDROID_MEDIA_TV_LNB_CLIENT_CALLBACK_H_
diff --git a/media/jni/tuner/TimeFilterClient.cpp b/media/jni/tuner/TimeFilterClient.cpp
index e123c9f57ce7..40dba8b4c420 100644
--- a/media/jni/tuner/TimeFilterClient.cpp
+++ b/media/jni/tuner/TimeFilterClient.cpp
@@ -16,14 +16,15 @@
#define LOG_TAG "TimeFilterClient"
+#include "TimeFilterClient.h"
+
+#include <aidl/android/hardware/tv/tuner/Constant64Bit.h>
#include <android-base/logging.h>
#include <utils/Log.h>
#include "ClientHelper.h"
-#include "TimeFilterClient.h"
-using ::android::hardware::tv::tuner::V1_0::Result;
-using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
+using ::aidl::android::hardware::tv::tuner::Constant64Bit;
namespace android {
@@ -34,108 +35,60 @@ TimeFilterClient::TimeFilterClient(shared_ptr<ITunerTimeFilter> tunerTimeFilter)
}
TimeFilterClient::~TimeFilterClient() {
- mTunerTimeFilter = NULL;
- mTimeFilter = NULL;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void TimeFilterClient::setHidlTimeFilter(sp<ITimeFilter> timeFilter) {
- mTimeFilter = timeFilter;
+ mTunerTimeFilter = nullptr;
}
-Result TimeFilterClient::setTimeStamp(long timeStamp) {
- if (mTunerTimeFilter != NULL) {
+Result TimeFilterClient::setTimeStamp(int64_t timeStamp) {
+ if (mTunerTimeFilter != nullptr) {
Status s = mTunerTimeFilter->setTimeStamp(timeStamp);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mTimeFilter != NULL) {
- return mTimeFilter->setTimeStamp(timeStamp);
- }
-
return Result::INVALID_STATE;
}
Result TimeFilterClient::clearTimeStamp() {
- if (mTunerTimeFilter != NULL) {
+ if (mTunerTimeFilter != nullptr) {
Status s = mTunerTimeFilter->clearTimeStamp();
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mTimeFilter != NULL) {
- return mTimeFilter->clearTimeStamp();
- }
-
return Result::INVALID_STATE;
}
-long TimeFilterClient::getTimeStamp() {
- if (mTunerTimeFilter != NULL) {
+int64_t TimeFilterClient::getTimeStamp() {
+ if (mTunerTimeFilter != nullptr) {
int64_t timeStamp;
Status s = mTunerTimeFilter->getTimeStamp(&timeStamp);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ if (!s.isOk()) {
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
return timeStamp;
}
- if (mTimeFilter != NULL) {
- Result res;
- long timestamp;
- mTimeFilter->getTimeStamp(
- [&](Result r, uint64_t t) {
- res = r;
- timestamp = t;
- });
- if (res != Result::SUCCESS) {
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
- }
- return timestamp;
- }
-
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
-long TimeFilterClient::getSourceTime() {
- if (mTunerTimeFilter != NULL) {
+int64_t TimeFilterClient::getSourceTime() {
+ if (mTunerTimeFilter != nullptr) {
int64_t sourceTime;
Status s = mTunerTimeFilter->getTimeStamp(&sourceTime);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ if (!s.isOk()) {
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
return sourceTime;
}
- if (mTimeFilter != NULL) {
- Result res;
- long sourceTime;
- mTimeFilter->getSourceTime(
- [&](Result r, uint64_t t) {
- res = r;
- sourceTime = t;
- });
- if (res != Result::SUCCESS) {
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
- }
- return sourceTime;
- }
-
- return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+ return static_cast<int64_t>(Constant64Bit::INVALID_PRESENTATION_TIME_STAMP);
}
Result TimeFilterClient::close() {
- if (mTunerTimeFilter != NULL) {
+ if (mTunerTimeFilter != nullptr) {
Status s = mTunerTimeFilter->close();
- mTunerTimeFilter = NULL;
+ mTunerTimeFilter = nullptr;
return ClientHelper::getServiceSpecificErrorCode(s);
}
- if (mTimeFilter != NULL) {
- Result res = mTimeFilter->close();
- mTimeFilter = NULL;
- return res;
- }
-
return Result::INVALID_STATE;
}
} // namespace android
diff --git a/media/jni/tuner/TimeFilterClient.h b/media/jni/tuner/TimeFilterClient.h
index 56ddd68d363e..46f33beedd8d 100644
--- a/media/jni/tuner/TimeFilterClient.h
+++ b/media/jni/tuner/TimeFilterClient.h
@@ -17,18 +17,14 @@
#ifndef _ANDROID_MEDIA_TV_TIME_FILTER_CLIENT_H_
#define _ANDROID_MEDIA_TV_TIME_FILTER_CLIENT_H_
+#include <aidl/android/hardware/tv/tuner/Result.h>
#include <aidl/android/media/tv/tuner/ITunerTimeFilter.h>
-#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
-
-using ::aidl::android::media::tv::tuner::ITunerTimeFilter;
+#include <utils/RefBase.h>
using Status = ::ndk::ScopedAStatus;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
-using ::android::hardware::tv::tuner::V1_0::Result;
+
+using ::aidl::android::hardware::tv::tuner::Result;
+using ::aidl::android::media::tv::tuner::ITunerTimeFilter;
using namespace std;
@@ -40,13 +36,10 @@ public:
TimeFilterClient(shared_ptr<ITunerTimeFilter> tunerTimeFilter);
~TimeFilterClient();
- // TODO: remove after migration to Tuner Service is done.
- void setHidlTimeFilter(sp<ITimeFilter> timeFilter);
-
/**
* Set time stamp for time based filter.
*/
- Result setTimeStamp(long timeStamp);
+ Result setTimeStamp(int64_t timeStamp);
/**
* Clear the time stamp in the time filter.
@@ -56,12 +49,12 @@ public:
/**
* Get the current time in the time filter.
*/
- long getTimeStamp();
+ int64_t getTimeStamp();
/**
* Get the time from the beginning of current data source.
*/
- long getSourceTime();
+ int64_t getSourceTime();
/**
* Releases the Time Filter instance.
@@ -74,13 +67,6 @@ private:
* opens an TimeFilter. Default null when time filter is not opened.
*/
shared_ptr<ITunerTimeFilter> mTunerTimeFilter;
-
- /**
- * A TimeFilter HAL interface that is ready before migrating to the TunerTimeFilter.
- * This is a temprary interface before Tuner Framework migrates to use TunerService.
- * Default null when the HAL service does not exist.
- */
- sp<ITimeFilter> mTimeFilter;
};
} // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index e05dba629d7f..d19ee0d460ea 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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.
@@ -22,31 +22,20 @@
#include "TunerClient.h"
-using ::aidl::android::media::tv::tuner::TunerFrontendCapabilities;
-using ::aidl::android::media::tv::tuner::TunerFrontendDtmbCapabilities;
-using ::android::hardware::tv::tuner::V1_0::FrontendId;
-using ::android::hardware::tv::tuner::V1_0::FrontendStatusType;
-using ::android::hardware::tv::tuner::V1_0::FrontendType;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
+using ::aidl::android::hardware::tv::tuner::FrontendType;
namespace android {
-sp<ITuner> TunerClient::mTuner;
-sp<::android::hardware::tv::tuner::V1_1::ITuner> TunerClient::mTuner_1_1;
shared_ptr<ITunerService> TunerClient::mTunerService;
-int TunerClient::mTunerVersion;
+int32_t TunerClient::mTunerVersion;
/////////////// TunerClient ///////////////////////
TunerClient::TunerClient() {
- // Get HIDL Tuner in migration stage.
- getHidlTuner();
- if (mTuner != NULL) {
- updateTunerResources();
- }
- // Connect with Tuner Service.
::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
mTunerService = ITunerService::fromBinder(binder);
- if (mTunerService == NULL) {
+ if (mTunerService == nullptr) {
ALOGE("Failed to get tuner service");
} else {
mTunerService->getTunerHalVersion(&mTunerVersion);
@@ -54,575 +43,124 @@ TunerClient::TunerClient() {
}
TunerClient::~TunerClient() {
- mTuner = NULL;
- mTuner_1_1 = NULL;
mTunerVersion = 0;
- mTunerService = NULL;
+ mTunerService = nullptr;
}
-vector<FrontendId> TunerClient::getFrontendIds() {
- vector<FrontendId> ids;
+vector<int32_t> TunerClient::getFrontendIds() {
+ vector<int32_t> ids;
- if (mTunerService != NULL) {
- vector<int32_t> v;
- Status s = mTunerService->getFrontendIds(&v);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS || v.size() == 0) {
+ if (mTunerService != nullptr) {
+ Status s = mTunerService->getFrontendIds(&ids);
+ if (!s.isOk()) {
ids.clear();
- return ids;
- }
- for (int32_t id : v) {
- ids.push_back(static_cast<FrontendId>(id));
}
- return ids;
- }
-
- if (mTuner != NULL) {
- Result res;
- mTuner->getFrontendIds([&](Result r, const hardware::hidl_vec<FrontendId>& frontendIds) {
- res = r;
- ids = frontendIds;
- });
- if (res != Result::SUCCESS || ids.size() == 0) {
- ALOGW("Frontend ids not available");
- ids.clear();
- return ids;
- }
- return ids;
}
return ids;
}
-
-sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) {
- if (mTunerService != NULL) {
+sp<FrontendClient> TunerClient::openFrontend(int32_t frontendHandle) {
+ if (mTunerService != nullptr) {
shared_ptr<ITunerFrontend> tunerFrontend;
Status s = mTunerService->openFrontend(frontendHandle, &tunerFrontend);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS
- || tunerFrontend == NULL) {
- return NULL;
+ if (!s.isOk() || tunerFrontend == nullptr) {
+ return nullptr;
}
- int id;
+ int32_t id;
s = tunerFrontend->getFrontendId(&id);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ tunerFrontend->close();
+ return nullptr;
}
- TunerFrontendInfo aidlFrontendInfo;
- s = mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ FrontendInfo frontendInfo;
+ s = mTunerService->getFrontendInfo(id, &frontendInfo);
+ if (!s.isOk()) {
+ tunerFrontend->close();
+ return nullptr;
}
- return new FrontendClient(tunerFrontend, aidlFrontendInfo.type);
+ return new FrontendClient(tunerFrontend, frontendInfo.type);
}
- if (mTuner != NULL) {
- int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
- sp<IFrontend> hidlFrontend = openHidlFrontendById(id);
- if (hidlFrontend != NULL) {
- FrontendInfo hidlInfo;
- Result res = getHidlFrontendInfo(id, hidlInfo);
- if (res != Result::SUCCESS) {
- return NULL;
- }
- sp<FrontendClient> frontendClient = new FrontendClient(
- NULL, (int)hidlInfo.type);
- frontendClient->setHidlFrontend(hidlFrontend);
- frontendClient->setId(id);
- return frontendClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
-shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) {
- if (mTunerService != NULL) {
- TunerFrontendInfo aidlFrontendInfo;
+shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int32_t id) {
+ if (mTunerService != nullptr) {
+ FrontendInfo aidlFrontendInfo;
Status s = mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
- }
- return make_shared<FrontendInfo>(frontendInfoAidlToHidl(aidlFrontendInfo));
- }
-
- if (mTuner != NULL) {
- FrontendInfo hidlInfo;
- Result res = getHidlFrontendInfo(id, hidlInfo);
- if (res != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
- return make_shared<FrontendInfo>(hidlInfo);
+ return make_shared<FrontendInfo>(aidlFrontendInfo);
}
- return NULL;
+ return nullptr;
}
-shared_ptr<FrontendDtmbCapabilities> TunerClient::getFrontendDtmbCapabilities(int id) {
- if (mTunerService != NULL) {
- TunerFrontendDtmbCapabilities dtmbCaps;
- Status s = mTunerService->getFrontendDtmbCapabilities(id, &dtmbCaps);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
- }
- FrontendDtmbCapabilities hidlCaps{
- .transmissionModeCap = static_cast<uint32_t>(dtmbCaps.transmissionModeCap),
- .bandwidthCap = static_cast<uint32_t>(dtmbCaps.bandwidthCap),
- .modulationCap = static_cast<uint32_t>(dtmbCaps.modulationCap),
- .codeRateCap = static_cast<uint32_t>(dtmbCaps.codeRateCap),
- .guardIntervalCap = static_cast<uint32_t>(dtmbCaps.guardIntervalCap),
- .interleaveModeCap = static_cast<uint32_t>(dtmbCaps.interleaveModeCap),
- };
- return make_shared<FrontendDtmbCapabilities>(hidlCaps);
- }
-
- if (mTuner_1_1 != NULL) {
- Result result;
- FrontendDtmbCapabilities dtmbCaps;
- mTuner_1_1->getFrontendDtmbCapabilities(id,
- [&](Result r, const FrontendDtmbCapabilities& caps) {
- dtmbCaps = caps;
- result = r;
- });
- if (result == Result::SUCCESS) {
- return make_shared<FrontendDtmbCapabilities>(dtmbCaps);
- }
- }
-
- return NULL;
-}
-
-sp<DemuxClient> TunerClient::openDemux(int demuxHandle) {
- if (mTunerService != NULL) {
+sp<DemuxClient> TunerClient::openDemux(int32_t demuxHandle) {
+ if (mTunerService != nullptr) {
shared_ptr<ITunerDemux> tunerDemux;
Status s = mTunerService->openDemux(demuxHandle, &tunerDemux);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
return new DemuxClient(tunerDemux);
}
- if (mTuner != NULL) {
- sp<DemuxClient> demuxClient = new DemuxClient(NULL);
- int demuxId;
- sp<IDemux> hidlDemux = openHidlDemux(demuxId);
- if (hidlDemux != NULL) {
- demuxClient->setHidlDemux(hidlDemux);
- demuxClient->setId(demuxId);
- return demuxClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
shared_ptr<DemuxCapabilities> TunerClient::getDemuxCaps() {
- if (mTunerService != NULL) {
- TunerDemuxCapabilities aidlCaps;
+ if (mTunerService != nullptr) {
+ DemuxCapabilities aidlCaps;
Status s = mTunerService->getDemuxCaps(&aidlCaps);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
- return make_shared<DemuxCapabilities>(getHidlDemuxCaps(aidlCaps));
+ return make_shared<DemuxCapabilities>(aidlCaps);
}
- if (mTuner != NULL) {
- Result res;
- DemuxCapabilities caps;
- mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
- caps = demuxCaps;
- res = r;
- });
- if (res == Result::SUCCESS) {
- return make_shared<DemuxCapabilities>(caps);
- }
- }
-
- return NULL;
+ return nullptr;
}
-sp<DescramblerClient> TunerClient::openDescrambler(int descramblerHandle) {
- if (mTunerService != NULL) {
+sp<DescramblerClient> TunerClient::openDescrambler(int32_t descramblerHandle) {
+ if (mTunerService != nullptr) {
shared_ptr<ITunerDescrambler> tunerDescrambler;
Status s = mTunerService->openDescrambler(descramblerHandle, &tunerDescrambler);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
return new DescramblerClient(tunerDescrambler);
}
- if (mTuner != NULL) {
- sp<DescramblerClient> descramblerClient = new DescramblerClient(NULL);
- sp<IDescrambler> hidlDescrambler = openHidlDescrambler();
- if (hidlDescrambler != NULL) {
- descramblerClient->setHidlDescrambler(hidlDescrambler);
- return descramblerClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
-sp<LnbClient> TunerClient::openLnb(int lnbHandle) {
- if (mTunerService != NULL) {
+sp<LnbClient> TunerClient::openLnb(int32_t lnbHandle) {
+ if (mTunerService != nullptr) {
shared_ptr<ITunerLnb> tunerLnb;
Status s = mTunerService->openLnb(lnbHandle, &tunerLnb);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
return new LnbClient(tunerLnb);
}
- if (mTuner != NULL) {
- int id = getResourceIdFromHandle(lnbHandle, LNB);
- sp<LnbClient> lnbClient = new LnbClient(NULL);
- sp<ILnb> hidlLnb = openHidlLnbById(id);
- if (hidlLnb != NULL) {
- lnbClient->setHidlLnb(hidlLnb);
- lnbClient->setId(id);
- return lnbClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
sp<LnbClient> TunerClient::openLnbByName(string lnbName) {
- if (mTunerService != NULL) {
+ if (mTunerService != nullptr) {
shared_ptr<ITunerLnb> tunerLnb;
Status s = mTunerService->openLnbByName(lnbName, &tunerLnb);
- if (ClientHelper::getServiceSpecificErrorCode(s) != Result::SUCCESS) {
- return NULL;
+ if (!s.isOk()) {
+ return nullptr;
}
return new LnbClient(tunerLnb);
}
- if (mTuner != NULL) {
- sp<LnbClient> lnbClient = new LnbClient(NULL);
- LnbId id;
- sp<ILnb> hidlLnb = openHidlLnbByName(lnbName, id);
- if (hidlLnb != NULL) {
- lnbClient->setHidlLnb(hidlLnb);
- lnbClient->setId(id);
- return lnbClient;
- }
- }
-
- return NULL;
+ return nullptr;
}
-/////////////// TunerClient Helper Methods ///////////////////////
-
-void TunerClient::updateTunerResources() {
- if (mTuner == NULL) {
- return;
- }
-
- // Connect with Tuner Resource Manager.
- ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr"));
- mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
-
- updateFrontendResources();
- updateLnbResources();
- // TODO: update Demux, Descrambler.
-}
-
-// TODO: remove after migration to Tuner Service is done.
-void TunerClient::updateFrontendResources() {
- vector<FrontendId> ids = getFrontendIds();
- if (ids.size() == 0) {
- return;
- }
- vector<TunerFrontendInfo> infos;
- for (int i = 0; i < ids.size(); i++) {
- shared_ptr<FrontendInfo> frontendInfo = getFrontendInfo((int)ids[i]);
- if (frontendInfo == NULL) {
- continue;
- }
- TunerFrontendInfo tunerFrontendInfo{
- .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
- .type = static_cast<int>(frontendInfo->type),
- .exclusiveGroupId = static_cast<int>(frontendInfo->exclusiveGroupId),
- };
- infos.push_back(tunerFrontendInfo);
- }
- mTunerResourceManager->setFrontendInfoList(infos);
-}
-
-void TunerClient::updateLnbResources() {
- vector<int> handles = getLnbHandles();
- if (handles.size() == 0) {
- return;
- }
- mTunerResourceManager->setLnbInfoList(handles);
-}
-
-sp<ITuner> TunerClient::getHidlTuner() {
- if (mTuner == NULL) {
- mTunerVersion = TUNER_HAL_VERSION_UNKNOWN;
- mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
-
- if (mTuner_1_1 == NULL) {
- ALOGW("Failed to get tuner 1.1 service.");
- mTuner = ITuner::getService();
- if (mTuner == NULL) {
- ALOGW("Failed to get tuner 1.0 service.");
- } else {
- mTunerVersion = TUNER_HAL_VERSION_1_0;
- }
- } else {
- mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
- mTunerVersion = TUNER_HAL_VERSION_1_1;
- }
- }
- return mTuner;
-}
-
-sp<IFrontend> TunerClient::openHidlFrontendById(int id) {
- sp<IFrontend> fe;
- Result res;
- mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
- fe = frontend;
- res = r;
- });
- if (res != Result::SUCCESS || fe == nullptr) {
- ALOGE("Failed to open frontend");
- return NULL;
- }
- return fe;
-}
-
-Result TunerClient::getHidlFrontendInfo(int id, FrontendInfo& feInfo) {
- Result res;
- mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
- feInfo = info;
- res = r;
- });
- return res;
-}
-
-sp<IDemux> TunerClient::openHidlDemux(int& demuxId) {
- sp<IDemux> demux;
- Result res;
-
- mTuner->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
- demux = demuxSp;
- demuxId = id;
- res = result;
- });
- if (res != Result::SUCCESS || demux == nullptr) {
- ALOGE("Failed to open demux");
- return NULL;
- }
- return demux;
-}
-
-sp<ILnb> TunerClient::openHidlLnbById(int id) {
- sp<ILnb> lnb;
- Result res;
-
- mTuner->openLnbById(id, [&](Result r, const sp<ILnb>& lnbSp) {
- res = r;
- lnb = lnbSp;
- });
- if (res != Result::SUCCESS || lnb == nullptr) {
- ALOGE("Failed to open lnb by id");
- return NULL;
- }
- return lnb;
-}
-
-sp<ILnb> TunerClient::openHidlLnbByName(string name, LnbId& lnbId) {
- sp<ILnb> lnb;
- Result res;
-
- mTuner->openLnbByName(name, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
- res = r;
- lnb = lnbSp;
- lnbId = id;
- });
- if (res != Result::SUCCESS || lnb == nullptr) {
- ALOGE("Failed to open lnb by name");
- return NULL;
- }
- return lnb;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-vector<int> TunerClient::getLnbHandles() {
- vector<int> lnbHandles;
- if (mTuner != NULL) {
- Result res;
- vector<LnbId> lnbIds;
- mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
- lnbIds = ids;
- res = r;
- });
- if (res != Result::SUCCESS || lnbIds.size() == 0) {
- ALOGW("Lnb isn't available");
- } else {
- for (int i = 0; i < lnbIds.size(); i++) {
- lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
- }
- }
- }
-
- return lnbHandles;
-}
-
-sp<IDescrambler> TunerClient::openHidlDescrambler() {
- sp<IDescrambler> descrambler;
- Result res;
-
- mTuner->openDescrambler([&](Result r, const sp<IDescrambler>& descramblerSp) {
- res = r;
- descrambler = descramblerSp;
- });
-
- if (res != Result::SUCCESS || descrambler == NULL) {
- return NULL;
- }
-
- return descrambler;
-}
-
-DemuxCapabilities TunerClient::getHidlDemuxCaps(TunerDemuxCapabilities& aidlCaps) {
- DemuxCapabilities caps{
- .numDemux = (uint32_t)aidlCaps.numDemux,
- .numRecord = (uint32_t)aidlCaps.numRecord,
- .numPlayback = (uint32_t)aidlCaps.numPlayback,
- .numTsFilter = (uint32_t)aidlCaps.numTsFilter,
- .numSectionFilter = (uint32_t)aidlCaps.numSectionFilter,
- .numAudioFilter = (uint32_t)aidlCaps.numAudioFilter,
- .numVideoFilter = (uint32_t)aidlCaps.numVideoFilter,
- .numPesFilter = (uint32_t)aidlCaps.numPesFilter,
- .numPcrFilter = (uint32_t)aidlCaps.numPcrFilter,
- .numBytesInSectionFilter = (uint32_t)aidlCaps.numBytesInSectionFilter,
- .filterCaps = (uint32_t)aidlCaps.filterCaps,
- .bTimeFilter = aidlCaps.bTimeFilter,
- };
- caps.linkCaps.resize(aidlCaps.linkCaps.size());
- copy(aidlCaps.linkCaps.begin(), aidlCaps.linkCaps.end(), caps.linkCaps.begin());
- return caps;
-}
-
-FrontendInfo TunerClient::frontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo) {
- FrontendInfo hidlFrontendInfo {
- .type = static_cast<FrontendType>(aidlFrontendInfo.type),
- .minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
- .maxFrequency = static_cast<uint32_t>(aidlFrontendInfo.maxFrequency),
- .minSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.minSymbolRate),
- .maxSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.maxSymbolRate),
- .acquireRange = static_cast<uint32_t>(aidlFrontendInfo.acquireRange),
- .exclusiveGroupId = static_cast<uint32_t>(aidlFrontendInfo.exclusiveGroupId),
- };
-
- int size = aidlFrontendInfo.statusCaps.size();
- hidlFrontendInfo.statusCaps.resize(size);
- for (int i = 0; i < size; i++) {
- hidlFrontendInfo.statusCaps[i] =
- static_cast<FrontendStatusType>(aidlFrontendInfo.statusCaps[i]);
- }
-
- switch (aidlFrontendInfo.caps.getTag()) {
- case TunerFrontendCapabilities::analogCaps: {
- auto analog = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::analogCaps>();
- hidlFrontendInfo.frontendCaps.analogCaps({
- .typeCap = static_cast<uint32_t>(analog.typeCap),
- .sifStandardCap = static_cast<uint32_t>(analog.sifStandardCap),
- });
- break;
- }
- case TunerFrontendCapabilities::atscCaps: {
- auto atsc = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::atscCaps>();
- hidlFrontendInfo.frontendCaps.atscCaps({
- .modulationCap = static_cast<uint32_t>(atsc.modulationCap),
- });
- break;
- }
- case TunerFrontendCapabilities::atsc3Caps: {
- auto atsc3 = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::atsc3Caps>();
- hidlFrontendInfo.frontendCaps.atsc3Caps({
- .bandwidthCap = static_cast<uint32_t>(atsc3.bandwidthCap),
- .modulationCap = static_cast<uint32_t>(atsc3.modulationCap),
- .timeInterleaveModeCap = static_cast<uint32_t>(atsc3.timeInterleaveModeCap),
- .codeRateCap = static_cast<uint32_t>(atsc3.codeRateCap),
- .fecCap = static_cast<uint32_t>(atsc3.fecCap),
- .demodOutputFormatCap = static_cast<uint8_t>(atsc3.demodOutputFormatCap),
- });
- break;
- }
- case TunerFrontendCapabilities::cableCaps: {
- auto cable = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::cableCaps>();
- hidlFrontendInfo.frontendCaps.dvbcCaps({
- .modulationCap = static_cast<uint32_t>(cable.modulationCap),
- .fecCap = static_cast<uint64_t>(cable.codeRateCap),
- .annexCap = static_cast<uint8_t>(cable.annexCap),
- });
- break;
- }
- case TunerFrontendCapabilities::dvbsCaps: {
- auto dvbs = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::dvbsCaps>();
- hidlFrontendInfo.frontendCaps.dvbsCaps({
- .modulationCap = static_cast<int32_t>(dvbs.modulationCap),
- .innerfecCap = static_cast<uint64_t>(dvbs.codeRateCap),
- .standard = static_cast<uint8_t>(dvbs.standard),
- });
- break;
- }
- case TunerFrontendCapabilities::dvbtCaps: {
- auto dvbt = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::dvbtCaps>();
- hidlFrontendInfo.frontendCaps.dvbtCaps({
- .transmissionModeCap = static_cast<uint32_t>(dvbt.transmissionModeCap),
- .bandwidthCap = static_cast<uint32_t>(dvbt.bandwidthCap),
- .constellationCap = static_cast<uint32_t>(dvbt.constellationCap),
- .coderateCap = static_cast<uint32_t>(dvbt.codeRateCap),
- .hierarchyCap = static_cast<uint32_t>(dvbt.hierarchyCap),
- .guardIntervalCap = static_cast<uint32_t>(dvbt.guardIntervalCap),
- .isT2Supported = dvbt.isT2Supported,
- .isMisoSupported = dvbt.isMisoSupported,
- });
- break;
- }
- case TunerFrontendCapabilities::isdbsCaps: {
- auto isdbs = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::isdbsCaps>();
- hidlFrontendInfo.frontendCaps.isdbsCaps({
- .modulationCap = static_cast<uint32_t>(isdbs.modulationCap),
- .coderateCap = static_cast<uint32_t>(isdbs.codeRateCap),
- });
- break;
- }
- case TunerFrontendCapabilities::isdbs3Caps: {
- auto isdbs3 = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::isdbs3Caps>();
- hidlFrontendInfo.frontendCaps.isdbs3Caps({
- .modulationCap = static_cast<uint32_t>(isdbs3.modulationCap),
- .coderateCap = static_cast<uint32_t>(isdbs3.codeRateCap),
- });
- break;
- }
- case TunerFrontendCapabilities::isdbtCaps: {
- auto isdbt = aidlFrontendInfo.caps.get<TunerFrontendCapabilities::isdbtCaps>();
- hidlFrontendInfo.frontendCaps.isdbtCaps({
- .modeCap = static_cast<uint32_t>(isdbt.modeCap),
- .bandwidthCap = static_cast<uint32_t>(isdbt.bandwidthCap),
- .modulationCap = static_cast<uint32_t>(isdbt.modulationCap),
- .coderateCap = static_cast<uint32_t>(isdbt.codeRateCap),
- .guardIntervalCap = static_cast<uint32_t>(isdbt.guardIntervalCap),
- });
- break;
- }
- }
- return hidlFrontendInfo;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-int TunerClient::getResourceIdFromHandle(int handle, int /*resourceType*/) {
- return (handle & 0x00ff0000) >> 16;
-}
-
-// TODO: remove after migration to Tuner Service is done.
-int TunerClient::getResourceHandleFromId(int id, int resourceType) {
- return (resourceType & 0x000000ff) << 24
- | (id << 16)
- | (mResourceRequestCount++ & 0xffff);
-}
} // namespace android
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 9671cf787e3e..641f106d6dff 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 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,12 +17,8 @@
#ifndef _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
#define _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
-#include <aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.h>
#include <aidl/android/media/tv/tuner/ITunerService.h>
-#include <aidl/android/media/tv/tuner/TunerFrontendInfo.h>
#include <android/binder_parcel_utils.h>
-#include <android/hardware/tv/tuner/1.1/ITuner.h>
-#include <android/hardware/tv/tuner/1.1/types.h>
#include "DemuxClient.h"
#include "ClientHelper.h"
@@ -32,32 +28,19 @@
using Status = ::ndk::ScopedAStatus;
-using ::aidl::android::media::tv::tuner::TunerDemuxCapabilities;
+using ::aidl::android::hardware::tv::tuner::DemuxCapabilities;
+using ::aidl::android::hardware::tv::tuner::FrontendInfo;
+using ::aidl::android::hardware::tv::tuner::Result;
using ::aidl::android::media::tv::tuner::ITunerService;
-using ::aidl::android::media::tv::tuner::TunerFrontendInfo;
-using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager;
-
-using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
-using ::android::hardware::tv::tuner::V1_0::FrontendId;
-using ::android::hardware::tv::tuner::V1_0::ITuner;
-using ::android::hardware::tv::tuner::V1_0::LnbId;
-using ::android::hardware::tv::tuner::V1_0::Result;
-using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
using namespace std;
namespace android {
-const static int TUNER_HAL_VERSION_UNKNOWN = 0;
-const static int TUNER_HAL_VERSION_1_0 = 1 << 16;
-const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
-
-typedef enum {
- FRONTEND,
- LNB,
- DEMUX,
- DESCRAMBLER,
-} TunerResourceType;
+const static int32_t TUNER_HAL_VERSION_UNKNOWN = 0;
+const static int32_t TUNER_HAL_VERSION_1_0 = 1 << 16;
+const static int32_t TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
+const static int32_t TUNER_HAL_VERSION_2_0 = 2 << 16;
struct TunerClient : public RefBase {
@@ -70,7 +53,7 @@ public:
*
* @return a list of the available frontend ids
*/
- vector<FrontendId> getFrontendIds();
+ vector<int32_t> getFrontendIds();
/**
* Open a new interface of FrontendClient given a frontendHandle.
@@ -78,7 +61,7 @@ public:
* @param frontendHandle the handle of the frontend granted by TRM.
* @return a newly created FrontendClient interface.
*/
- sp<FrontendClient> openFrontend(int frontendHandle);
+ sp<FrontendClient> openFrontend(int32_t frontendHandle);
/**
* Retrieve the granted frontend's information.
@@ -86,15 +69,7 @@ public:
* @param id the id of the frontend granted by TRM.
* @return the information for the frontend.
*/
- shared_ptr<FrontendInfo> getFrontendInfo(int id);
-
- /**
- * Retrieve the DTMB frontend's capabilities.
- *
- * @param id the id of the DTMB frontend.
- * @return the capabilities of the frontend.
- */
- shared_ptr<FrontendDtmbCapabilities> getFrontendDtmbCapabilities(int id);
+ shared_ptr<FrontendInfo> getFrontendInfo(int32_t id);
/**
* Open a new interface of DemuxClient given a demuxHandle.
@@ -102,7 +77,7 @@ public:
* @param demuxHandle the handle of the demux granted by TRM.
* @return a newly created DemuxClient interface.
*/
- sp<DemuxClient> openDemux(int demuxHandle);
+ sp<DemuxClient> openDemux(int32_t demuxHandle);
/**
* Retrieve the Demux capabilities.
@@ -117,7 +92,7 @@ public:
* @param descramblerHandle the handle of the descrambler granted by TRM.
* @return a newly created DescramblerClient interface.
*/
- sp<DescramblerClient> openDescrambler(int descramblerHandle);
+ sp<DescramblerClient> openDescrambler(int32_t descramblerHandle);
/**
* Open a new interface of LnbClient given an lnbHandle.
@@ -125,7 +100,7 @@ public:
* @param lnbHandle the handle of the LNB granted by TRM.
* @return a newly created LnbClient interface.
*/
- sp<LnbClient> openLnb(int lnbHandle);
+ sp<LnbClient> openLnb(int32_t lnbHandle);
/**
* Open a new interface of LnbClient given a LNB name.
@@ -139,54 +114,18 @@ public:
* Get the current Tuner HAL version. The high 16 bits are the major version number
* while the low 16 bits are the minor version. Default value is unknown version 0.
*/
- int getHalTunerVersion() { return mTunerVersion; }
+ int32_t getHalTunerVersion() { return mTunerVersion; }
private:
- sp<ITuner> getHidlTuner();
- sp<IFrontend> openHidlFrontendById(int id);
- sp<IDemux> openHidlDemux(int& demuxId);
- Result getHidlFrontendInfo(int id, FrontendInfo& info);
- sp<ILnb> openHidlLnbById(int id);
- sp<ILnb> openHidlLnbByName(string name, LnbId& lnbId);
- sp<IDescrambler> openHidlDescrambler();
- vector<int> getLnbHandles();
- DemuxCapabilities getHidlDemuxCaps(TunerDemuxCapabilities& aidlCaps);
- FrontendInfo frontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo);
- void updateTunerResources();
- void updateFrontendResources();
- void updateLnbResources();
-
- int getResourceIdFromHandle(int handle, int resourceType);
-
- int getResourceHandleFromId(int id, int resourceType);
-
/**
* An AIDL Tuner Service Singleton assigned at the first time the Tuner Client
* connects with the Tuner Service. Default null when the service does not exist.
*/
static shared_ptr<ITunerService> mTunerService;
- /**
- * A Tuner 1.0 HAL interface that is ready before connecting to the TunerService
- * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
- * Default null.
- */
- static sp<ITuner> mTuner;
-
- /**
- * A Tuner 1.1 HAL interface that is ready before connecting to the TunerService
- * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
- * Default null.
- */
- static sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
-
// An integer that carries the Tuner version. The high 16 bits are the major version number
// while the low 16 bits are the minor version. Default value is unknown version 0.
- static int mTunerVersion;
-
- shared_ptr<ITunerResourceManager> mTunerResourceManager;
-
- int mResourceRequestCount = 0;
+ static int32_t mTunerVersion;
};
} // namespace android
diff --git a/mms/OWNERS b/mms/OWNERS
index befc320b949c..7f05a2a24d6e 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -2,7 +2,6 @@ set noparent
tgunn@google.com
breadley@google.com
-hallliu@google.com
rgreenwalt@google.com
amitmahajan@google.com
fionaxu@google.com
@@ -10,7 +9,10 @@ jackyu@google.com
jminjie@google.com
satk@google.com
shuoq@google.com
-refuhoo@google.com
nazaninb@google.com
sarahchin@google.com
-dbright@google.com \ No newline at end of file
+xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 56688409bf78..0d23f053499c 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -1,7 +1,6 @@
set noparent
tgunn@google.com
breadley@google.com
-hallliu@google.com
rgreenwalt@google.com
amitmahajan@google.com
fionaxu@google.com
@@ -9,9 +8,11 @@ jackyu@google.com
jminjie@google.com
satk@google.com
shuoq@google.com
-refuhoo@google.com
nazaninb@google.com
sarahchin@google.com
-dbright@google.com
xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b4d520d7d71a..1bc498342d24 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -33,6 +33,10 @@
<intent-filter>
<action android:name="android.os.image.action.START_INSTALL" />
<category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="content" />
+ <data android:scheme="file" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
</intent-filter>
</activity>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index 8951e0def1cb..11e01c7ce51d 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -83,10 +83,10 @@
<string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ టాబ్లెట్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్‌లలో మార్చవచ్చు."</string>
<string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ టీవీ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్‌లలో మార్చవచ్చు."</string>
<string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ ఫోన్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్‌లలో మార్చవచ్చు."</string>
- <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"తెలియని యాప్‌లు మీ ఫోన్ పైన, వ్యక్తిగత డేటా పైన దాడి చేయడానికి ఎక్కువగా అవకాశం ఉంటుంది. ఈ యాప్ను ఇన్‌స్టాల్ చేయడం ద్వారా, దాని వినియోగంతో మీ ఫోన్‌కు ఏదైనా నష్టం జరిగితే లేదా మీ డేటాను కోల్పోతే అందుకు మీరే బాధ్యత వహిస్తారని అంగీకరిస్తున్నారు."</string>
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"తెలియని యాప్‌లు మీ ఫోన్ పైన, వ్యక్తిగత డేటా పైన దాడి చేయడానికి ఎక్కువగా అవకాశం ఉంటుంది. ఈ యాప్‌ను ఇన్‌స్టాల్ చేయడం ద్వారా, దాని వినియోగంతో మీ ఫోన్‌కు ఏదైనా నష్టం జరిగితే లేదా మీ డేటాను కోల్పోతే అందుకు మీరే బాధ్యత వహిస్తారని అంగీకరిస్తున్నారు."</string>
<string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"మీ టాబ్లెట్ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్‌లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టాబ్లెట్‌కు ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string>
<string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"మీ టీవీ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్‌లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టీవీకి ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string>
- <string name="anonymous_source_continue" msgid="4375745439457209366">"కొనసాగించు"</string>
+ <string name="anonymous_source_continue" msgid="4375745439457209366">"కొనసాగండి"</string>
<string name="external_sources_settings" msgid="4046964413071713807">"సెట్టింగ్‌లు"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"Wear యాప్‌లను ఇన్‌స్టాల్/అన్‌ఇన్‌స్టాల్ చేస్తోంది"</string>
<string name="app_installed_notification_channel_description" msgid="2695385797601574123">"యాప్ ఇన్‌స్టాల్ చేయబడిందనే నోటిఫికేషన్"</string>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-af/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-af/strings.xml
new file mode 100644
index 000000000000..0a4288c771a8
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-af/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Instellings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-am/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-am/strings.xml
new file mode 100644
index 000000000000..f8db6d877fa6
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-am/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ቅንብሮች"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ar/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ar/strings.xml
new file mode 100644
index 000000000000..778715cd21cc
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ar/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"الإعدادات"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-as/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-as/strings.xml
new file mode 100644
index 000000000000..21be4ade3906
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ছেটিং"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
new file mode 100644
index 000000000000..064f14ae6746
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-az/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ayarlar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 000000000000..d51823f3c74e
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Podešavanja"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-be/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-be/strings.xml
new file mode 100644
index 000000000000..e6c513ec5710
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-be/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Налады"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
new file mode 100644
index 000000000000..df46ee73c9fb
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bg/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Настройки"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bn/strings.xml
new file mode 100644
index 000000000000..31eb432685de
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"সেটিংস"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
new file mode 100644
index 000000000000..442217ac3e47
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-bs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ca/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ca/strings.xml
new file mode 100644
index 000000000000..5077025ec637
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ca/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configuració"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-cs/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-cs/strings.xml
new file mode 100644
index 000000000000..96d9019403a4
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-cs/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Nastavení"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-da/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-da/strings.xml
new file mode 100644
index 000000000000..fa2b17e41572
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-da/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Indstillinger"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-de/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-de/strings.xml
new file mode 100644
index 000000000000..bbc309c791f8
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-de/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Einstellungen"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-el/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-el/strings.xml
new file mode 100644
index 000000000000..b7b732612c82
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-el/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ρυθμίσεις"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
new file mode 100644
index 000000000000..b048293434f3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rAU/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
new file mode 100644
index 000000000000..b048293434f3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
new file mode 100644
index 000000000000..b048293434f3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rGB/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
new file mode 100644
index 000000000000..b048293434f3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rIN/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Settings"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
new file mode 100644
index 000000000000..d5c868b2dbf6
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-en-rXC/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎Settings‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es-rUS/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es-rUS/strings.xml
new file mode 100644
index 000000000000..7146861a8419
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configuración"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
new file mode 100644
index 000000000000..64dddc9cf9c5
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-es/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ajustes"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-et/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-et/strings.xml
new file mode 100644
index 000000000000..b9c0e6fac355
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-et/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Seaded"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-eu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-eu/strings.xml
new file mode 100644
index 000000000000..1033ce2526d0
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-eu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ezarpenak"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
new file mode 100644
index 000000000000..76a8bd781970
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fa/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"تنظیمات"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fi/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fi/strings.xml
new file mode 100644
index 000000000000..6c0caaa3267f
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Asetukset"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr-rCA/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr-rCA/strings.xml
new file mode 100644
index 000000000000..c894348b1808
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr-rCA/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Paramètres"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr/strings.xml
new file mode 100644
index 000000000000..c894348b1808
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-fr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Paramètres"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gl/strings.xml
new file mode 100644
index 000000000000..7146861a8419
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configuración"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gu/strings.xml
new file mode 100644
index 000000000000..7ae0ea2983da
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-gu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"સેટિંગ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hi/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hi/strings.xml
new file mode 100644
index 000000000000..f38a00fb29e5
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"सेटिंग"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
new file mode 100644
index 000000000000..442217ac3e47
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Postavke"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
new file mode 100644
index 000000000000..bdab37285e2d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Beállítások"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
new file mode 100644
index 000000000000..d91474ac39ba
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-hy/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Կարգավորումներ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-in/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-in/strings.xml
new file mode 100644
index 000000000000..ceb5aa7d5e9f
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-in/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Setelan"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-is/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-is/strings.xml
new file mode 100644
index 000000000000..bd3d86360a70
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-is/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Stillingar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
new file mode 100644
index 000000000000..1c0204d0e837
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-it/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Impostazioni"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
new file mode 100644
index 000000000000..28ff3e72addf
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-iw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"הגדרות"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
new file mode 100644
index 000000000000..b8acb7b6ecee
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ja/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
new file mode 100644
index 000000000000..671fc1c5f1ae
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ka/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"პარამეტრები"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
new file mode 100644
index 000000000000..bcd6784bc8f8
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Параметрлер"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
new file mode 100644
index 000000000000..df2c7d0fca22
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-km/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ការកំណត់"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kn/strings.xml
new file mode 100644
index 000000000000..aab8bedcda1b
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-kn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
new file mode 100644
index 000000000000..8a543188e201
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ko/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"설정"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
new file mode 100644
index 000000000000..f4a893a1cd83
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Жөндөөлөр"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
new file mode 100644
index 000000000000..2a91bc3d199e
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lo/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ການຕັ້ງຄ່າ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lt/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lt/strings.xml
new file mode 100644
index 000000000000..e452cbb03b43
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Nustatymai"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lv/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lv/strings.xml
new file mode 100644
index 000000000000..e8bb10295922
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-lv/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Iestatījumi"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mk/strings.xml
new file mode 100644
index 000000000000..6031e9fdd420
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Поставки"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ml/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ml/strings.xml
new file mode 100644
index 000000000000..cb613a12bb0e
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ml/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ക്രമീകരണം"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
new file mode 100644
index 000000000000..194aa028669c
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Тохиргоо"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mr/strings.xml
new file mode 100644
index 000000000000..f2f027adeccd
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-mr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"सेटिंग्ज"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ms/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ms/strings.xml
new file mode 100644
index 000000000000..51c2f196aaf7
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ms/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Tetapan"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-my/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-my/strings.xml
new file mode 100644
index 000000000000..a29153bf5638
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-my/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ဆက်တင်များ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nb/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nb/strings.xml
new file mode 100644
index 000000000000..fdfdecd36144
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nb/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Innstillinger"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ne/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ne/strings.xml
new file mode 100644
index 000000000000..e1a5b1b8eb49
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ne/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"सेटिङ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
new file mode 100644
index 000000000000..9a7365d10468
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-nl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Instellingen"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml
new file mode 100644
index 000000000000..8b211e790017
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ସେଟିଂସ୍"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pa/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pa/strings.xml
new file mode 100644
index 000000000000..23b79a1a7587
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pa/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ਸੈਟਿੰਗਾਂ"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pl/strings.xml
new file mode 100644
index 000000000000..45c6e985f1a4
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ustawienia"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
new file mode 100644
index 000000000000..87dbe7d9af9e
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rBR/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
new file mode 100644
index 000000000000..5ac727828221
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt-rPT/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Definições"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
new file mode 100644
index 000000000000..87dbe7d9af9e
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-pt/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Configurações"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ro/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ro/strings.xml
new file mode 100644
index 000000000000..7d20417f3085
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ro/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Setări"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ru/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ru/strings.xml
new file mode 100644
index 000000000000..df46ee73c9fb
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ru/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Настройки"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
new file mode 100644
index 000000000000..10f8475f9ac8
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-si/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"සැකසීම්"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sk/strings.xml
new file mode 100644
index 000000000000..51b5bea1ad3c
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Nastavenia"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
new file mode 100644
index 000000000000..41b33fe761ef
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Nastavitve"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sq/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sq/strings.xml
new file mode 100644
index 000000000000..8c0c32230399
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sq/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Cilësimet"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
new file mode 100644
index 000000000000..1478a00e110d
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Подешавања"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
new file mode 100644
index 000000000000..ef5420619a8a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sv/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Inställningar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
new file mode 100644
index 000000000000..d5dbf19b252c
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-sw/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Mipangilio"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ta/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ta/strings.xml
new file mode 100644
index 000000000000..f9294292e589
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ta/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"அமைப்புகள்"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-te/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-te/strings.xml
new file mode 100644
index 000000000000..154c9ac7ea86
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-te/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"సెట్టింగ్‌లు"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-th/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-th/strings.xml
new file mode 100644
index 000000000000..8e7218dac66a
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-th/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"การตั้งค่า"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
new file mode 100644
index 000000000000..f923a180ed86
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tl/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Mga Setting"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tr/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tr/strings.xml
new file mode 100644
index 000000000000..064f14ae6746
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-tr/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Ayarlar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
new file mode 100644
index 000000000000..8f03a19ecc52
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uk/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Налаштування"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ur/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ur/strings.xml
new file mode 100644
index 000000000000..24e76a647001
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ur/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"ترتیبات"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
new file mode 100644
index 000000000000..e8fb658b8104
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-uz/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Sozlamalar"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
new file mode 100644
index 000000000000..ab7136b06f02
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-vi/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Cài đặt"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rCN/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rCN/strings.xml
new file mode 100644
index 000000000000..9c74a49eb767
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rCN/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"设置"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
new file mode 100644
index 000000000000..b8acb7b6ecee
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rHK/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
new file mode 100644
index 000000000000..b8acb7b6ecee
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zh-rTW/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"設定"</string>
+</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
new file mode 100644
index 000000000000..bb87ec28ebe3
--- /dev/null
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-zu/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="settings_label" msgid="5948970810295631236">"Amasethingi"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 24d9873f20a4..976f0b0ddf90 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -511,7 +511,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"السماح بضبط المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"عليك السماح لهذا التطبيق بضبط المنبّهات وتحديد مواعيد للإجراءات الحساسة زمنيًا. يسمح هذا الأذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من شحن البطارية.\n\nإذا كان هذا الإذن غير مسموح به، لن تعمل الأحداث المستندة إلى وقت والمنبّهات الحالية التي يحدِّد هذا التطبيق موعدها."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات لتنفيذها في الوقت المناسب. ويسمح هذا الإذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من البطارية.\n\nفي حال عدم تفعيل هذا الإذن، لن تعمل المنبهات الحالية والأحداث المستندة إلى الوقت المضبوطة في هذا التطبيق."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"جدول زمني، جدولة، منبّه، تذكير، ساعة"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"تفعيل"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"تفعيل ميزة \"عدم الإزعاج\""</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 0fd9ae592c05..5c9a3e048b91 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"ওয়াই-ফাই ভারবোস লগিং চালু করুন"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"ওয়াই-ফাই স্ক্যান থ্রোটলিং"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"অল্প সময় ওয়াই-ফাই নেটওয়ার্কে যুক্ত থাকে এমন MAC অ্যাড্রেসের র‍্যান্ডমাইজেশন"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"নামহীন ব্লুটুথ ডিভাইসগুলি দেখুন"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ব্যাটারির খরচ কমায় এবং নেটওয়ার্কের পারফর্ম্যান্স উন্নত করে"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"এই মোডটি চালু থাকলে, MAC অ্যাড্রেসের র‍্যান্ডমাইজেশনের সুবিধা চালু আছে এমন কোনও নেটওয়ার্কে প্রত্যেকবার কানেক্ট করার সময় ডিভাইসের MAC অ্যাড্রেস পরিবর্তিত হতে পারে।"</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"মিটার্ড"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"পরিমাপ করা নয়"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"লগার বাফারের আকারগুলি"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 27fbf44b1de9..ae5ffa092bd1 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -426,7 +426,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajusta cómo se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieres:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt; Ver colores con más exactitud&lt;/li&gt; &lt;li&gt; Quitar colores para tener un enfoque más claro&lt;/li&gt; &lt;/ol&gt;"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Ajusta cómo se muestran los colores en tu dispositivo. Esto puede ser útil cuando quieres:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Ver colores con más exactitud&lt;/li&gt; &lt;li&gt;&amp;nbsp;Quitar colores para tener un enfoque más claro&lt;/li&gt; &lt;/ol&gt;"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 0ede2488dfaf..15c50e11ac01 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -507,7 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmid ja meeldetuletused"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Luba alarmide ja meeldetuletuste määramine"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmid ja meeldetuletused"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lubage sellel rakendusel määrata alarme ja ajastada kiire tähtajaga toiminguid. See võimaldab rakendusel töötada taustal, mistõttu võib akukasutus olla suurem.\n\nKui see luba on välja lülitatud, siis olemasolevad alarmid ja selle rakenduse ajastatud ajapõhised sündmused ei tööta."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lubage sellel rakendusel määrata alarme ja ajastada ajakriitilisi toiminguid. See võimaldab rakendusel töötada taustal, mistõttu võib akukasutus olla suurem.\n\nKui see luba on välja lülitatud, siis olemasolevad alarmid ja selle rakenduse ajastatud ajapõhised sündmused ei tööta."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajakava, äratus, meeldetuletus, kell"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Lülita sisse"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Valiku Mitte segada sisselülitamine"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 3abd21100131..a225b741c4be 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -284,7 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"Afficher les options pour la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Détailler les infos Wi-Fi, afficher par RSSI de SSID dans l\'outil de sélection Wi-Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Réduit la décharge de la batterie et améliore les performances du réseau"</string>
- <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau Wi-Fi où le changement aléatoire d\'adresse MAC est activé."</string>
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quand ce mode est activé, l\'adresse MAC de cet appareil peut changer chaque fois qu\'il se connecte à un réseau où le changement aléatoire d\'adresse MAC est activé."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Facturé à l\'usage"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Non facturé à l\'usage"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"Tailles des tampons de l\'enregistreur"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 9fc70cf5cb33..eedadc93116b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ ચાલુ કરો"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"વાઇ-ફાઇ સ્કૅનની ક્ષમતા મર્યાદિત કરવી"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"વાઇ-ફાઇ માટે સતત બદલાતું MAC રેન્ડમાઇઝેશન"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"નામ વિનાના બ્લૂટૂથ ડિવાઇસ બતાવો"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"બૅટરીનો ચાર્જ ઝડપથી ઓછો થવાનું ટાળે છે અને નેટવર્કના કાર્યપ્રદર્શનમાં સુધારો કરે છે"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"આ મોડ ચાલુ કરેલો હોય ત્યારે MAC રેન્ડમાઇઝેશન ચાલુ કરેલું હોય તેવા નેટવર્ક સાથે આ ડિવાઇસ કનેક્ટ થશે, ત્યારે દર વખતે તેનું MAC ઍડ્રેસ બદલાય તેવું બની શકે છે."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"મીટર કરેલું"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"મીટર ન કરેલ"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"લોગર બફર કદ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index c065f9add4f3..3e0791e64b74 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -527,7 +527,7 @@
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
<string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string>
- <string name="storage_category" msgid="2287342585424631813">"डिवाइस की मेमोरी"</string>
+ <string name="storage_category" msgid="2287342585424631813">"डिवाइस का स्टोरेज"</string>
<string name="shared_data_title" msgid="1017034836800864953">"शेयर किया गया डेटा"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"शेयर किए गए डेटा को देखें और उसमें बदलाव करें"</string>
<string name="shared_data_no_blobs_text" msgid="3108114670341737434">"इस उपयोगकर्ता के साथ किसी तरह का डेटा शेयर नहीं किया गया है."</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 3480411a346b..37d0db3cb215 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -507,7 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarm dan pengingat"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Izinkan menyetel alarm dan pengingat"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm &amp; pengingat"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan berjangka waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berjangka waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Izinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index fba3aebcefc7..310f9f9f51f3 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -252,7 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"‏אישור של תצוגת Wi-Fi"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"‏הפעלת רישום מפורט של Wi‑Fi ביומן"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"‏ויסות סריקה לנקודות Wi-Fi"</string>
- <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"‏רנדומיזציה של כתובות MAC בלי חיבור יציב ל-Wi-Fi"</string>
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"‏רנדומיזציה של כתובות MAC משתנות ברשתות Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"חבילת הגלישה פעילה תמיד"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"‏הצגת מכשירי Bluetooth ללא שמות"</string>
@@ -426,7 +426,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"פרוטנומליה (אדום-ירוק)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"טריטנומליה (כחול-צהוב)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"תיקון צבע"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"‏ניתן לשנות את האופן שבו צבעים מוצגים במכשיר. שינוי כזה עשוי לעזור:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt; להבחין בצבעים בצורה יותר מדויקת&lt;/li&gt; &lt;li&gt; להסיר צבעים מסוימים כדי להתמקד&lt;/li&gt; &lt;/ol&gt;"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"‏ניתן לשנות את האופן שבו צבעים מוצגים במכשיר. שינוי כזה עשוי לעזור:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;להבחין בצבעים בצורה יותר מדויקת&lt;/li&gt; &lt;li&gt;&amp;nbsp;להסיר צבעים מסוימים כדי להתמקד&lt;/li&gt; &lt;/ol&gt;"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 99fd1d396989..3af87284e532 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"ವೈರ್‌ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"ವೈ-ಫೈ ಸ್ಕ್ಯಾನ್ ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತಿದೆ"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"ವೈ-ಫೈ ನಿರಂತರವಲ್ಲದ MAC ಯಾದೃಚ್ಛಿಕರಣ"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"ಟೆಥರಿಂಗ್‍‍ಗಾಗಿ ಹಾರ್ಡ್‍ವೇರ್ ವೇಗವರ್ಧನೆ"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"ಹೆಸರುಗಳಿಲ್ಲದ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ತೋರಿಸಿ"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"ವೈರ್‌ಲೆಸ್‌‌‌ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ಬ್ಯಾಟರಿ ಹೆಚ್ಚು ಬಾಳಿಕೆ ಬರುವಂತೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನೆಟ್‌ವರ್ಕ್‌ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಸುಧಾರಿಸುತ್ತದೆ"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ಈ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, MAC ಯಾದೃಚ್ಛಿಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ ಈ ಸಾಧನದ MAC ವಿಳಾಸವು ಪ್ರತಿ ಬಾರಿಯೂ ಬದಲಾಗಬಹುದು."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"ಮೀಟರ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"ಮೀಟರ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 074b86473683..34ac3d135643 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -426,7 +426,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулах"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Таны төхөөрөмж дээр өнгийг хэрхэн үзүүлэхийг тохируулна уу. Энэ нь танд дараахыг хийхийг хүссэн үед хэрэг болж магадгүй:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;Өнгийг илүү оновчтой харах&lt;/li&gt; &lt;li&gt;Танд төвлөрөхөд туслахын тулд өнгийг хасах&lt;/li&gt; &lt;/ol&gt;"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"Таны төхөөрөмж дээр өнгийг хэрхэн үзүүлэхийг тохируулна уу. Энэ нь танд дараахыг хийхийг хүссэн үед хэрэг болж магадгүй:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;Өнгийг илүү оновчтой харах&lt;/li&gt; &lt;li&gt;&amp;nbsp;Танд төвлөрөхөд туслахын тулд өнгийг хасах&lt;/li&gt; &lt;/ol&gt;"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0b0a4a6b1fc7..95e6f635ea19 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"वाय-फाय व्हर्बोझ लॉगिंग सुरू करा"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"वाय-फाय स्कॅन थ्रॉटलिंग"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"वाय-फायचे सातत्याने न होणारे MAC रँडमायझेशन"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा नेहमी सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"टेदरिंग हार्डवेअर अ‍ॅक्सिलरेशन"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"नावांशिवाय ब्‍लूटूथ डिव्‍हाइस दाखवा"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाय-फाय लॉगिंग स्‍तर वाढवा, वाय-फाय सिलेक्टरमध्‍ये प्रति SSID RSSI दर्शवा"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"बॅटरी जलदरीतीने संपण्यापासून रोखते आणि नेटवर्क परफॉर्मन्समध्ये सुधारणा करते"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"हा मोड सुरू केलेला असले तेव्हा, हे डिव्हाइस MAC रँडमायझेशन सुरू केलेल्या नेटवर्कशी कनेक्ट होताना प्रत्येक वेळी त्याचा MAC अ‍ॅड्रेस बदलू शकतो."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"मीटरने मोजलेले"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"मीटरने न मोजलेले"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफर आकार"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b004082f2495..dc42136fa81f 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -252,8 +252,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"Certifikimi i ekranit pa tel"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivizo hyrjen Wi-Fi Verbose"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Përshpejtimi i skanimit të Wi‑Fi"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization (7482769677894247316) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Renditje e rastësishme jo e përhershme e MAC për Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Të dhënat celulare gjithmonë aktive"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Përshpejtimi i harduerit për ndarjen e lidhjes (internet)"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Shfaq pajisjet me Bluetooth pa emra"</string>
@@ -285,8 +284,7 @@
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"Shfaq opsionet për certifikimin e ekranit pa tel"</string>
<string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
<string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Zvogëlon shkarkimin e baterisë dhe përmirëson cilësinë e funksionimit të rrjetit"</string>
- <!-- no translation found for wifi_non_persistent_mac_randomization_summary (2159794543105053930) -->
- <skip />
+ <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Kur ky modalitet është i aktivizuar, adresa MAC e kësaj pajisjeje mund të ndryshojë çdo herë që lidhet me një rrjet që ka të aktivizuar renditjen e rastësishme të adresave MAC."</string>
<string name="wifi_metered_label" msgid="8737187690304098638">"Me matje"</string>
<string name="wifi_unmetered_label" msgid="6174142840934095093">"Pa matje"</string>
<string name="select_logd_size_title" msgid="1604578195914595173">"Madhësitë e regjistruesit"</string>
@@ -509,7 +507,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmet dhe alarmet rikujtuese"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Lejo caktimin e alarmeve dhe alarmeve rikujtuese"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmet dhe alarmet rikujtuese"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lejo që ky aplikacion të caktojë alarmet dhe të planifikojë veprime që kanë një afat të caktuar. Kjo lejon që aplikacioni të ekzekutohet në sfond, gjë që mund të përdorë më shumë bateri.\n\nNëse kjo leje është caktuar si joaktive, alarmet ekzistuese dhe ngjarjet me bazë kohore të planifikuara nga ky apliikacion nuk do të funksionojnë."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lejo që ky aplikacion të caktojë alarmet dhe të planifikojë veprime që kanë një afat të caktuar. Kjo mundëson që aplikacioni të ekzekutohet në sfond, gjë që mund të përdorë më shumë bateri.\n\nNëse kjo leje është caktuar si joaktive, alarmet ekzistuese dhe ngjarjet në bazë kohore të planifikuara nga ky aplikacion nuk do të funksionojnë."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planifiko, alarm, alarm rikujtues, ora"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivizo"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivizo \"Mos shqetëso\""</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 2f25722a7c32..2fc34d561022 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -98,7 +98,7 @@
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"செவித்துணை கருவிகளுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
- <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"கோப்பைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
+ <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"ஃபைலைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"வரைபடத்துடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"SAP உடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"கோப்பு இடமாற்றும் சேவையகத்துடன் இணைக்கப்படவில்லை"</string>
@@ -426,7 +426,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"நிறம் அடையாளங்காண முடியாமை (சிவப்பு-பச்சை)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"நிறம் அடையாளங்காண முடியாமை (நீலம்-மஞ்சள்)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"வண்ணத்திருத்தம்"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"சாதனத்தில் வண்ணங்கள் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம். இதன் மூலம் நீங்கள் விரும்பும்போதெல்லாம்:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;வண்ணங்களை மிகத் தெளிவாகப் பார்க்கலாம்&lt;/li&gt; &lt;li&gt;கவனம் சிதறாமல் இருக்க வண்ணங்களை நீக்கலாம்&lt;/li&gt; &lt;/ol&gt;"</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="2333641630205214702">"சாதனத்தில் வண்ணங்கள் காண்பிக்கப்படும் விதத்தைச் சரிசெய்யலாம். இதன் மூலம் நீங்கள் விரும்பும்போதெல்லாம்:&lt;br/&gt;&lt;br/&gt; &lt;ol&gt; &lt;li&gt;&amp;nbsp;வண்ணங்களை மிகத் தெளிவாகப் பார்க்கலாம்&lt;/li&gt; &lt;li&gt;&amp;nbsp;கவனம் சிதறாமல் இருக்க வண்ணங்களை நீக்கலாம்&lt;/li&gt; &lt;/ol&gt;"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 71e4fe29487e..7ee835307dba 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -33,12 +33,12 @@
<string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'కు కనెక్ట్ చేయడం సాధ్యపడదు"</string>
<string name="wifi_check_password_try_again" msgid="8817789642851605628">"పాస్‌వర్డ్‌ను చెక్ చేసి, మళ్లీ ప్రయత్నించండి"</string>
<string name="wifi_not_in_range" msgid="1541760821805777772">"పరిధిలో లేదు"</string>
- <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"స్వయంచాలకంగా కనెక్ట్ కాదు"</string>
+ <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"ఆటోమేటిక్‌గా కనెక్ట్ కాదు"</string>
<string name="wifi_no_internet" msgid="1774198889176926299">"ఇంటర్నెట్ యాక్సెస్ లేదు"</string>
<string name="saved_network" msgid="7143698034077223645">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా సేవ్ చేయబడింది"</string>
<string name="connected_to_metered_access_point" msgid="9179693207918156341">"డేటా నియంత్రణ నెట్‌వర్క్‌కు కనెక్ట్ చేయబడింది"</string>
- <string name="connected_via_network_scorer" msgid="7665725527352893558">"%1$s ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string>
- <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"నెట్‌వర్క్ రేటింగ్ ప్రదాత ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string>
+ <string name="connected_via_network_scorer" msgid="7665725527352893558">"%1$s ద్వారా ఆటోమేటిక్‌గా కనెక్ట్ చేయబడింది"</string>
+ <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"నెట్‌వర్క్ రేటింగ్ ప్రదాత ద్వారా ఆటోమేటిక్‌గా కనెక్ట్ చేయబడింది"</string>
<string name="connected_via_passpoint" msgid="7735442932429075684">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string>
<string name="connected_via_app" msgid="3532267661404276584">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా కనెక్ట్ చేయబడింది"</string>
<string name="available_via_passpoint" msgid="1716000261192603682">"%1$s ద్వారా అందుబాటులో ఉంది"</string>
@@ -83,7 +83,7 @@
<string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ"</string>
<string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"యాక్టివ్‌గా ఉంది"</string>
<string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"మీడియా ఆడియో"</string>
- <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ఫోన్ కాల్‌లు"</string>
+ <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ఫోన్ కాల్స్‌"</string>
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ఫైల్ బదిలీ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ఇన్‌పుట్ పరికరం"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ఇంటర్నెట్ యాక్సెస్"</string>
@@ -301,7 +301,7 @@
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ఎల్లప్పుడూ మొబైల్ డేటాను యాక్టివ్‌గా ఉంచు, Wi‑Fi యాక్టివ్‌గా ఉన్నా కూడా (వేగవంతమైన నెట్‌వర్క్ మార్పు కోసం)."</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే టెథెరింగ్ హార్డ్‌వేర్ వేగవృద్ధిని ఉపయోగించండి"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"USB డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
- <string name="adb_warning_message" msgid="8145270656419669221">"USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో అనువర్తనాలను ఇన్‌స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string>
+ <string name="adb_warning_message" msgid="8145270656419669221">"USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string>
<string name="adbwifi_warning_title" msgid="727104571653031865">"వైర్‌లెస్ డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
<string name="adbwifi_warning_message" msgid="8005936574322702388">"వైర్‌లెస్ డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్, పరికరాల మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో యాప్‌లను ఇన్‌స్టాల్ చేయడానికి, లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"మీరు గతంలో ప్రామాణీకరించిన అన్ని కంప్యూటర్‌ల నుండి USB డీబగ్గింగ్‌కు ప్రాప్యతను ఉపసంహరించాలా?"</string>
@@ -489,7 +489,7 @@
<string name="active_input_method_subtypes" msgid="4232680535471633046">"సక్రియ ఇన్‌పుట్ పద్ధతులు"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"సిస్టమ్ భాషలను ఉపయోగించు"</string>
<string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> యొక్క సెట్టింగ్‌లను తెరవడం విఫలమైంది"</string>
- <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్‌పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్‌వర్డ్‌లు మరియు క్రెడిట్ కార్డు నంబర్‌ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> అనువర్తనంలో అందించబడుతుంది. ఈ ఇన్‌పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
+ <string name="ime_security_warning" msgid="6547562217880551450">"ఈ ఇన్‌పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్‌వర్డ్‌లు మరియు క్రెడిట్ కార్డు నంబర్‌ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> యాప్‌లో అందించబడుతుంది. ఈ ఇన్‌పుట్ పద్ధతిని ఉపయోగించాలా?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్‌ను అన్‌లాక్ చేసే వరకు ఈ యాప్ ప్రారంభం కాదు"</string>
<string name="ims_reg_title" msgid="8197592958123671062">"IMS నమోదు స్థితి"</string>
<string name="ims_reg_status_registered" msgid="884916398194885457">"నమోదు చేయబడింది"</string>
@@ -541,8 +541,8 @@
<string name="accessor_expires_text" msgid="4625619273236786252">"లీజు గడువు <xliff:g id="DATE">%s</xliff:g>తో ముగుస్తుంది"</string>
<string name="delete_blob_text" msgid="2819192607255625697">"షేర్ చేసిన డేటాను తొలగించు"</string>
<string name="delete_blob_confirmation_text" msgid="7807446938920827280">"మీరు ఖచ్చితంగా ఈ షేర్ చేసిన డేటాను తొలగించాలనుకుంటున్నారా?"</string>
- <string name="user_add_user_item_summary" msgid="5748424612724703400">"వినియోగదారులు వారి స్వంత అనువర్తనాలను మరియు కంటెంట్‌ను కలిగి ఉన్నారు"</string>
- <string name="user_add_profile_item_summary" msgid="5418602404308968028">"మీరు మీ ఖాతా నుండి అనువర్తనాలకు మరియు కంటెంట్‌కు ప్రాప్యతను పరిమితం చేయవచ్చు"</string>
+ <string name="user_add_user_item_summary" msgid="5748424612724703400">"వినియోగదారులు వారి స్వంత యాప్‌లను మరియు కంటెంట్‌ను కలిగి ఉన్నారు"</string>
+ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"మీరు మీ ఖాతా నుండి యాప్‌లకు మరియు కంటెంట్‌కు ప్రాప్యతను పరిమితం చేయవచ్చు"</string>
<string name="user_add_user_item_title" msgid="2394272381086965029">"యూజర్"</string>
<string name="user_add_profile_item_title" msgid="3111051717414643029">"పరిమితం చేయబడిన ప్రొఫైల్"</string>
<string name="user_add_user_title" msgid="5457079143694924885">"కొత్త వినియోగదారుని జోడించాలా?"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java
index e0339dacf5ac..364698f14623 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminController.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.settingslib.RestrictedLockUtils;
@@ -32,10 +33,12 @@ public class BiometricActionDisabledByAdminController extends BaseActionDisabled
// These MUST not change, as they are the stable API between here and device admin specified
// by the component below.
- private static final String ACTION_LEARN_MORE =
- "android.intent.action.MANAGE_RESTRICTED_SETTING";
- private static final String EXTRA_SETTING_KEY = "extra_setting";
- private static final String EXTRA_SETTING_VALUE = "biometric_disabled_by_admin_controller";
+ @VisibleForTesting
+ static final String ACTION_LEARN_MORE = "android.intent.action.MANAGE_RESTRICTED_SETTING";
+ @VisibleForTesting
+ static final String EXTRA_SETTING_KEY = "extra_setting";
+ @VisibleForTesting
+ static final String EXTRA_SETTING_VALUE = "biometric_disabled_by_admin_controller";
BiometricActionDisabledByAdminController(
DeviceAdminStringProvider stringProvider) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 79446e430d4f..3c43f4a637ba 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -15,7 +15,6 @@
*/
package com.android.settingslib.media;
-import static android.media.MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK;
import static android.media.MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
import static android.media.MediaRoute2Info.TYPE_DOCK;
@@ -44,6 +43,8 @@ import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -56,6 +57,7 @@ import java.util.concurrent.Executors;
/**
* InfoMediaManager provide interface to get InfoMediaDevice list.
*/
+@RequiresApi(Build.VERSION_CODES.R)
public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
@@ -145,9 +147,16 @@ public class InfoMediaManager extends MediaManager {
}
private RoutingSessionInfo getRoutingSessionInfo() {
+ return getRoutingSessionInfo(mPackageName);
+ }
+
+ private RoutingSessionInfo getRoutingSessionInfo(String packageName) {
final List<RoutingSessionInfo> sessionInfos =
- mRouterManager.getRoutingSessions(mPackageName);
+ mRouterManager.getRoutingSessions(packageName);
+ if (sessionInfos == null || sessionInfos.isEmpty()) {
+ return null;
+ }
return sessionInfos.get(sessionInfos.size() - 1);
}
@@ -367,65 +376,18 @@ public class InfoMediaManager extends MediaManager {
}
boolean shouldDisableMediaOutput(String packageName) {
- boolean shouldDisableMediaOutput = false;
if (TextUtils.isEmpty(packageName)) {
Log.w(TAG, "shouldDisableMediaOutput() package name is null or empty!");
- return false;
- }
- final List<MediaRoute2Info> infos = mRouterManager.getTransferableRoutes(packageName);
- if (infos.size() == 1) {
- final MediaRoute2Info info = infos.get(0);
- final int deviceType = info.getType();
- switch (deviceType) {
- case TYPE_UNKNOWN:
- case TYPE_REMOTE_TV:
- case TYPE_REMOTE_SPEAKER:
- case TYPE_GROUP:
- shouldDisableMediaOutput = true;
- break;
- default:
- shouldDisableMediaOutput = false;
- break;
- }
- }
- if (DEBUG) {
- Log.d(TAG, "shouldDisableMediaOutput() MediaRoute2Info size : " + infos.size()
- + ", package name : " + packageName + ", shouldDisableMediaOutput : "
- + shouldDisableMediaOutput);
+ return true;
}
- return shouldDisableMediaOutput;
+
+ // Disable when there is no transferable route
+ return mRouterManager.getTransferableRoutes(packageName).isEmpty();
}
@TargetApi(Build.VERSION_CODES.R)
boolean shouldEnableVolumeSeekBar(RoutingSessionInfo sessionInfo) {
- if (sessionInfo == null) {
- Log.w(TAG, "shouldEnableVolumeSeekBar() package name is null or empty!");
- return false;
- }
- final List<MediaRoute2Info> mediaRoute2Infos =
- mRouterManager.getSelectedRoutes(sessionInfo);
- // More than one selected route
- if (mediaRoute2Infos.size() > 1) {
- if (DEBUG) {
- Log.d(TAG, "shouldEnableVolumeSeekBar() package name : "
- + sessionInfo.getClientPackageName()
- + ", mediaRoute2Infos.size() " + mediaRoute2Infos.size());
- }
- return false;
- }
- // Route contains group feature
- for (MediaRoute2Info mediaRoute2Info : mediaRoute2Infos) {
- final List<String> features = mediaRoute2Info.getFeatures();
- if (features.contains(FEATURE_REMOTE_GROUP_PLAYBACK)) {
- if (DEBUG) {
- Log.d(TAG, "shouldEnableVolumeSeekBar() package name : "
- + mediaRoute2Info.getClientPackageName()
- + "contain group playback ");
- }
- return false;
- }
- }
- return true;
+ return false;
}
private void refreshDevices() {
@@ -456,7 +418,7 @@ public class InfoMediaManager extends MediaManager {
}
private void buildAvailableRoutes() {
- for (MediaRoute2Info route : mRouterManager.getTransferableRoutes(mPackageName)) {
+ for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) {
if (DEBUG) {
Log.d(TAG, "buildAvailableRoutes() route : " + route.getName() + ", volume : "
+ route.getVolume() + ", type : " + route.getType());
@@ -465,6 +427,29 @@ public class InfoMediaManager extends MediaManager {
}
}
+ private List<MediaRoute2Info> getAvailableRoutes(String packageName) {
+ final List<MediaRoute2Info> infos = new ArrayList<>();
+ RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo(packageName);
+ if (routingSessionInfo != null) {
+ infos.addAll(mRouterManager.getSelectedRoutes(routingSessionInfo));
+ }
+ final List<MediaRoute2Info> transferableRoutes =
+ mRouterManager.getTransferableRoutes(packageName);
+ for (MediaRoute2Info transferableRoute : transferableRoutes) {
+ boolean alreadyAdded = false;
+ for (MediaRoute2Info mediaRoute2Info : infos) {
+ if (TextUtils.equals(transferableRoute.getId(), mediaRoute2Info.getId())) {
+ alreadyAdded = true;
+ break;
+ }
+ }
+ if (!alreadyAdded) {
+ infos.add(transferableRoute);
+ }
+ }
+ return infos;
+ }
+
@VisibleForTesting
void addMediaDevice(MediaRoute2Info route) {
final int deviceType = route.getType();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index a8da2c0ba269..22001c9c925a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -22,11 +22,13 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.RoutingSessionInfo;
+import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.A2dpProfile;
@@ -49,6 +51,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
/**
* LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
*/
+@RequiresApi(Build.VERSION_CODES.R)
public class LocalMediaManager implements BluetoothCallback {
private static final Comparator<MediaDevice> COMPARATOR = Comparator.naturalOrder();
private static final String TAG = "LocalMediaManager";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index 97e6d5051fd2..ed198fa923f2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -38,6 +38,7 @@ import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@@ -158,6 +159,7 @@ public class LifecycleTest {
}
@Test
+ @Ignore("b/188888268")
public void runThroughActivityLifecycles_shouldObserveEverything() {
ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class);
TestActivity activity = ac.setup().get();
@@ -179,6 +181,7 @@ public class LifecycleTest {
}
@Test
+ @Ignore("b/188888268")
public void runThroughDialogFragmentLifecycles_shouldObserveEverything() {
final TestDialogFragment fragment = new TestDialogFragment();
FragmentController.setupFragment(fragment);
@@ -202,6 +205,7 @@ public class LifecycleTest {
}
@Test
+ @Ignore("b/188888268")
public void runThroughFragmentLifecycles_shouldObserveEverything() {
final TestFragment fragment = new TestFragment();
FragmentController.setupFragment(fragment);
@@ -241,6 +245,7 @@ public class LifecycleTest {
}
@Test
+ @Ignore("b/188888268")
public void onOptionItemSelectedShortCircuitsIfAnObserverHandlesTheMenuItem() {
final TestFragment fragment = new TestFragment();
FragmentController.setupFragment(fragment);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java
index 766c2f5f9872..c41f4db6f6d1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/enterprise/BiometricActionDisabledByAdminControllerTest.java
@@ -22,7 +22,7 @@ import static com.android.settingslib.enterprise.FakeDeviceAdminStringProvider.D
import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -39,41 +39,49 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class BiometricActionDisabledByAdminControllerTest {
- private final ActionDisabledByAdminControllerTestUtils mTestUtils =
- new ActionDisabledByAdminControllerTestUtils();
- private final BiometricActionDisabledByAdminController mController =
- new BiometricActionDisabledByAdminController(DEFAULT_DEVICE_ADMIN_STRING_PROVIDER);
+ @Mock
+ private Context mContext;
+
+ private ActionDisabledByAdminControllerTestUtils mTestUtils;
+ private BiometricActionDisabledByAdminController mController;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mTestUtils = new ActionDisabledByAdminControllerTestUtils();
+
+ mController = new BiometricActionDisabledByAdminController(
+ DEFAULT_DEVICE_ADMIN_STRING_PROVIDER);
mController.initialize(mTestUtils.createLearnMoreButtonLauncher());
mController.updateEnforcedAdmin(ENFORCED_ADMIN, ENFORCEMENT_ADMIN_USER_ID);
}
@Test
public void buttonClicked() {
- Context context = mock(Context.class);
ComponentName componentName = mock(ComponentName.class);
RestrictedLockUtils.EnforcedAdmin enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin(
componentName, new UserHandle(UserHandle.myUserId()));
DialogInterface.OnClickListener listener =
- mController.getPositiveButtonListener(context, enforcedAdmin);
+ mController.getPositiveButtonListener(mContext, enforcedAdmin);
assertNotNull("Biometric Controller must supply a non-null listener", listener);
listener.onClick(mock(DialogInterface.class), 0 /* which */);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(context).startActivity(intentCaptor.capture());
- assertEquals("android.settings.LEARN_MORE",
+ verify(mContext).startActivity(intentCaptor.capture());
+ assertEquals(BiometricActionDisabledByAdminController.ACTION_LEARN_MORE,
intentCaptor.getValue().getAction());
- assertTrue("from_biometric_setup", intentCaptor.getValue()
- .getBooleanExtra("from_biometric_setup", false));
- assertEquals(componentName, intentCaptor.getValue().getComponent());
+ assertEquals(BiometricActionDisabledByAdminController.EXTRA_SETTING_VALUE,
+ intentCaptor.getValue().getStringExtra(
+ BiometricActionDisabledByAdminController.EXTRA_SETTING_KEY));
+ assertSame(componentName, intentCaptor.getValue().getComponent());
}
-
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 9bc8e657daa3..fe48575c40c9 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -118,6 +118,10 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.CLOCKWORK_SYSUI_PACKAGE_NAME, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.CLOCKWORK_HOME_READY, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.ENABLE_TARE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.ENABLE_TARE_ALARM_MANAGER, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.ENABLE_TARE_JOB_SCHEDULER, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.TARE_ALARM_MANAGER_CONSTANTS, ANY_STRING_VALIDATOR);
+ VALIDATORS.put(Global.TARE_JOB_SCHEDULER_CONSTANTS, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.PRIVATE_DNS_MODE, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.PRIVATE_DNS_SPECIFIER, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.SOFT_AP_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 294399e754df..6bb125bab68f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3588,7 +3588,7 @@ public class SettingsProvider extends ContentProvider {
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 204;
+ private static final int SETTINGS_VERSION = 205;
private final int mUserId;
@@ -5399,6 +5399,44 @@ public class SettingsProvider extends ContentProvider {
currentVersion = 204;
}
+ if (currentVersion == 204) {
+ // Version 204: Replace 'wifi' or 'cell' tiles with 'internet' if existed.
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting currentValue = secureSettings.getSettingLocked(Secure.QS_TILES);
+ if (!currentValue.isNull()) {
+ String tileList = currentValue.getValue();
+ String[] tileSplit = tileList.split(",");
+ final ArrayList<String> tiles = new ArrayList<String>();
+ boolean hasInternetTile = false;
+ for (int i = 0; i < tileSplit.length; i++) {
+ String tile = tileSplit[i].trim();
+ if (tile.isEmpty()) continue;
+ tiles.add(tile);
+ if (tile.equals("internet")) hasInternetTile = true;
+ }
+ if (!hasInternetTile) {
+ if (tiles.contains("wifi")) {
+ // Replace the WiFi with Internet, and remove the Cell
+ tiles.set(tiles.indexOf("wifi"), "internet");
+ tiles.remove("cell");
+ } else if (tiles.contains("cell")) {
+ // Replace the Cell with Internet
+ tiles.set(tiles.indexOf("cell"), "internet");
+ }
+ } else {
+ tiles.remove("wifi");
+ tiles.remove("cell");
+ }
+ secureSettings.insertSettingOverrideableByRestoreLocked(
+ Secure.QS_TILES,
+ TextUtils.join(",", tiles),
+ null /* tag */,
+ true /* makeDefault */,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 205;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index ec2ec668d2d9..b2100629a394 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -266,6 +266,8 @@ public class SettingsBackupTest {
Settings.Global.ENABLE_EPHEMERAL_FEATURE,
Settings.Global.ENABLE_RESTRICTED_BUCKET,
Settings.Global.ENABLE_TARE,
+ Settings.Global.ENABLE_TARE_ALARM_MANAGER,
+ Settings.Global.ENABLE_TARE_JOB_SCHEDULER,
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
@@ -474,6 +476,8 @@ public class SettingsBackupTest {
Settings.Global.SYS_UIDCPUPOWER,
Settings.Global.SYS_TRACED,
Settings.Global.FPS_DEVISOR,
+ Settings.Global.TARE_ALARM_MANAGER_CONSTANTS,
+ Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS,
Settings.Global.TCP_DEFAULT_INIT_RWND,
Settings.Global.TETHER_DUN_APN,
Settings.Global.TETHER_DUN_REQUIRED,
diff --git a/packages/Shell/res/values-te/strings.xml b/packages/Shell/res/values-te/strings.xml
index 989b53e7810d..50b5c8550ef2 100644
--- a/packages/Shell/res/values-te/strings.xml
+++ b/packages/Shell/res/values-te/strings.xml
@@ -18,30 +18,30 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"షెల్"</string>
<string name="bugreport_notification_channel" msgid="2574150205913861141">"బగ్ రిపోర్ట్స్"</string>
- <string name="bugreport_in_progress_title" msgid="4311705936714972757">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> ఉత్పాదించబడుతోంది"</string>
- <string name="bugreport_finished_title" msgid="4429132808670114081">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> సంగ్రహించబడింది"</string>
- <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ నివేదికకు వివరాలను జోడిస్తోంది"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"బగ్ రిపోర్ట్‌ <xliff:g id="ID">#%d</xliff:g> ఉత్పాదించబడుతోంది"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"బగ్ రిపోర్ట్‌ <xliff:g id="ID">#%d</xliff:g> సంగ్రహించబడింది"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ రిపోర్ట్‌‌కు వివరాలను జోడిస్తోంది"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"దయచేసి వేచి ఉండండి..."</string>
- <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"బగ్ నివేదిక త్వరలో ఫోన్‌లో కనిపిస్తుంది"</string>
- <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎంచుకోండి"</string>
- <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"మీ బగ్ నివేదికను షేర్ చేయడానికి నొక్కండి"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎంచుకోండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"బగ్ రిపోర్ట్‌ త్వరలో ఫోన్‌లో కనిపిస్తుంది"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"మీ బగ్ రిపోర్ట్‌ను భాగస్వామ్యం చేయడానికి ఎంచుకోండి"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"మీ బగ్ రిపోర్ట్‌ను షేర్ చేయడానికి నొక్కండి"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ రిపోర్ట్‌ను భాగస్వామ్యం చేయడానికి ఎంచుకోండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
- <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ రిపోర్ట్స్‌లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం, లొకేష‌న్‌ డేటా వంటి) డేటాతో పాటు సిస్టమ్‌కు సంబంధించిన విభిన్న లాగ్ ఫైల్‌ల డేటా ఉంటుంది. బగ్ నివేదికలను మీరు విశ్వసించే యాప్‌లు, వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ రిపోర్ట్స్‌లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం, లొకేష‌న్‌ డేటా వంటి) డేటాతో పాటు సిస్టమ్‌కు సంబంధించిన విభిన్న లాగ్ ఫైళ్ల డేటా ఉంటుంది. బగ్ రిపోర్ట్‌లను మీరు విశ్వసించే యాప్‌లు, వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"మళ్లీ చూపవద్దు"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ రిపోర్ట్స్"</string>
- <string name="bugreport_unreadable_text" msgid="586517851044535486">"బగ్ నివేదిక ఫైల్‌ను చదవడం సాధ్యపడలేదు"</string>
- <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"బగ్ నివేదిక వివరాలను జిప్ ఫైల్‌కు జోడించడం సాధ్యపడలేదు"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"బగ్ రిపోర్ట్‌ ఫైల్‌ను చదవడం సాధ్యపడలేదు"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"బగ్ రిపోర్ట్‌ వివరాలను జిప్ ఫైల్‌కు జోడించడం సాధ్యపడలేదు"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"పేరు లేనివి"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"వివరాలు"</string>
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"స్క్రీన్‌షాట్"</string>
<string name="bugreport_screenshot_taken" msgid="5684211273096253120">"స్క్రీన్‌షాట్ విజయవంతంగా తీయబడింది."</string>
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"స్క్రీన్‌షాట్‌ను తీయడం సాధ్యపడలేదు."</string>
- <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> వివరాలు"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"బగ్ రిపోర్ట్‌ <xliff:g id="ID">#%d</xliff:g> వివరాలు"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ఫైల్ పేరు"</string>
<string name="bugreport_info_title" msgid="2306030793918239804">"బగ్ శీర్షిక"</string>
<string name="bugreport_info_description" msgid="5072835127481627722">"బగ్ సారాంశం"</string>
<string name="save" msgid="4781509040564835759">"సేవ్ చేయి"</string>
- <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"బగ్ నివేదిక షేర్ చేయండి"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"బగ్ రిపోర్ట్‌ షేర్ చేయండి"</string>
</resources>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/plugin/src/com/android/systemui/flags/Flag.kt
new file mode 100644
index 000000000000..68834bc2aa23
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/flags/Flag.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 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.flags
+
+interface Flag<T> {
+ val id: Int
+ val default: T
+}
+
+data class BooleanFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: Boolean = false
+) : Flag<Boolean>
+
+data class StringFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: String = ""
+) : Flag<String>
+
+data class IntFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: Int = 0
+) : Flag<Int>
+
+data class LongFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: Long = 0
+) : Flag<Long>
+
+data class FloatFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: Float = 0f
+) : Flag<Float>
+
+data class DoubleFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val default: Double = 0.0
+) : Flag<Double> \ No newline at end of file
diff --git a/core/java/android/uwb/SessionHandle.aidl b/packages/SystemUI/plugin/src/com/android/systemui/flags/Flags.java
index 58a7dbb2ef9f..d5b9243ebe86 100644
--- a/core/java/android/uwb/SessionHandle.aidl
+++ b/packages/SystemUI/plugin/src/com/android/systemui/flags/Flags.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 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,6 +14,10 @@
* limitations under the License.
*/
-package android.uwb;
+package com.android.systemui.flags;
-parcelable SessionHandle;
+/**
+ * List of {@link Flag} objects for use in SystemUI.
+ */
+public class Flags {
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FlagReaderPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FlagReaderPlugin.java
new file mode 100644
index 000000000000..ab1749978653
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FlagReaderPlugin.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+
+/**
+ * Plugin for loading flag values from an alternate source of truth.
+ */
+@ProvidesInterface(action = FlagReaderPlugin.ACTION, version = FlagReaderPlugin.VERSION)
+public interface FlagReaderPlugin extends Plugin {
+ int VERSION = 1;
+ String ACTION = "com.android.systemui.flags.FLAG_READER_PLUGIN";
+
+ /** Returns a boolean value for the given flag. */
+ default boolean isEnabled(int id, boolean def) {
+ return def;
+ }
+
+ /** Returns a string value for the given flag id. */
+ default String getValue(int id, String def) {
+ return def;
+ }
+
+ /** Returns a int value for the given flag. */
+ default int getValue(int id, int def) {
+ return def;
+ }
+
+ /** Returns a long value for the given flag. */
+ default long getValue(int id, long def) {
+ return def;
+ }
+
+ /** Returns a float value for the given flag. */
+ default float getValue(int id, float def) {
+ return def;
+ }
+
+ /** Returns a double value for the given flag. */
+ default double getValue(int id, double def) {
+ return def;
+ }
+
+ /** Add a listener to be alerted when any flag changes. */
+ default void addListener(Listener listener) {}
+
+ /** Remove a listener to be alerted when any flag changes. */
+ default void removeListener(Listener listener) {}
+
+ /** A simple listener to be alerted when a flag changes. */
+ interface Listener {
+ /** */
+ void onFlagChanged(int id);
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
new file mode 100644
index 000000000000..dfc3e63a4e2b
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2021, 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.
+-->
+
+<!-- Action buttons for footer in QS/QQS, containing settings button, power off button etc -->
+<com.android.systemui.qs.FooterActionsView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:gravity="center_vertical">
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@android:id/edit"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:contentDescription="@string/accessibility_quick_settings_edit"
+ android:focusable="true"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:src="@*android:drawable/ic_mode_edit"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.phone.MultiUserSwitch
+ android:id="@+id/multi_user_switch"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:focusable="true">
+
+ <ImageView
+ android:id="@+id/multi_user_avatar"
+ android:layout_width="@dimen/multi_user_avatar_expanded_size"
+ android:layout_height="@dimen/multi_user_avatar_expanded_size"
+ android:layout_gravity="center"
+ android:scaleType="centerInside" />
+ </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/pm_lite"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:clickable="true"
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:src="@*android:drawable/ic_lock_power_off"
+ android:contentDescription="@string/accessibility_quick_settings_power_menu"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/settings_button_container"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:background="@drawable/qs_footer_action_chip_background"
+ android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false">
+
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_footer_action_button_size"
+ android:layout_gravity="center"
+ android:contentDescription="@string/accessibility_quick_settings_settings"
+ android:background="@drawable/qs_footer_action_chip_background_borderless"
+ android:padding="@dimen/qs_footer_icon_padding"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_settings"
+ android:tint="?android:attr/textColorPrimary" />
+
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
+ android:layout_width="8dp"
+ android:layout_height="8dp"
+ android:layout_gravity="center_horizontal|bottom"
+ android:layout_marginBottom="@dimen/qs_footer_icon_padding"
+ android:src="@drawable/tuner"
+ android:tint="?android:attr/textColorTertiary"
+ android:visibility="invisible" />
+
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+</com.android.systemui.qs.FooterActionsView> \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 28c61663bd4d..6016aafbd6ae 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -68,6 +68,16 @@
lockScreenWeight="400"
/>
</FrameLayout>
+ <FrameLayout
+ android:id="@+id/keyguard_smartspace_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/below_clock_padding_start"
+ android:paddingEnd="@dimen/below_clock_padding_end"
+ android:layout_alignParentStart="true"
+ android:layout_below="@id/lockscreen_clock_view"
+ />
+ <!-- either keyguard_status_area or keyguard_smartspace_container is visible -->
<include layout="@layout/keyguard_status_area"
android:id="@+id/keyguard_status_area"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index ce63082868bb..f613a195ea67 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -27,49 +27,44 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- androidprv:layout_maxHeight="@dimen/keyguard_security_height"
- android:gravity="center_horizontal">
+ android:clipChildren="false"
+ android:clipToPadding="false">
- <FrameLayout
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/pattern_container"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <LinearLayout
- android:id="@+id/pattern_container"
- android:layout_height="wrap_content"
+ android:layout_height="0dp"
+ android:layout_marginBottom="8dp"
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/pattern_top_guideline"
android:layout_width="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="center_horizontal|bottom"
- android:clipChildren="false"
- android:clipToPadding="false">
+ android:layout_height="wrap_content"
+ androidprv:layout_constraintGuide_percent="0"
+ android:orientation="horizontal" />
- <com.android.internal.widget.LockPatternView
- android:id="@+id/lockPatternView"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:layout_marginEnd="8dip"
- android:layout_marginBottom="4dip"
- android:layout_marginStart="8dip"
- android:layout_gravity="center_horizontal"
- android:gravity="center"
- android:clipChildren="false"
- android:clipToPadding="false" />
+ <com.android.internal.widget.LockPatternView
+ android:id="@+id/lockPatternView"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ androidprv:layout_constraintTop_toBottomOf="@id/pattern_top_guideline"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintLeft_toLeftOf="parent"
+ androidprv:layout_constraintRight_toRightOf="parent"
+ androidprv:layout_constraintDimensionRatio="1.0"
+ androidprv:layout_constraintVertical_bias="1.0"
+ />
+ </androidx.constraintlayout.widget.ConstraintLayout>
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:gravity="center_horizontal" />
- </LinearLayout>
- </FrameLayout>
+ <include layout="@layout/keyguard_eca"
+ android:id="@+id/keyguard_selector_fade_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:gravity="center_horizontal" />
</com.android.keyguard.KeyguardPatternView>
diff --git a/packages/SystemUI/res/anim/fp_to_unlock.xml b/packages/SystemUI/res/anim/fp_to_unlock.xml
index a348208f48c7..a5f75b6726c8 100644
--- a/packages/SystemUI/res/anim/fp_to_unlock.xml
+++ b/packages/SystemUI/res/anim/fp_to_unlock.xml
@@ -19,10 +19,10 @@
<group android:name="_R_G">
<group android:name="_R_G_L_1_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
<group android:name="_R_G_L_1_G" android:translateX="30.75" android:translateY="25.75">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
- <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
- <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
- <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " />
+ <path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " />
+ <path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " />
+ <path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " />
</group>
</group>
<group android:name="_R_G_L_0_G_N_7_T_0" android:translateX="-27" android:translateY="-17.5">
diff --git a/packages/SystemUI/res/anim/lock_to_unlock.xml b/packages/SystemUI/res/anim/lock_to_unlock.xml
index ec51c0171709..76f7a05866d9 100644
--- a/packages/SystemUI/res/anim/lock_to_unlock.xml
+++ b/packages/SystemUI/res/anim/lock_to_unlock.xml
@@ -21,7 +21,7 @@
<group android:name="_R_G_L_2_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
<group android:name="_R_G_L_2_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
<group android:name="_R_G_L_2_G" android:translateX="-0.375" android:translateY="-22.375">
- <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
</group>
</group>
</group>
@@ -30,7 +30,7 @@
<group android:name="_R_G_L_1_G_N_10_T_1" android:translateX="50.25" android:translateY="61">
<group android:name="_R_G_L_1_G_N_10_T_0" android:translateX="-13.75" android:translateY="-7.5">
<group android:name="_R_G_L_1_G" android:translateX="5" android:translateY="-22.5">
- <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#b7f29f" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M2.5 15 C2.5,15 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15,15 15,15 " />
</group>
</group>
</group>
diff --git a/packages/SystemUI/res/drawable/ic_unlock.xml b/packages/SystemUI/res/drawable/ic_unlock.xml
index c3b34699e8e2..46023e6160f5 100644
--- a/packages/SystemUI/res/drawable/ic_unlock.xml
+++ b/packages/SystemUI/res/drawable/ic_unlock.xml
@@ -21,7 +21,7 @@
android:strokeColor="#FF000000"
android:strokeLineCap="round"
android:strokeLineJoin="round"
- android:strokeWidth="2.5"
+ android:strokeWidth="2"
android:pathData="M4.75 15 C4.75,15 23.25,15 23.25,15 C24.35,15 25.25,15.9 25.25,17 C25.25,17 25.25,33 25.25,33 C25.25,34.1 24.35,35 23.25,35 C23.25,35 4.75,35 4.75,35 C3.65,35 2.75,34.1 2.75,33 C2.75,33 2.75,17 2.75,17 C2.75,15.9 3.65,15 4.75,15c " />
</group>
<group android:translateX="14" android:translateY="13.5">
@@ -29,7 +29,7 @@
android:strokeColor="#FF000000"
android:strokeLineCap="round"
android:strokeLineJoin="round"
- android:strokeWidth="2.5"
+ android:strokeWidth="2"
android:pathData="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
</group>
<group android:translateX="20" android:translateY="35.75">
diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_off.xml b/packages/SystemUI/res/drawable/settingslib_thumb_off.xml
index 8b69ad1b2493..87d4aeaac84f 100644
--- a/packages/SystemUI/res/drawable/settingslib_thumb_off.xml
+++ b/packages/SystemUI/res/drawable/settingslib_thumb_off.xml
@@ -18,8 +18,6 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="@dimen/settingslib_switch_thumb_margin"
- android:left="@dimen/settingslib_switch_thumb_margin"
- android:right="@dimen/settingslib_switch_thumb_margin"
android:bottom="@dimen/settingslib_switch_thumb_margin">
<shape android:shape="oval">
<size
diff --git a/packages/SystemUI/res/drawable/settingslib_thumb_on.xml b/packages/SystemUI/res/drawable/settingslib_thumb_on.xml
index 0f27fc2f4ad8..5566ea3f62fc 100644
--- a/packages/SystemUI/res/drawable/settingslib_thumb_on.xml
+++ b/packages/SystemUI/res/drawable/settingslib_thumb_on.xml
@@ -18,8 +18,6 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="@dimen/settingslib_switch_thumb_margin"
- android:left="@dimen/settingslib_switch_thumb_margin"
- android:right="@dimen/settingslib_switch_thumb_margin"
android:bottom="@dimen/settingslib_switch_thumb_margin">
<shape android:shape="oval">
<size
diff --git a/packages/SystemUI/res/drawable/settingslib_track_off_background.xml b/packages/SystemUI/res/drawable/settingslib_track_off_background.xml
index 4d79a6e20776..3a09284d10a0 100644
--- a/packages/SystemUI/res/drawable/settingslib_track_off_background.xml
+++ b/packages/SystemUI/res/drawable/settingslib_track_off_background.xml
@@ -19,6 +19,8 @@
android:shape="rectangle"
android:width="@dimen/settingslib_switch_track_width"
android:height="@dimen/settingslib_switch_track_height">
+ <padding android:left="@dimen/settingslib_switch_thumb_margin"
+ android:right="@dimen/settingslib_switch_thumb_margin"/>
<solid android:color="@color/settingslib_track_off_color"/>
<corners android:radius="@dimen/settingslib_switch_track_radius"/>
</shape>
diff --git a/packages/SystemUI/res/drawable/settingslib_track_on_background.xml b/packages/SystemUI/res/drawable/settingslib_track_on_background.xml
index c12d012a0508..1d9dacd6c0f9 100644
--- a/packages/SystemUI/res/drawable/settingslib_track_on_background.xml
+++ b/packages/SystemUI/res/drawable/settingslib_track_on_background.xml
@@ -19,6 +19,8 @@
android:shape="rectangle"
android:width="@dimen/settingslib_switch_track_width"
android:height="@dimen/settingslib_switch_track_height">
+ <padding android:left="@dimen/settingslib_switch_thumb_margin"
+ android:right="@dimen/settingslib_switch_thumb_margin"/>
<solid android:color="@color/settingslib_track_on_color"/>
<corners android:radius="@dimen/settingslib_switch_track_radius"/>
</shape>
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index f7919d43c551..5b58fe8c0b58 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -19,18 +19,18 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/internet_connectivity_dialog"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_width="@dimen/internet_dialog_list_max_width"
+ android:layout_height="@dimen/internet_dialog_list_max_height"
android:background="@drawable/internet_dialog_rounded_top_corner_background"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
+ android:layout_height="wrap_content"
style="@style/Widget.SliceView.Panel"
android:gravity="center_vertical|center_horizontal"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp"
- android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
@@ -54,21 +54,28 @@
android:textSize="14sp"/>
</LinearLayout>
- <View
- android:id="@+id/divider"
- android:layout_gravity="center_vertical|center_horizontal"
- android:layout_width="340dp"
- android:layout_height="4dp"
- android:background="?androidprv:attr/colorSurfaceVariant"/>
-
- <ProgressBar
- android:id="@+id/wifi_searching_progress"
- android:indeterminate="true"
- android:layout_width="340dp"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:visibility="gone"
- style="@style/TrimmedHorizontalProgressBar"/>
+ android:layout_marginBottom="16dp"
+ android:orientation="vertical">
+
+ <View
+ android:id="@+id/divider"
+ android:layout_gravity="center_vertical|center_horizontal"
+ android:layout_width="340dp"
+ android:layout_height="4dp"
+ android:background="?androidprv:attr/colorSurfaceVariant"/>
+
+ <ProgressBar
+ android:id="@+id/wifi_searching_progress"
+ android:indeterminate="true"
+ android:layout_width="340dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:visibility="gone"
+ style="@style/TrimmedHorizontalProgressBar"/>
+ </LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
@@ -94,9 +101,8 @@
android:background="?android:attr/selectableItemBackground"
android:layout_gravity="center_vertical|start"
android:orientation="horizontal"
- android:layout_marginRight="@dimen/settingslib_switchbar_margin"
- android:layout_marginLeft="@dimen/settingslib_switchbar_margin"
- android:layout_marginTop="16dp"
+ android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
+ android:layout_marginStart="@dimen/settingslib_switchbar_margin"
android:paddingStart="22dp"
android:paddingEnd="22dp">
@@ -107,6 +113,7 @@
android:layout_gravity="center_vertical|start">
<ImageView
android:id="@+id/signal_icon"
+ android:autoMirrored="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
@@ -122,10 +129,11 @@
android:gravity="start|center_vertical">
<TextView
android:id="@+id/mobile_title"
- android:layout_marginLeft="16dp"
+ android:textDirection="locale"
+ android:layout_marginStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center_vertical|start"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
@@ -133,10 +141,11 @@
android:fontFamily="google-sans"/>
<TextView
android:id="@+id/mobile_summary"
- android:layout_marginLeft="16dp"
+ android:textDirection="locale"
+ android:layout_marginStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center_vertical|start"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorTertiary"
@@ -145,14 +154,15 @@
</LinearLayout>
<FrameLayout
- android:layout_width="48dp"
+ android:layout_width="@dimen/settingslib_switch_track_width"
android:layout_height="48dp"
android:layout_gravity="end|center_vertical">
<Switch
android:id="@+id/mobile_toggle"
+ android:switchMinWidth="@dimen/settingslib_switch_track_width"
android:layout_gravity="center"
- android:layout_width="48dp"
- android:layout_height="wrap_content"
+ android:layout_width="@dimen/settingslib_switch_track_width"
+ android:layout_height="@dimen/settingslib_switch_track_height"
android:track="@drawable/settingslib_track_selector"
android:thumb="@drawable/settingslib_thumb_selector"
android:theme="@style/MainSwitch.Settingslib"/>
@@ -169,8 +179,8 @@
android:background="?android:attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
- android:layout_marginRight="@dimen/settingslib_switchbar_margin"
- android:layout_marginLeft="@dimen/settingslib_switchbar_margin"
+ android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
+ android:layout_marginStart="@dimen/settingslib_switchbar_margin"
android:paddingStart="22dp"
android:paddingEnd="22dp">
@@ -182,6 +192,7 @@
android:layout_height="match_parent">
<TextView
android:text="@string/turn_on_wifi"
+ android:textDirection="locale"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
@@ -191,15 +202,16 @@
</FrameLayout>
<FrameLayout
- android:layout_width="48dp"
+ android:layout_width="@dimen/settingslib_switch_track_width"
android:layout_height="48dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<Switch
android:id="@+id/wifi_toggle"
+ android:switchMinWidth="@dimen/settingslib_switch_track_width"
android:layout_gravity="center"
- android:layout_width="48dp"
- android:layout_height="wrap_content"
+ android:layout_width="@dimen/settingslib_switch_track_width"
+ android:layout_height="@dimen/settingslib_switch_track_height"
android:track="@drawable/settingslib_track_selector"
android:thumb="@drawable/settingslib_thumb_selector"
android:theme="@style/MainSwitch.Settingslib"/>
@@ -217,8 +229,8 @@
android:visibility="gone"
android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal"
- android:layout_marginRight="@dimen/settingslib_switchbar_margin"
- android:layout_marginLeft="@dimen/settingslib_switchbar_margin"
+ android:layout_marginEnd="@dimen/settingslib_switchbar_margin"
+ android:layout_marginStart="@dimen/settingslib_switchbar_margin"
android:paddingStart="22dp"
android:paddingEnd="22dp">
@@ -244,10 +256,11 @@
android:gravity="start|center_vertical">
<TextView
android:id="@+id/wifi_connected_title"
+ android:textDirection="locale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginLeft="16dp"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
@@ -255,10 +268,11 @@
android:fontFamily="google-sans"/>
<TextView
android:id="@+id/wifi_connected_summary"
+ android:textDirection="locale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginLeft="16dp"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorTertiary"
@@ -269,7 +283,7 @@
<FrameLayout
android:layout_width="24dp"
android:layout_height="match_parent"
- android:layout_marginRight="5dp"
+ android:layout_marginEnd="5dp"
android:clickable="false"
android:gravity="center">
<ImageView
@@ -323,9 +337,10 @@
android:clickable="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginLeft="16dp">
+ android:layout_marginStart="16dp">
<TextView
android:text="@string/see_all_networks"
+ android:textDirection="locale"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="start|center_vertical"
@@ -336,31 +351,23 @@
</LinearLayout>
- <Space
- android:id="@+id/space"
- android:layout_width="match_parent"
- android:layout_height="28dp"
- android:visibility="gone"/>
-
- <LinearLayout
+ <FrameLayout
android:layout_width="match_parent"
android:layout_height="48dp"
- android:layout_marginBottom="25dp"
- android:gravity="end"
- android:orientation="horizontal">
+ android:layout_marginBottom="40dp">
<Button
style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
android:id="@+id/done"
- android:layout_width="60dp"
- android:layout_height="30dp"
- android:layout_marginRight="24dp"
- android:layout_gravity="end"
+ android:layout_width="67dp"
+ android:layout_height="36dp"
+ android:layout_marginEnd="24dp"
+ android:layout_gravity="end|center_vertical"
android:background="@drawable/internet_dialog_footer_background"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/inline_done_button"
android:textSize="14sp"
android:fontFamily="google-sans"/>
- </LinearLayout>
+ </FrameLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml
index fb5790100410..19b1ef90bdfa 100644
--- a/packages/SystemUI/res/layout/internet_list_item.xml
+++ b/packages/SystemUI/res/layout/internet_list_item.xml
@@ -56,12 +56,13 @@
android:layout_height="72dp">
<TextView
android:id="@+id/wifi_title"
+ android:textDirection="locale"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="0dp"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center_vertical|start"
android:gravity="start|center_vertical"
- android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
@@ -69,12 +70,13 @@
android:fontFamily="google-sans"/>
<TextView
android:id="@+id/wifi_summary"
+ android:textDirection="locale"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="0dp"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center_vertical|start"
android:gravity="start|center_vertical"
- android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
@@ -85,7 +87,7 @@
<FrameLayout
android:layout_width="24dp"
android:layout_height="match_parent"
- android:layout_marginRight="@dimen/settingslib_switchbar_padding_right"
+ android:layout_marginEnd="@dimen/settingslib_switchbar_padding_right"
android:clickable="false"
android:gravity="center">
<ImageView
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 317dbc09eae6..e70084b80308 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -68,93 +68,9 @@
</LinearLayout>
- <LinearLayout
- android:id="@+id/qs_footer_actions_container"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:gravity="center_vertical">
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@android:id/edit"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:clickable="true"
- android:clipToPadding="false"
- android:contentDescription="@string/accessibility_quick_settings_edit"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_mode_edit"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch
- android:id="@+id/multi_user_switch"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:focusable="true">
-
- <ImageView
- android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside" />
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
+ <include layout="@layout/footer_actions"
+ android:id="@+id/qs_footer_actions"/>
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/pm_lite"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_marginEnd="@dimen/qs_tile_margin_horizontal"
- android:layout_weight="1"
- android:background="@drawable/qs_footer_action_chip_background"
- android:clickable="true"
- android:clipToPadding="false"
- android:focusable="true"
- android:padding="@dimen/qs_footer_icon_padding"
- android:src="@*android:drawable/ic_lock_power_off"
- android:contentDescription="@string/accessibility_quick_settings_power_menu"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:background="@drawable/qs_footer_action_chip_background"
- android:layout_weight="1"
- android:clipChildren="false"
- android:clipToPadding="false">
-
- <com.android.systemui.statusbar.phone.SettingsButton
- android:id="@+id/settings_button"
- android:layout_width="match_parent"
- android:layout_height="@dimen/qs_footer_action_button_size"
- android:layout_gravity="center"
- android:contentDescription="@string/accessibility_quick_settings_settings"
- android:background="@drawable/qs_footer_action_chip_background_borderless"
- android:padding="@dimen/qs_footer_icon_padding"
- android:scaleType="centerInside"
- android:src="@drawable/ic_settings"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/tuner_icon"
- android:layout_width="8dp"
- android:layout_height="8dp"
- android:layout_gravity="center_horizontal|bottom"
- android:layout_marginBottom="@dimen/qs_footer_icon_padding"
- android:src="@drawable/tuner"
- android:tint="?android:attr/textColorTertiary"
- android:visibility="invisible" />
-
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
- </LinearLayout>
</LinearLayout>
</com.android.systemui.qs.QSFooterView>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index df02730fc866..6b14c96b58e2 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -56,7 +56,18 @@
android:clipToPadding="false"
android:focusable="true"
android:paddingBottom="24dp"
- android:importantForAccessibility="yes" />
+ android:importantForAccessibility="yes">
+
+ <include
+ layout="@layout/footer_actions"
+ android:id="@+id/qqs_footer_actions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginStart="@dimen/qs_footer_margin"
+ android:layout_marginEnd="@dimen/qs_footer_margin"
+ />
+ </com.android.systemui.qs.QuickQSPanel>
</RelativeLayout>
</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index e0a51c21dbe6..0c3c602fe658 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -68,7 +68,7 @@
android:id="@+id/lock_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"/>
</com.android.keyguard.LockIconView>
@@ -92,6 +92,18 @@
android:layout_height="match_parent"
android:visibility="gone"/>
+ <FrameLayout
+ android:id="@+id/split_shade_smartspace_container"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/notification_side_paddings"
+ android:paddingEnd="@dimen/notification_side_paddings"
+ systemui:layout_constraintStart_toStartOf="@id/qs_edge_guideline"
+ systemui:layout_constraintEnd_toEndOf="parent"
+ systemui:layout_constraintTop_toTopOf="parent"
+ android:visibility="gone">
+ </FrameLayout>
+
<include layout="@layout/dock_info_overlay"/>
<FrameLayout
diff --git a/packages/SystemUI/res/layout/udfps_keyguard_view.xml b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
index 1851790673e3..a9eb27ad3b02 100644
--- a/packages/SystemUI/res/layout/udfps_keyguard_view.xml
+++ b/packages/SystemUI/res/layout/udfps_keyguard_view.xml
@@ -34,7 +34,7 @@
android:id="@+id/udfps_aod_fp"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"
app:lottie_autoPlay="false"
@@ -46,7 +46,7 @@
android:id="@+id/udfps_lockscreen_fp"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="48px"
+ android:padding="@dimen/lock_icon_padding"
android:layout_gravity="center"
android:scaleType="centerCrop"
app:lottie_autoPlay="false"
diff --git a/packages/SystemUI/res/raw/udfps_aod_fp.json b/packages/SystemUI/res/raw/udfps_aod_fp.json
index 3247fe74fcfe..51d9058f4dd2 100644
--- a/packages/SystemUI/res/raw/udfps_aod_fp.json
+++ b/packages/SystemUI/res/raw/udfps_aod_fp.json
@@ -5,7 +5,7 @@
"op":361,
"w":46,
"h":65,
- "nm":"fingerprint_burn_in_Loop_02",
+ "nm":"fingerprint_burn_in_loop",
"ddd":0,
"assets":[
@@ -15,7 +15,7 @@
"ddd":0,
"ind":2,
"ty":4,
- "nm":"Fingerprint_20210701 Outlines 9",
+ "nm":"Fingerprint_20210701 Outlines 8",
"sr":1,
"ks":{
"o":{
@@ -164,13 +164,62 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
"lj":1,
"ml":10,
"bm":0,
+ "d":[
+ {
+ "n":"d",
+ "nm":"dash",
+ "v":{
+ "a":0,
+ "k":3,
+ "ix":1
+ }
+ },
+ {
+ "n":"o",
+ "nm":"offset",
+ "v":{
+ "a":1,
+ "k":[
+ {
+ "i":{
+ "x":[
+ 0.833
+ ],
+ "y":[
+ 0.833
+ ]
+ },
+ "o":{
+ "x":[
+ 0.167
+ ],
+ "y":[
+ 0.167
+ ]
+ },
+ "t":0,
+ "s":[
+ 0
+ ]
+ },
+ {
+ "t":360,
+ "s":[
+ -6
+ ]
+ }
+ ],
+ "ix":7
+ }
+ }
+ ],
"nm":"Stroke 1",
"mn":"ADBE Vector Graphic - Stroke",
"hd":false
@@ -241,403 +290,12 @@
},
"e":{
"a":0,
- "k":17,
+ "k":100,
"ix":2
},
"o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 246
- ]
- },
- {
- "t":360,
- "s":[
- 1326
- ]
- }
- ],
- "ix":3
- },
- "m":1,
- "ix":2,
- "nm":"Trim Paths 1",
- "mn":"ADBE Vector Filter - Trim",
- "hd":false
- },
- {
- "ty":"gr",
- "it":[
- {
- "ty":"tm",
- "s":{
- "a":0,
- "k":0,
- "ix":1
- },
- "e":{
- "a":0,
- "k":17,
- "ix":2
- },
- "o":{
- "a":0,
- "k":0,
- "ix":3
- },
- "m":1,
- "ix":1,
- "nm":"Trim Paths 1",
- "mn":"ADBE Vector Filter - Trim",
- "hd":false
- },
- {
- "ty":"tr",
- "p":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":2
- },
- "a":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":1
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100
- ],
- "ix":3
- },
- "r":{
- "a":0,
- "k":0,
- "ix":6
- },
- "o":{
- "a":0,
- "k":100,
- "ix":7
- },
- "sk":{
- "a":0,
- "k":0,
- "ix":4
- },
- "sa":{
- "a":0,
- "k":0,
- "ix":5
- },
- "nm":"Transform"
- }
- ],
- "nm":"Group 1",
- "np":1,
- "cix":2,
- "bm":0,
- "ix":3,
- "mn":"ADBE Vector Group",
- "hd":false
- }
- ],
- "ip":0,
- "op":600,
- "st":0,
- "bm":0
- },
- {
- "ddd":0,
- "ind":3,
- "ty":4,
- "nm":"Fingerprint_20210701 Outlines 8",
- "sr":1,
- "ks":{
- "o":{
- "a":0,
- "k":100,
- "ix":11
- },
- "r":{
- "a":0,
- "k":0,
- "ix":10
- },
- "p":{
- "a":0,
- "k":[
- 23.091,
- 32.5,
- 0
- ],
- "ix":2,
- "l":2
- },
- "a":{
- "a":0,
- "k":[
- 19.341,
- 24.25,
- 0
- ],
- "ix":1,
- "l":2
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100,
- 100
- ],
- "ix":6,
- "l":2
- }
- },
- "ao":0,
- "shapes":[
- {
- "ty":"gr",
- "it":[
- {
- "ind":0,
- "ty":"sh",
- "ix":1,
- "ks":{
- "a":0,
- "k":{
- "i":[
- [
- 0,
- 0
- ],
- [
- -1.701,
- 0.42
- ],
- [
- -1.757,
- 0
- ],
- [
- -1.577,
- -0.381
- ],
- [
- -1.485,
- -0.816
- ]
- ],
- "o":[
- [
- 1.455,
- -0.799
- ],
- [
- 1.608,
- -0.397
- ],
- [
- 1.719,
- 0
- ],
- [
- 1.739,
- 0.42
- ],
- [
- 0,
- 0
- ]
- ],
- "v":[
- [
- -9.818,
- 1.227
- ],
- [
- -5.064,
- -0.618
- ],
- [
- 0,
- -1.227
- ],
- [
- 4.96,
- -0.643
- ],
- [
- 9.818,
- 1.227
- ]
- ],
- "c":false
- },
- "ix":2
- },
- "nm":"Path 1",
- "mn":"ADBE Vector Shape - Group",
- "hd":false
- },
- {
- "ty":"st",
- "c":{
- "a":0,
- "k":[
- 1,
- 1,
- 1,
- 1
- ],
- "ix":3
- },
- "o":{
- "a":0,
- "k":100,
- "ix":4
- },
- "w":{
- "a":0,
- "k":1,
- "ix":5
- },
- "lc":2,
- "lj":1,
- "ml":10,
- "bm":0,
- "nm":"Stroke 1",
- "mn":"ADBE Vector Graphic - Stroke",
- "hd":false
- },
- {
- "ty":"tr",
- "p":{
- "a":0,
- "k":[
- 19.341,
- 7.477
- ],
- "ix":2
- },
- "a":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":1
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100
- ],
- "ix":3
- },
- "r":{
- "a":0,
- "k":0,
- "ix":6
- },
- "o":{
- "a":0,
- "k":100,
- "ix":7
- },
- "sk":{
- "a":0,
- "k":0,
- "ix":4
- },
- "sa":{
- "a":0,
- "k":0,
- "ix":5
- },
- "nm":"Transform"
- }
- ],
- "nm":"Top",
- "np":2,
- "cix":2,
- "bm":0,
- "ix":1,
- "mn":"ADBE Vector Group",
- "hd":false
- },
- {
- "ty":"tm",
- "s":{
"a":0,
"k":0,
- "ix":1
- },
- "e":{
- "a":0,
- "k":54,
- "ix":2
- },
- "o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 0
- ]
- },
- {
- "t":360,
- "s":[
- 1080
- ]
- }
- ],
"ix":3
},
"m":1,
@@ -645,257 +303,6 @@
"nm":"Trim Paths 1",
"mn":"ADBE Vector Filter - Trim",
"hd":false
- }
- ],
- "ip":0,
- "op":600,
- "st":0,
- "bm":0
- },
- {
- "ddd":0,
- "ind":4,
- "ty":4,
- "nm":"Fingerprint_20210701 Outlines 7",
- "sr":1,
- "ks":{
- "o":{
- "a":0,
- "k":100,
- "ix":11
- },
- "r":{
- "a":0,
- "k":0,
- "ix":10
- },
- "p":{
- "a":0,
- "k":[
- 23.091,
- 32.5,
- 0
- ],
- "ix":2,
- "l":2
- },
- "a":{
- "a":0,
- "k":[
- 19.341,
- 24.25,
- 0
- ],
- "ix":1,
- "l":2
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100,
- 100
- ],
- "ix":6,
- "l":2
- }
- },
- "ao":0,
- "shapes":[
- {
- "ty":"gr",
- "it":[
- {
- "ind":0,
- "ty":"sh",
- "ix":1,
- "ks":{
- "a":0,
- "k":{
- "i":[
- [
- 0,
- 0
- ],
- [
- -2.446,
- 1.161
- ],
- [
- -1.168,
- 0.275
- ],
- [
- -1.439,
- 0
- ],
- [
- -1.301,
- -0.304
- ],
- [
- -1.225,
- -0.66
- ],
- [
- -1.11,
- -1.844
- ]
- ],
- "o":[
- [
- 1.23,
- -2.044
- ],
- [
- 1.024,
- -0.486
- ],
- [
- 1.312,
- -0.31
- ],
- [
- 1.425,
- 0
- ],
- [
- 1.454,
- 0.34
- ],
- [
- 2.122,
- 1.143
- ],
- [
- 0,
- 0
- ]
- ],
- "v":[
- [
- -13.091,
- 3.273
- ],
- [
- -7.438,
- -1.646
- ],
- [
- -4.14,
- -2.797
- ],
- [
- 0,
- -3.273
- ],
- [
- 4.104,
- -2.805
- ],
- [
- 8.141,
- -1.29
- ],
- [
- 13.091,
- 3.273
- ]
- ],
- "c":false
- },
- "ix":2
- },
- "nm":"Path 1",
- "mn":"ADBE Vector Shape - Group",
- "hd":false
- },
- {
- "ty":"st",
- "c":{
- "a":0,
- "k":[
- 1,
- 1,
- 1,
- 1
- ],
- "ix":3
- },
- "o":{
- "a":0,
- "k":100,
- "ix":4
- },
- "w":{
- "a":0,
- "k":1,
- "ix":5
- },
- "lc":2,
- "lj":1,
- "ml":10,
- "bm":0,
- "nm":"Stroke 1",
- "mn":"ADBE Vector Graphic - Stroke",
- "hd":false
- },
- {
- "ty":"tr",
- "p":{
- "a":0,
- "k":[
- 19.341,
- 16.069
- ],
- "ix":2
- },
- "a":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":1
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100
- ],
- "ix":3
- },
- "r":{
- "a":0,
- "k":0,
- "ix":6
- },
- "o":{
- "a":0,
- "k":100,
- "ix":7
- },
- "sk":{
- "a":0,
- "k":0,
- "ix":4
- },
- "sa":{
- "a":0,
- "k":0,
- "ix":5
- },
- "nm":"Transform"
- }
- ],
- "nm":"Mid Top",
- "np":2,
- "cix":2,
- "bm":0,
- "ix":1,
- "mn":"ADBE Vector Group",
- "hd":false
},
{
"ty":"tm",
@@ -906,46 +313,17 @@
},
"e":{
"a":0,
- "k":38.2,
+ "k":100,
"ix":2
},
"o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 170
- ]
- },
- {
- "t":360,
- "s":[
- 890
- ]
- }
- ],
+ "a":0,
+ "k":0,
"ix":3
},
"m":1,
- "ix":2,
- "nm":"Trim Paths 1",
+ "ix":3,
+ "nm":"Trim Paths 2",
"mn":"ADBE Vector Filter - Trim",
"hd":false
}
@@ -957,7 +335,7 @@
},
{
"ddd":0,
- "ind":5,
+ "ind":3,
"ty":4,
"nm":"Fingerprint_20210701 Outlines 6",
"sr":1,
@@ -1132,13 +510,62 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
"lj":1,
"ml":10,
"bm":0,
+ "d":[
+ {
+ "n":"d",
+ "nm":"dash",
+ "v":{
+ "a":0,
+ "k":3,
+ "ix":1
+ }
+ },
+ {
+ "n":"o",
+ "nm":"offset",
+ "v":{
+ "a":1,
+ "k":[
+ {
+ "i":{
+ "x":[
+ 0.833
+ ],
+ "y":[
+ 0.833
+ ]
+ },
+ "o":{
+ "x":[
+ 0.167
+ ],
+ "y":[
+ 0.167
+ ]
+ },
+ "t":0,
+ "s":[
+ 0
+ ]
+ },
+ {
+ "t":360,
+ "s":[
+ -6
+ ]
+ }
+ ],
+ "ix":7
+ }
+ }
+ ],
"nm":"Stroke 1",
"mn":"ADBE Vector Graphic - Stroke",
"hd":false
@@ -1209,416 +636,12 @@
},
"e":{
"a":0,
- "k":34.2,
+ "k":100,
"ix":2
},
"o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 0
- ]
- },
- {
- "t":360,
- "s":[
- 720
- ]
- }
- ],
- "ix":3
- },
- "m":1,
- "ix":2,
- "nm":"Trim Paths 1",
- "mn":"ADBE Vector Filter - Trim",
- "hd":false
- }
- ],
- "ip":0,
- "op":600,
- "st":0,
- "bm":0
- },
- {
- "ddd":0,
- "ind":6,
- "ty":4,
- "nm":"Fingerprint_20210701 Outlines 5",
- "sr":1,
- "ks":{
- "o":{
- "a":0,
- "k":100,
- "ix":11
- },
- "r":{
- "a":0,
- "k":0,
- "ix":10
- },
- "p":{
- "a":0,
- "k":[
- 23.091,
- 32.5,
- 0
- ],
- "ix":2,
- "l":2
- },
- "a":{
- "a":0,
- "k":[
- 19.341,
- 24.25,
- 0
- ],
- "ix":1,
- "l":2
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100,
- 100
- ],
- "ix":6,
- "l":2
- }
- },
- "ao":0,
- "shapes":[
- {
- "ty":"gr",
- "it":[
- {
- "ind":0,
- "ty":"sh",
- "ix":1,
- "ks":{
- "a":0,
- "k":{
- "i":[
- [
- 0,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- -6.53,
- 0
- ],
- [
- 0,
- -5.793
- ],
- [
- 0,
- 0
- ],
- [
- 2.159,
- 0
- ],
- [
- 0.59,
- 1.489
- ],
- [
- 0,
- 0
- ],
- [
- 1.587,
- 0
- ],
- [
- 0,
- -2.16
- ],
- [
- -0.81,
- -1.363
- ],
- [
- -0.844,
- -0.674
- ],
- [
- 0,
- 0
- ]
- ],
- "o":[
- [
- -0.753,
- -2.095
- ],
- [
- 0,
- -5.793
- ],
- [
- 6.529,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- 0,
- 2.16
- ],
- [
- -1.604,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- -0.589,
- -1.489
- ],
- [
- -2.161,
- 0
- ],
- [
- 0,
- 1.62
- ],
- [
- 0.54,
- 0.909
- ],
- [
- 0,
- 0
- ],
- [
- 0,
- 0
- ]
- ],
- "v":[
- [
- -10.702,
- 5.728
- ],
- [
- -11.454,
- 1.506
- ],
- [
- 0.001,
- -9
- ],
- [
- 11.454,
- 1.506
- ],
- [
- 11.454,
- 1.817
- ],
- [
- 7.544,
- 5.728
- ],
- [
- 3.926,
- 3.273
- ],
- [
- 2.618,
- 0
- ],
- [
- -0.997,
- -2.454
- ],
- [
- -4.91,
- 1.457
- ],
- [
- -3.657,
- 6.014
- ],
- [
- -1.57,
- 8.412
- ],
- [
- -0.818,
- 9
- ]
- ],
- "c":false
- },
- "ix":2
- },
- "nm":"Path 1",
- "mn":"ADBE Vector Shape - Group",
- "hd":false
- },
- {
- "ty":"st",
- "c":{
- "a":0,
- "k":[
- 1,
- 1,
- 1,
- 1
- ],
- "ix":3
- },
- "o":{
- "a":0,
- "k":100,
- "ix":4
- },
- "w":{
- "a":0,
- "k":1,
- "ix":5
- },
- "lc":2,
- "lj":1,
- "ml":10,
- "bm":0,
- "nm":"Stroke 1",
- "mn":"ADBE Vector Graphic - Stroke",
- "hd":false
- },
- {
- "ty":"tr",
- "p":{
- "a":0,
- "k":[
- 19.341,
- 28.341
- ],
- "ix":2
- },
- "a":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":1
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100
- ],
- "ix":3
- },
- "r":{
- "a":0,
- "k":0,
- "ix":6
- },
- "o":{
- "a":0,
- "k":100,
- "ix":7
- },
- "sk":{
- "a":0,
- "k":0,
- "ix":4
- },
- "sa":{
- "a":0,
- "k":0,
- "ix":5
- },
- "nm":"Transform"
- }
- ],
- "nm":"Inside to dot ",
- "np":2,
- "cix":2,
- "bm":0,
- "ix":1,
- "mn":"ADBE Vector Group",
- "hd":false
- },
- {
- "ty":"tm",
- "s":{
"a":0,
"k":0,
- "ix":1
- },
- "e":{
- "a":0,
- "k":35,
- "ix":2
- },
- "o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- -159
- ]
- },
- {
- "t":360,
- "s":[
- 201
- ]
- }
- ],
"ix":3
},
"m":1,
@@ -1635,9 +658,9 @@
},
{
"ddd":0,
- "ind":7,
+ "ind":4,
"ty":4,
- "nm":"Fingerprint_20210701 Outlines 4",
+ "nm":"Fingerprint_20210701 Outlines 5",
"sr":1,
"ks":{
"o":{
@@ -1882,13 +905,62 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
"lj":1,
"ml":10,
"bm":0,
+ "d":[
+ {
+ "n":"d",
+ "nm":"dash",
+ "v":{
+ "a":0,
+ "k":3,
+ "ix":1
+ }
+ },
+ {
+ "n":"o",
+ "nm":"offset",
+ "v":{
+ "a":1,
+ "k":[
+ {
+ "i":{
+ "x":[
+ 0.833
+ ],
+ "y":[
+ 0.833
+ ]
+ },
+ "o":{
+ "x":[
+ 0.167
+ ],
+ "y":[
+ 0.167
+ ]
+ },
+ "t":0,
+ "s":[
+ 0
+ ]
+ },
+ {
+ "t":360,
+ "s":[
+ -6
+ ]
+ }
+ ],
+ "ix":7
+ }
+ }
+ ],
"nm":"Stroke 1",
"mn":"ADBE Vector Graphic - Stroke",
"hd":false
@@ -1959,416 +1031,12 @@
},
"e":{
"a":0,
- "k":9,
+ "k":100,
"ix":2
},
"o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 135
- ]
- },
- {
- "t":360,
- "s":[
- 495
- ]
- }
- ],
- "ix":3
- },
- "m":1,
- "ix":2,
- "nm":"Trim Paths 1",
- "mn":"ADBE Vector Filter - Trim",
- "hd":false
- }
- ],
- "ip":0,
- "op":600,
- "st":0,
- "bm":0
- },
- {
- "ddd":0,
- "ind":8,
- "ty":4,
- "nm":"Fingerprint_20210701 Outlines 3",
- "sr":1,
- "ks":{
- "o":{
- "a":0,
- "k":100,
- "ix":11
- },
- "r":{
- "a":0,
- "k":0,
- "ix":10
- },
- "p":{
- "a":0,
- "k":[
- 23.091,
- 32.5,
- 0
- ],
- "ix":2,
- "l":2
- },
- "a":{
- "a":0,
- "k":[
- 19.341,
- 24.25,
- 0
- ],
- "ix":1,
- "l":2
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100,
- 100
- ],
- "ix":6,
- "l":2
- }
- },
- "ao":0,
- "shapes":[
- {
- "ty":"gr",
- "it":[
- {
- "ind":0,
- "ty":"sh",
- "ix":1,
- "ks":{
- "a":0,
- "k":{
- "i":[
- [
- 0,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- -6.53,
- 0
- ],
- [
- 0,
- -5.793
- ],
- [
- 0,
- 0
- ],
- [
- 2.159,
- 0
- ],
- [
- 0.59,
- 1.489
- ],
- [
- 0,
- 0
- ],
- [
- 1.587,
- 0
- ],
- [
- 0,
- -2.16
- ],
- [
- -0.81,
- -1.363
- ],
- [
- -0.844,
- -0.674
- ],
- [
- 0,
- 0
- ]
- ],
- "o":[
- [
- -0.753,
- -2.095
- ],
- [
- 0,
- -5.793
- ],
- [
- 6.529,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- 0,
- 2.16
- ],
- [
- -1.604,
- 0
- ],
- [
- 0,
- 0
- ],
- [
- -0.589,
- -1.489
- ],
- [
- -2.161,
- 0
- ],
- [
- 0,
- 1.62
- ],
- [
- 0.54,
- 0.909
- ],
- [
- 0,
- 0
- ],
- [
- 0,
- 0
- ]
- ],
- "v":[
- [
- -10.702,
- 5.728
- ],
- [
- -11.454,
- 1.506
- ],
- [
- 0.001,
- -9
- ],
- [
- 11.454,
- 1.506
- ],
- [
- 11.454,
- 1.817
- ],
- [
- 7.544,
- 5.728
- ],
- [
- 3.926,
- 3.273
- ],
- [
- 2.618,
- 0
- ],
- [
- -0.997,
- -2.454
- ],
- [
- -4.91,
- 1.457
- ],
- [
- -3.657,
- 6.014
- ],
- [
- -1.57,
- 8.412
- ],
- [
- -0.818,
- 9
- ]
- ],
- "c":false
- },
- "ix":2
- },
- "nm":"Path 1",
- "mn":"ADBE Vector Shape - Group",
- "hd":false
- },
- {
- "ty":"st",
- "c":{
- "a":0,
- "k":[
- 1,
- 1,
- 1,
- 1
- ],
- "ix":3
- },
- "o":{
- "a":0,
- "k":100,
- "ix":4
- },
- "w":{
- "a":0,
- "k":1,
- "ix":5
- },
- "lc":2,
- "lj":1,
- "ml":10,
- "bm":0,
- "nm":"Stroke 1",
- "mn":"ADBE Vector Graphic - Stroke",
- "hd":false
- },
- {
- "ty":"tr",
- "p":{
- "a":0,
- "k":[
- 19.341,
- 28.341
- ],
- "ix":2
- },
- "a":{
- "a":0,
- "k":[
- 0,
- 0
- ],
- "ix":1
- },
- "s":{
- "a":0,
- "k":[
- 100,
- 100
- ],
- "ix":3
- },
- "r":{
- "a":0,
- "k":0,
- "ix":6
- },
- "o":{
- "a":0,
- "k":100,
- "ix":7
- },
- "sk":{
- "a":0,
- "k":0,
- "ix":4
- },
- "sa":{
- "a":0,
- "k":0,
- "ix":5
- },
- "nm":"Transform"
- }
- ],
- "nm":"Inside to dot ",
- "np":2,
- "cix":2,
- "bm":0,
- "ix":1,
- "mn":"ADBE Vector Group",
- "hd":false
- },
- {
- "ty":"tm",
- "s":{
"a":0,
"k":0,
- "ix":1
- },
- "e":{
- "a":0,
- "k":30,
- "ix":2
- },
- "o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 0
- ]
- },
- {
- "t":360,
- "s":[
- 360
- ]
- }
- ],
"ix":3
},
"m":1,
@@ -2385,7 +1053,7 @@
},
{
"ddd":0,
- "ind":9,
+ "ind":5,
"ty":4,
"nm":"Fingerprint_20210701 Outlines",
"sr":1,
@@ -2560,13 +1228,62 @@
},
"w":{
"a":0,
- "k":1,
+ "k":1.3,
"ix":5
},
"lc":2,
"lj":1,
"ml":10,
"bm":0,
+ "d":[
+ {
+ "n":"d",
+ "nm":"dash",
+ "v":{
+ "a":0,
+ "k":2.5,
+ "ix":1
+ }
+ },
+ {
+ "n":"o",
+ "nm":"offset",
+ "v":{
+ "a":1,
+ "k":[
+ {
+ "i":{
+ "x":[
+ 0.833
+ ],
+ "y":[
+ 0.833
+ ]
+ },
+ "o":{
+ "x":[
+ 0.167
+ ],
+ "y":[
+ 0.167
+ ]
+ },
+ "t":0,
+ "s":[
+ 0
+ ]
+ },
+ {
+ "t":360,
+ "s":[
+ -5
+ ]
+ }
+ ],
+ "ix":7
+ }
+ }
+ ],
"nm":"Stroke 1",
"mn":"ADBE Vector Graphic - Stroke",
"hd":false
@@ -2637,41 +1354,12 @@
},
"e":{
"a":0,
- "k":69,
+ "k":100,
"ix":2
},
"o":{
- "a":1,
- "k":[
- {
- "i":{
- "x":[
- 0.833
- ],
- "y":[
- 0.833
- ]
- },
- "o":{
- "x":[
- 0.167
- ],
- "y":[
- 0.167
- ]
- },
- "t":0,
- "s":[
- 0
- ]
- },
- {
- "t":360,
- "s":[
- 720
- ]
- }
- ],
+ "a":0,
+ "k":0,
"ix":3
},
"m":1,
@@ -2699,4 +1387,4 @@
"dr":0
}
]
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
index a25a47595fe7..a30a03a7e608 100644
--- a/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
+++ b/packages/SystemUI/res/raw/udfps_lockscreen_fp.json
@@ -1 +1 @@
-{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2.5]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]} \ No newline at end of file
+{"v":"5.7.8","fr":60,"ip":0,"op":46,"w":46,"h":65,"nm":"fingerprint_build_on","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Fingerprint_20210701 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[23.091,32.5,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999994755,0.949000000954,0.624000012875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.717999985639,0.948999980852,0.62400004069,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":24,"s":[2]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":210,"cm":"2","dr":0},{"tm":255,"cm":"1","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index daf4fdc7438e..a1684207746b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Gebruik jou vingerafdruk om voort te gaan"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Kan nie vingerafdruk herken nie. Gebruik eerder skermslot."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Soek tans vir jou …"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Gesig-ikoon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Versoenbaarheid-zoem se knoppie."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Netwerkbesonderhede"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tik op \'n netwerk om te koppel"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ontsluit om netwerke te bekyk"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Soek tans na netwerke …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kon nie aan netwerk koppel nie"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Sien alles"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 0125b665efde..c8184b6fbdb0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ለመቀጠል የእርስዎን የጣት አሻራ ይጠቀሙ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"የጣት አሻራን መለየት አልተቻለም። በምትኩ የማያ ገጽ መቆለፊያ ይጠቀሙ።"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"እርስዎን በመፈለግ ላይ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"የፊት አዶ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"የተኳኋኝአጉላ አዝራር።"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"የአውታረ መረብ ዝርዝሮች"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ለመገናኘት አንድ አውታረ መረብ መታ ያድርጉ"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"አውታረ መረቦችን በመፈለግ ላይ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ከአውታረ መረቡ ጋር መገናኘት አልተሳካም"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ሁሉንም ይመልከቱ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 06bc4d5829b1..7160498f9996 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"عليك استخدام بصمة الإصبع للمتابعة."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"يتعذّر التعرّف على بصمة الإصبع. عليك استخدام قفل الشاشة بدلاً من ذلك."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"جارٍ البحث عن وجهك…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"رمز الوجه"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"زر تكبير/تصغير للتوافق."</string>
@@ -1194,6 +1196,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"تفاصيل الشبكة"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"انقر على إحدى الشبكات للاتصال بالإنترنت"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"جارٍ البحث عن شبكات…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"تعذّر الاتصال بالشبكة."</string>
<string name="see_all_networks" msgid="3773666844913168122">"عرض الكل"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 2dd3195b862c..c60de5580e5b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব নোৱাৰি। তাৰ সলনি স্ক্ৰীন লক ব্যৱহাৰ কৰক।"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"মুখমণ্ডলৰ আইকন"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"উপযোগিতা অনুসৰি জুম কৰা বুটাম।"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"ৱাই-ফাই"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"নেটৱৰ্কৰ সবিশেষ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"সংযোগ কৰিবলৈ এটা নেটৱৰ্কত টিপক"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"নেটৱৰ্ক সন্ধান কৰি থকা হৈছে…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"নেটৱৰ্কৰ সৈতে সংযোগ কৰিব পৰা নগ\'ল"</string>
<string name="see_all_networks" msgid="3773666844913168122">"আটাইবোৰ চাওক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index b87b0334ab00..2ed55ce8a381 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tanımaq olmur. Barmaq izini işlədin."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Davam etmək üçün barmaq izinizi istifadə edin"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Barmaq izini tanımaq olmur. Əvəzində ekran kilidindən istifadə edin."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Siz axtarılırsınız…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Üz işarəsi"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Uyğunluq zoom düyməsi."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Şəbəkə məlumatları"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Qoşulmaq üçün şəbəkəyə toxunun"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Şəbəkə axtarılır…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Şəbəkəyə qoşulmaq alınmadı"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Hamısına baxı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 93e7c0c29c5f..202d9eaa0100 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Lice nije prepoznato. Koristite otisak prsta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Nastavite pomoću otiska prsta"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Prepoznavanje otiska prsta nije uspelo. Koristite zaključavanje ekrana umesto toga."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Tražimo vas…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona lica"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Dugme Zum kompatibilnosti."</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalji o mreži"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da biste se povezali"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte da biste videli mreže"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traže se mreže…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje sa mrežom nije uspelo"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Pogledajte sve"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index ea4012cedce2..c5624ae1d33e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Твар не распазнаны. Скарыстайце адбітак пальца."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Каб працягнуць, скарыстайце адбітак пальца"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Не ўдалося распазнаць адбітак пальца. Разблакіруйце экран іншым спосабам."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Ідзе пошук вашага твару…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Значок твару"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Кнопка сумяшчальнасці маштаба."</string>
@@ -1182,6 +1184,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Інфармацыя пра сетку"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Каб падключыцца, націсніце на сетку"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Выконваецца пошук сетак…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не ўдалося падключыцца да сеткі"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Паказаць усе"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 389e71a84545..d5f26e1d2f27 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лицето не е разпознато. Използвайте отпечатък."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Използвайте отпечатъка си, за да продължите"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Отпечатъкът не може да бъде разпознат. Вместо това използвайте опция за заключване на екрана."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Търсим ви…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Икона на лице"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Бутон за промяна на мащаба с цел съвместимост."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Подробности за мрежата"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Докоснете мрежа, за да се свържете"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Отключване с цел преглед на мрежите"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Търсят се мрежи…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Свързването с мрежата не бе успешно"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Вижте всички"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c856b8a31f5a..017441708d95 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"চালিয়ে যেতে আঙ্গুলের ছাপ ব্যবহার করুন"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"আঙ্গুলের ছাপ শনাক্ত করতে পারছি না। পরিবর্তে স্ক্রিন লক ব্যবহার করুন।"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"আপনার জন্য খোঁজা হচ্ছে…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ফেস আইকন"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"সামঞ্জস্যের জুম বোতাম৷"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"ওয়াই-ফাই"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"নেটওয়ার্কের বিবরণ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"কানেক্ট করতে একটি নেটওয়ার্কে ট্যাপ করুন"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"নেটওয়ার্ক সার্চ করা হচ্ছে…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"নেটওয়ার্কে কানেক্ট করা যায়নি"</string>
<string name="see_all_networks" msgid="3773666844913168122">"সবকটি দেখুন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 83a3e1453033..26a0c7a6777c 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nije moguće prepoznati lice. Koristite otisak prsta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Nastavite pomoću otiska prsta"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Nije moguće prepoznati otisak prsta. Umjesto toga koristite zaključavanje ekrana."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Tražimo vas…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona lica"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Dugme za uvećavanje u slučaju nekompatibilnosti."</string>
@@ -993,7 +995,7 @@
<string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ni internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi mreže."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vaš operater"</string>
<string name="touch_filtered_warning" msgid="8119511393338714836">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
- <string name="slice_permission_title" msgid="3262615140094151017">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+ <string name="slice_permission_title" msgid="3262615140094151017">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
<string name="slice_permission_text_1" msgid="6675965177075443714">"- Može čitati informacije iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="slice_permission_text_2" msgid="6758906940360746983">"- Može poduzeti radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="slice_permission_checkbox" msgid="4242888137592298523">"Dozvoli aplikaciji <xliff:g id="APP">%1$s</xliff:g> prikazivanje isječaka iz svake aplikacije"</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalji o mreži"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da se povežete"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte da vidite mreže"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traženje mreža…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje s mrežom nije uspjelo"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b008d4487848..86bbe2e160c3 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No podem detectar la cara. Usa l\'empremta digital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Fes servir l\'empremta digital per continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"No es pot reconèixer l\'empremta digital. Utilitza el bloqueig de pantalla."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"S\'està cercant la teva cara…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icona facial"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botó de zoom de compatibilitat."</string>
@@ -577,7 +579,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Has donat permís a una aplicació per configurar una connexió VPN.\n\nAquesta aplicació pot supervisar el dispositiu i l\'activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil de treball.\n\nL\'administrador pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador.\n\nA més, estàs connectat a una VPN, que també pot supervisar la teva activitat a la xarxa."</string>
- <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"El teu pare o la teva mare gestionen aquest dispositiu, i poden veure i gestionar informació com ara les aplicacions que utilitzes, la teva ubicació i el teu temps de connexió."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"El teu pare o mare gestionen aquest dispositiu, i poden veure i gestionar informació com ara les aplicacions que utilitzes, la teva ubicació i el teu temps de connexió."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalls de la xarxa"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca una xarxa per connectar-te"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueja per veure xarxes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"S\'estan cercant xarxes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"No s\'ha pogut connectar a la xarxa"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Mostra-ho tot"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ea9c4bb83bf0..ca96b6d18297 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Pokračujte přiložením prstu"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Otisk prstu se nepodařilo rozpoznat. Použijte místo něj zámek obrazovky."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Hledáme vás…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona obličeje"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
@@ -1182,6 +1184,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Podrobnosti sítě"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Klepněte na síť, ke které se chcete připojit"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sítě uvidíte po odemknutí"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Vyhledávání sítí…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Připojení k síti se nezdařilo"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Zobrazit vše"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index bf5f367120ca..d5de62537b3f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Brug dit fingeraftryk for at fortsætte"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Fingeraftrykket kan ikke genkendes. Brug skærmlåsen i stedet."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Forsøger at finde dig…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ansigt"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Knap for kompatibilitetszoom."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Netværksoplysninger"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tryk på et netværk for at oprette forbindelse"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås op for at se netværk"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søger efter netværk…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Der kunne ikke oprettes forbindelse til netværket"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4d662469094e..e1c091ce981d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Mithilfe deines Fingerabdrucks fortfahren"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Fingerabdruck wurde nicht erkannt. Verwende stattdessen die Displaysperre."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Wir suchen nach dir…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Gesichtssymbol"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Schaltfläche für Kompatibilitätszoom"</string>
@@ -1083,7 +1085,7 @@
<string name="controls_media_title" msgid="1746947284862928133">"Medien"</string>
<string name="controls_media_close_session" msgid="1193000643003066508">"Diese Mediensitzung ausblenden?"</string>
<string name="controls_media_active_session" msgid="3146882316024153337">"Die Mediensitzung kann nicht ausgeblendet werden."</string>
- <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ablehnen"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ausblenden"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
<string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wird gerade über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergegeben"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WLAN"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Netzwerkdetails"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tippe auf ein Netzwerk, um eine Verbindung herzustellen"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Netzwerke werden gesucht…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Netzwerkverbindung konnte nicht hergestellt werden"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Alle ansehen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 091105e054d9..13ebcb5b0842 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Χρησιμοποιήστε δακτυλ. αποτύπωμα για να συνεχίσετε"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Δεν είναι δυνατή η αναγνώριση του δακτυλικού αποτυπώματος. Χρησιμοποιήστε εναλλακτικά το κλείδωμα οθόνης."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Αναζήτηση για εσάς…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Εικονίδιο προσώπου"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Κουμπί εστίασης συμβατότητας."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Λεπτομέρειες δικτύου"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Πατήστε ένα δίκτυο για να συνδεθείτε"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ξεκλειδώστε για προβολή δικτύων"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Αναζήτηση δικτύων…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Αποτυχία σύνδεσης στο δίκτυο"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Εμφάνιση όλων"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 479ea06250cc..3c2abc1c978d 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use your fingerprint to continue"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Can’t recognise fingerprint. Use screen lock instead."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Looking for you…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Face icon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Compatibility zoom button."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string>
<string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index b148b09437a7..126549d291fc 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use your fingerprint to continue"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Can’t recognise fingerprint. Use screen lock instead."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Looking for you…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Face icon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Compatibility zoom button."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string>
<string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 479ea06250cc..3c2abc1c978d 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use your fingerprint to continue"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Can’t recognise fingerprint. Use screen lock instead."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Looking for you…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Face icon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Compatibility zoom button."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string>
<string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 479ea06250cc..3c2abc1c978d 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use your fingerprint to continue"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Can’t recognise fingerprint. Use screen lock instead."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Looking for you…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Face icon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Compatibility zoom button."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Network details"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tap a network to connect"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Unlock to view networks"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Searching for networks…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Failed to connect to network"</string>
<string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index a3fec1de19dd..e8f7e6b5ba80 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎Can’t recognize face. Use fingerprint instead.‎‏‎‎‏‎"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‏‎Use your fingerprint to continue‎‏‎‎‏‎"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎Can’t recognize fingerprint. Use screen lock instead.‎‏‎‎‏‎"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎Looking for you…‎‏‎‎‏‎"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎Face icon‎‏‎‎‏‎"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎Compatibility zoom button.‎‏‎‎‏‎"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎Wi‑Fi‎‏‎‎‏‎"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎Network details‎‏‎‎‏‎"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎Tap a network to connect‎‏‎‎‏‎"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎Unlock to view networks‎‏‎‎‏‎"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎Searching for networks…‎‏‎‎‏‎"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎Failed to connect to network‎‏‎‎‏‎"</string>
<string name="see_all_networks" msgid="3773666844913168122">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎See all‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 166e16d22f83..a12055c3c049 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce el rostro. Usa la huella dactilar."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utiliza tu huella dactilar para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"No se reconoce la huella dactilar. Utiliza el bloqueo de pantalla en su lugar."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Autenticando tu rostro…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ícono de rostro"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botón de zoom de compatibilidad"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalles de la red"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Presiona una red para conectarte a ella"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloquea para ver las redes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Se produjo un error al establecer conexión con la red"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3b06d9b6697b..0e71f7a9d3fb 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce la cara. Usa la huella digital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Usa tu huella digital para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"No se reconoce la huella digital. Usa el bloqueo de pantalla."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Buscando tu cara…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icono de cara"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botón de zoom de compatibilidad"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalles de la red"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca una red para conectarte"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloquea para ver redes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"No se ha podido conectar a la red"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 625b46618c0e..8ea0a2a9df6b 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Jätkamiseks kasutage sõrmejälge"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Sõrmejälge ei õnnestu tuvastada. Kasutage selle asemel ekraanilukku."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Otsitakse teid …"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Näoikoon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Sobivussuumi nupp."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Võrgu üksikasjad"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Puudutage ühendamiseks võrku"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Võrkude vaatamiseks avage"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Võrkude otsimine …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Võrguühenduse loomine ebaõnnestus"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Kuva kõik"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index fa50729129bd..09ee8d7aadcd 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -58,7 +58,7 @@
<string name="always_use_device" msgid="210535878779644679">"Ireki <xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g> konektatzen den guztietan"</string>
<string name="always_use_accessory" msgid="1977225429341838444">"Ireki <xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> konektatzen den guztietan"</string>
<string name="usb_debugging_title" msgid="8274884945238642726">"USB bidezko arazketa onartu?"</string>
- <string name="usb_debugging_message" msgid="5794616114463921773">"Ordenagailuaren RSA gakoaren erreferentzia-gako digitala hau da:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_message" msgid="5794616114463921773">"Ordenagailuaren RSA gakoaren aztarna digitala hau da:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="4003121804294739548">"Eman beti ordenagailu honetatik arazteko baimena"</string>
<string name="usb_debugging_allow" msgid="1722643858015321328">"Eman baimena"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Ez da onartzen USB bidezko arazketa"</string>
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ez da hauteman aurpegia. Erabili hatz-marka."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Aurrera egiteko, erabili hatz-marka"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Ez da hauteman hatz-marka. Erabili pantailaren blokeoa."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Zure bila…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Aurpegiaren ikonoa"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Zoom-bateragarritasunaren botoia."</string>
@@ -575,7 +577,7 @@
<string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
<string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Ireki kredentzial fidagarriak"</string>
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratzaileak sarearen erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
- <string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikazio bati VPN konexio bat konfiguratzeko baimena eman diozu.\n\nAplikazio horrek gailuko eta sareko jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
+ <string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikazio bati VPN bidezko konexio bat konfiguratzeko baimena eman diozu.\n\nAplikazio horrek gailuko eta sareko jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen du zure laneko profila.\n\nAdministratzaileak sareko jarduerak kontrola diezazkizuke, besteak beste, posta elektronikoa, aplikazioak eta webguneak.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nHorrez gain, VPN batera zaude konektatuta, eta hark ere kontrola ditzake zure sareko jarduerak."</string>
<string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikusi eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN konexioa"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wifia"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Sarearen xehetasunak"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Sakatu sare bat hartara konektatzeko"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sareak ikusteko, desblokeatu pantaila"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Sareak bilatzen…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ezin izan da konektatu sarera"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ikusi guztiak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 41e895b41828..2405ec6713e8 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"برای ادامه، از اثر انگشتتان استفاده کنید"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"اثر انگشت شناسایی نشد. درعوض از قفل صفحه استفاده کنید."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"درحال جستجوی شما…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"نماد چهره"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"دکمه بزرگ‌نمایی سازگار."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"جزئیات شبکه"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"برای اتصال به شبکه روی آن ضربه بزنید"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"برای مشاهده شبکه‌ها، قفل صفحه را باز کنید"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"درحال جستجوی شبکه…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"اتصال به شبکه برقرار نشد"</string>
<string name="see_all_networks" msgid="3773666844913168122">"مشاهده همه"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 76b245f0fdca..66b0d4e3fe73 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Jatka sormenjäljen avulla"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Sormenjälkeä ei voi tunnistaa. Käytä sen sijaan näytön lukitusta."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Etsitään kasvoja…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Kasvokuvake"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Yhteensopivuuszoomaus-painike."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Verkon tiedot"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Muodosta yhteys napauttamalla verkkoa"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Etsitään verkkoja…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Yhteyden muodostaminen verkkoon epäonnistui"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Näytä kaikki"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 788a319e75df..ccd63c7a3902 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utilisez votre empreinte digitale pour continuer"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Empreinte digitale non reconnue. Utilisez plutôt le verrouillage de l\'écran."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Recherche de votre visage…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icône de visage"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Bouton \"Zoom de compatibilité\""</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Détails du réseau"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Touchez un réseau pour vous y connecter"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Déverrouillez l\'écran pour afficher les réseaux Wi-Fi"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Recherche de réseaux en cours…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Échec de la connexion au réseau"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 645c9702aa33..cace9b5f9b57 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez votre empreinte."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utilisez votre empreinte pour continuer"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Empreinte non reconnue. Utilisez le verrouillage de l\'écran."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Recherche de votre visage…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icône représentant un visage"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Bouton \"Zoom de compatibilité\""</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Détails du réseau"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Appuyez sur un réseau pour vous connecter"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Déverrouiller pour afficher les réseaux"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Recherche de réseaux…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Échec de la connexion au réseau"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 88098a0d507a..09a7d7b12140 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utiliza a túa impresión dixital para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Non se puido recoñecer a impresión dixital. Mellor usa o bloqueo de pantalla."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Buscándote…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icona de cara"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botón de zoom de compatibilidade"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalles da rede"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toca unha rede para conectarte a ela"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Buscando redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Produciuse un erro ao conectarse á rede"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 2f098962d16c..2af29a370f2e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"આગળ વધવા માટે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ફિંગરપ્રિન્ટ ઓળખી શકતા નથી. તેને બદલે સ્ક્રીન લૉકનો ઉપયોગ કરો."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"તમારા માટે શોધી રહ્યાં છે..."</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ચહેરા આઇકન"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"સુસંગતતા ઝૂમ બટન."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"વાઇ-ફાઇ"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"નેટવર્કની વિગતો"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"કનેક્ટ કરવા માટે નેટવર્ક પર ટૅપ કરો"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"નેટવર્ક શોધી રહ્યાં છીએ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"નેટવર્ક સાથે કનેક્ટ કરવામાં નિષ્ફળ થયાં"</string>
<string name="see_all_networks" msgid="3773666844913168122">"બધા જુઓ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9b6ce4fa06a2..a5fb89b20f64 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"जारी रखने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"फ़िंगरप्रिंट पहचाना नहीं जा सका. इसके बजाय, स्क्रीन लॉक इस्तेमाल करके देखें."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"आपको पहचान रहा है…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"चेहरे का आइकॉन"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"संगतता ज़ूम बटन."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"वाई-फ़ाई"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्क की जानकारी"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"इंटरनेट से कनेक्ट करने के लिए, किसी नेटवर्क पर टैप करें"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"नेटवर्क देखने के लिए, स्क्रीन को अनलॉक करें"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्क खोजे जा रहे हैं…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्क से कनेक्ट नहीं किया जा सका"</string>
<string name="see_all_networks" msgid="3773666844913168122">"सभी देखें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2892e66099ae..3a047770b3dc 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Nastavite pomoću otiska prsta"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Prepoznavanje otiska prsta nije uspjelo. Umjesto toga upotrebljavajte zaključavanje zaslona."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Tražimo vas…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona lica"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Gumb za kompatibilnost zumiranja."</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Pojedinosti o mreži"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Dodirnite mrežu da biste se povezali"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Otključajte za prikaz mreža"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Traženje mreža…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Povezivanje s mrežom nije uspjelo"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 079c915b7ea7..37aa4add6faa 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"A folytatáshoz használja ujjlenyomatát"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Az ujjlenyomat nem ismerhető fel. Használja inkább a képernyőzárat."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Keresem az Ön arcát…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Arcikon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Kompatibilitási zoom gomb."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Hálózati információk"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"A kapcsolódáshoz koppintson a kívánt hálózatra"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Zárolás feloldása a hálózatok megtekintéséhez"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Hálózatok keresése…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nem sikerült hálózathoz csatlakozni."</string>
<string name="see_all_networks" msgid="3773666844913168122">"Megtekintés"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 7df2efb7d8bc..80c8f3ff387c 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Շարունակելու համար անհրաժեշտ է ձեր մատնահետքը"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Մատնահետքը չի հաջողվում ճանաչել։ Օգտագործեք էկրանի կողպումը։"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Դեմքի ճանաչում…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Դեմքի պատկերակ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Համատեղելիության խոշորացման կոճակը:"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Ցանցի տվյալներ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Հպեք ցանցին՝ միանալու համար"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ապակողպեք՝ ցանցերը դիտելու համար"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ցանցերի որոնում…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Չհաջողվեց միանալ ցանցին"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Տեսնել բոլորը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 07a567261b7d..11a1279b4e13 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Gunakan sidik jari untuk melanjutkan"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Tidak dapat mengenali sidik jari. Gunakan kunci layar."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Mencari wajah Anda…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikon wajah"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Tombol perbesar/perkecil kompatibilitas."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detail jaringan"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ketuk jaringan untuk menghubungkan"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Buka kunci untuk melihat jaringan"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Mencari jaringan …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Gagal menghubungkan ke jaringan"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index fbcbddbe0fa5..933fa2800201 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Notaðu fingrafarið þitt til að halda áfram"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Fingrafar þekkist ekki. Notaðu skjálás í staðinn."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Leitar að þér ..."</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Andlitstákn"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Hnappur fyrir samhæfisaðdrátt."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Upplýsingar um net"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ýttu á net til að tengjast"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Taktu úr lás til að skoða netkerfi"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Leitar að netum…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ekki tókst að tengjast neti"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Sjá allt"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 52b5879357f9..8ab437e5ee9d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utilizza la tua impronta per continuare"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Impossibile riconoscere l\'impronta. Usa il blocco schermo."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"In attesa del volto…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Icona volto"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Pulsante zoom compatibilità."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Dettagli rete"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tocca una rete per connetterti"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Sblocca per visualizzare le reti"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ricerca di reti in corso…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Connessione alla rete non riuscita"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Mostra tutte"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 7dce35073441..d1706cabfa70 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"יש להשתמש בטביעת האצבע כדי להמשיך"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"לא ניתן לזהות את טביעת האצבע. יש להשתמש בנעילת המסך במקום."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"מתבצע חיפוש…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"סמל הפנים"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"לחצן מרחק מתצוגה של תאימות."</string>
@@ -1182,6 +1184,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"פרטי הרשת"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"צריך להקיש על רשת כדי להתחבר"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"בתהליך חיפוש רשתות…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"נכשל הניסיון להתחבר לרשת"</string>
<string name="see_all_networks" msgid="3773666844913168122">"הצגת הכול"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 47aabbbb3bbd..e124b9c2b3bb 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"顔を認識できません。指紋認証を使用してください。"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"続行するには指紋認証を使用してください"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"指紋を認識できません。代わりに画面ロックを使用してください。"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"顔を認証しています…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"顔アイコン"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"互換ズームボタン。"</string>
@@ -799,7 +801,7 @@
<item quantity="other">%d分</item>
<item quantity="one">%d分</item>
</plurals>
- <string name="battery_panel_title" msgid="5931157246673665963">"電池の使用状況"</string>
+ <string name="battery_panel_title" msgid="5931157246673665963">"バッテリーの使用状況"</string>
<string name="battery_detail_charging_summary" msgid="8821202155297559706">"充電中はバッテリー セーバーは利用できません"</string>
<string name="battery_detail_switch_title" msgid="6940976502957380405">"バッテリー セーバー"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"パフォーマンスとバックグラウンド データを制限します"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ネットワークの詳細"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ネットワークをタップして接続"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ネットワークを表示するにはロック解除してください"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ネットワークを検索しています…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ネットワークに接続できませんでした"</string>
<string name="see_all_networks" msgid="3773666844913168122">"すべて表示"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4b9ab21126b1..bf04ac574030 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"თითის ანაბეჭდის ამოცნობა ვერ ხერხდება. სანაცვლოდ, გამოიყენეთ ეკრანის დაბლოკვა."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"მიმდინარეობს თქვენი ძიება…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"სახის ხატულა"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"თავსებადი მასშტაბირების ღილაკი."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ქსელის დეტალები"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"დასაკავშირებლად შეეხეთ ქსელს"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"განბლოკვა ქსელების სანახავად"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"მიმდინარეობს ქსელების ძიება…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ქსელთან დაკავშირება ვერ ხერხდება"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ყველას ნახვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index e9d6067cfdff..9085de7ec8e8 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Жалғастыру үшін саусақ ізін пайдаланыңыз."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Саусақ ізі танылмады. Орнына экран құлпын пайдаланыңыз."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Бет ізделуде…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Бет белгішесі"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Үйлесімділік ұлғайту түймесі."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Желі деректері"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Желіге қосылу үшін оны түртіңіз."</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Желілерді көру үшін құлыпты ашыңыз."</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Маңайдағы желілер ізделуде…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Желіге қосылмады."</string>
<string name="see_all_networks" msgid="3773666844913168122">"Барлығын көру"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 52d91f3aec98..24be69d37730 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ប្រើ​ស្នាមម្រាមដៃ​របស់អ្នក ដើម្បីបន្ត"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"មិនអាចសម្គាល់​ស្នាមម្រាមដៃបានទេ។ សូមប្រើសោ​អេក្រង់ជំនួសវិញ។"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"កំពុងស្វែងរកអ្នក…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"រូប​ផ្ទៃមុខ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ព័ត៌មាន​លម្អិត​អំពីបណ្ដាញ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ចុចលើបណ្ដាញណាមួយ ដើម្បីភ្ជាប់"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ដោះសោ​ដើម្បីមើល​បណ្ដាញ"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"កំពុងស្វែងរកបណ្ដាញ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"មិន​អាច​ភ្ជាប់​បណ្ដាញ​បានទេ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"មើលទាំងអស់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index f23153d7011a..7600f5081ec1 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಬದಲಾಗಿ ಪರದೆಲಾಕ್ ಬಳಸಿ."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ಮುಖದ ಐಕಾನ್‌"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"ವೈ‑ಫೈ"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ನೆಟ್‌ವರ್ಕ್ ವಿವರಗಳು"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ಕನೆಕ್ಟ್ ಮಾಡಲು ಒಂದು ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ನೆಟ್‌ವರ್ಕ್‌ಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3344ddc82d6c..598c20603f59 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"계속하려면 지문을 사용하세요."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"지문을 인식할 수 없습니다. 화면 잠금을 대신 사용하세요."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"찾는 중..."</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"얼굴 아이콘"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"호환성 확대/축소 버튼입니다."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"네트워크 세부정보"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"연결하려면 네트워크를 탭하세요"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"네트워크 검색 중…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"네트워크에 연결하지 못했습니다."</string>
<string name="see_all_networks" msgid="3773666844913168122">"모두 보기"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index f7a40b6ac712..04d5fabb9ef9 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Улантуу үчүн манжаңызды сканерге тийгизиңиз"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Манжа изи таанылбай жатат. Эрканды кулпулоо функциясын колдонуңуз."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Жүзүңүз изделүүдө…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Жүздүн сүрөтчөсү"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Масштабды сыйыштыруу баскычы."</string>
@@ -707,11 +709,11 @@
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"Эскертмелерди башкаруу каражаттары"</string>
<string name="tuner_full_importance_settings_on" msgid="917981436602311547">"Күйүк"</string>
<string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"Өчүк"</string>
- <string name="power_notification_controls_description" msgid="1334963837572708952">"Бул функциянын жардамы менен, ар бир колдонмо үчүн билдирменин маанилүүлүгүн 0дон 5ке чейин бааласаңыз болот. \n\n"<b>"5-деңгээл"</b>" \n- Билдирмелер тизмесинин өйдө жагында көрсөтүлөт \n- Билдирмелер толук экранда көрсөтүлөт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"4-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"3-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n\n"<b>"2-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n\n"<b>"1-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n- Кулпуланган экрандан жана абал тилкесинен жашырылат \n- Билдирмелер тизмесинин ылдый жагында көрсөтүлөт \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык билдирмелер бөгөттөлөт"</string>
+ <string name="power_notification_controls_description" msgid="1334963837572708952">"Бул функциянын жардамы менен, ар бир колдонмо үчүн билдирменин маанилүүлүгүн 0дон 5ке чейин бааласаңыз болот. \n\n"<b>"5-деңгээл"</b>" \n- Билдирмелер тизмесинин өйдө жагында көрүнөт \n- Билдирмелер толук экранда көрүнөт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"4-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"3-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n\n"<b>"2-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n\n"<b>"1-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n- Кулпуланган экрандан жана абал тилкесинен жашырылат \n- Билдирмелер тизмесинин ылдый жагында көрүнөт \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык билдирмелер бөгөттөлөт"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"Билдирмелер"</string>
<string name="notification_channel_disabled" msgid="928065923928416337">"Мындан ары бул билдирмелер сизге көрүнбөйт"</string>
<string name="notification_channel_minimized" msgid="6892672757877552959">"Бул билдирмелер кичирейтилет"</string>
- <string name="notification_channel_silenced" msgid="1995937493874511359">"Бул билдирмелер үнсүз көрсөтүлөт"</string>
+ <string name="notification_channel_silenced" msgid="1995937493874511359">"Бул билдирмелер үнсүз көрүнөт"</string>
<string name="notification_channel_unsilenced" msgid="94878840742161152">"Бул билдирмелер тууралуу кабарлап турабыз"</string>
<string name="inline_blocking_helper" msgid="2891486013649543452">"Адатта мындай билдирмелерди өткөрүп жибересиз. \nАлар көрүнө берсинби?"</string>
<string name="inline_done_button" msgid="6043094985588909584">"Бүттү"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Тармактын чоо-жайы"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Кайсы тармакка туташасыз?"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Тармактарды көрүү үчүн кулпусун ачыңыз"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Тармактар изделүүдө…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Тармакка туташпай калды"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Баарын көрүү"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index d2ac9effa3db..e554e1ab7cec 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ກະລຸນາໃຊ້ລາຍນິ້ວມືຂອງທ່ານເພື່ອສືບຕໍ່"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ບໍ່ສາມາດຈຳແນກລາຍນິ້ວມືໄດ້. ກະລຸນາໃຊ້ການລອກໜ້າຈໍແທນ."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ກຳລັງຊອກຫາທ່ານ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ໄອຄອນໃບໜ້າ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ລາຍລະອຽດເຄືອຂ່າຍ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ແຕະເຄືອຂ່າຍໃດໜຶ່ງເພື່ອເຊື່ອມຕໍ່"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ປົດລັອກເພື່ອເບິ່ງເຄືອຂ່າຍ"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ກຳລັງຊອກຫາເຄືອຂ່າຍ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ເຊື່ອມຕໍ່ເຄືອຂ່າຍບໍ່ສຳເລັດ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ເບິ່ງທັງໝົດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3101235d0201..1380cf665b3e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Jei norite tęsti, naudokite kontrolinį kodą"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Nepavyko atpažinti kontrolinio kodo. Naudokite ekrano užraktą."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Ieškoma jūsų…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Veido piktograma"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Suderinamumo priartinimo mygtukas."</string>
@@ -1182,6 +1184,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Išsami tinklo informacija"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Palieskite tinklą, kad prisijungtumėte"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ieškoma tinklų…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Jungiantis prie tinklo įvyko klaida"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Žiūrėti viską"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9c58eaf5693d..a6f90b1c97d0 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Lai turpinātu, izmantojiet pirksta nospiedumu."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Nevar atpazīt pirksta nospiedumu. Izmantojiet ekrāna bloķēšanu."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Notiek jūsu sejas meklēšana…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Sejas ikona"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Saderības tālummaiņas poga."</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Dati par tīklu"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Pieskarieties tīklam, lai izveidotu savienojumu"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lai skatītu tīklus, atbloķējiet"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Notiek tīklu meklēšana…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Neizdevās izveidot savienojumu ar tīklu"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Visu tīklu skatīšana"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index fc14cbab035d..4c35a471731a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Употребете го отпечатокот за да продолжите"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Не се препознава отпечатокот. Користете заклучување екран."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Ве бараме вас…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Икона за лице"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Копче за компатибилност на зум."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Детали за мрежата"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Допрете на мрежа за да се поврзете"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Отклучете за да се прикажат мрежите"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Се пребаруваат мрежи…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не успеа да се поврзе на мрежата"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Прикажи ги сите"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 4f908026c378..1394fc88c749 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"തുടരുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ഫിംഗർപ്രിന്റ് തിരിച്ചറിയാനാകുന്നില്ല. പകരം സ്‌ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"നിങ്ങൾക്കായി തിരയുന്നു…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"മുഖത്തിന്റെ ഐക്കൺ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"വൈഫൈ"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"നെറ്റ്‌വർക്ക് വിശദാംശങ്ങൾ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"കണക്‌റ്റ് ചെയ്യാൻ ഒരു നെറ്റ്‌വർക്കിൽ ടാപ്പ് ചെയ്യുക"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"നെറ്റ്‌വർക്കുകൾ കാണാൻ അൺ‌ലോക്ക് ചെയ്യുക"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"നെറ്റ്‌വർക്കുകൾ തിരയുന്നു…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"നെറ്റ്‌വർക്കിൽ കണക്റ്റ് ചെയ്യാനായില്ല"</string>
<string name="see_all_networks" msgid="3773666844913168122">"എല്ലാം കാണുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index b079d86dc919..97c87264cce3 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Үргэлжлүүлэхийн тулд хурууныхаа хээг ашиглана уу"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Хурууны хээг таних боломжгүй. Оронд нь дэлгэцийн түгжээ ашиглана уу."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Таныг хайж байна…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Царайны дүрс тэмдэг"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Тохиромжтой өсгөх товч."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Сүлжээний дэлгэрэнгүй мэдээлэл"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Холбогдохын тулд сүлжээг товшино уу"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Сүлжээг харахын тулд түгжээг тайлах"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Сүлжээ хайж байна…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Сүлжээнд холбогдож чадсангүй"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Бүгдийг харах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 0e8de9594293..80da2207692b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -148,7 +148,7 @@
<string name="voice_assist_label" msgid="3725967093735929020">"व्हॉइस सहाय्य उघडा"</string>
<string name="camera_label" msgid="8253821920931143699">"कॅमेरा उघडा"</string>
<string name="cancel" msgid="1089011503403416730">"रद्द करा"</string>
- <string name="biometric_dialog_confirm" msgid="2005978443007344895">"खात्री करा"</string>
+ <string name="biometric_dialog_confirm" msgid="2005978443007344895">"कंफर्म करा"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"पुन्हा प्रयत्न करा"</string>
<string name="biometric_dialog_empty_space_description" msgid="3330555462071453396">"ऑथेंटिकेशन रद्द करण्यासाठी टॅप करा"</string>
<string name="biometric_dialog_face_icon_description_idle" msgid="4351777022315116816">"कृपया पुन्हा प्रयत्न करा"</string>
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"पुढे सुरू ठेवण्‍यासाठी तुमची फिंगरप्रिंट वापरा"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"फिंगरप्रिंट ओळखता आली नाही. त्याऐवजी स्क्रीन लॉक वापरा."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"तुमच्यासाठी शोधत आहे…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"चेहरा आयकन"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"सुसंगतता झूम बटण."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"वाय-फाय"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्कचे तपशील"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"कनेक्ट करण्यासाठी नेटवर्कवर टॅप करा"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्क शोधत आहे…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्कशी कनेक्‍ट करता आले नाही"</string>
<string name="see_all_networks" msgid="3773666844913168122">"सर्व पहा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 955754ab97f9..3195d89c8570 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak mengenali wajah. Gunakan cap jari."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Gunakan cap jari anda untuk teruskan"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Tidak mengenali cap jari. Sebaliknya, gunakan kunci skrin."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Mencari anda…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikon wajah"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Butang zum keserasian."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Butiran rangkaian"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ketik rangkaian untuk membuat sambungan"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Buka kunci untuk melihat rangkaian"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Mencari rangkaian…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Gagal menyambung kepada rangkaian"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 968f6db4c446..53e1ffab3717 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ရှေ့ဆက်ရန် သင့်လက်ဗွေကို သုံးပါ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"လက်ဗွေကို မမှတ်မိပါ။ ဖန်သားပြင်လော့ခ်ချခြင်းကို အစားထိုးသုံးပါ။"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"သင့်ကို ရှာဖွေနေသည်…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"မျက်နှာသင်္ကေတ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"အံဝင်ခွင်ကျ ဇူးမ်ခလုတ်"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ကွန်ရက် အသေးစိတ်များ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ချိတ်ဆက်ရန် ကွန်ရက်ကို တို့ပါ"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ကွန်ရက်များကြည့်ရန် ဖွင့်ပါ"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ကွန်ရက်များကို ရှာဖွေနေသည်…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ကွန်ရက်သို့ ချိတ်ဆက်၍မရပါ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"အားလုံးကြည့်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1f8a01bdfd17..39bb80be6510 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Bruk fingeravtrykket for å fortsette"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Fingeravtrykket gjenkjennes ikke. Bruk skjermlås i stedet."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Ser etter deg …"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ansiktikon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Zoomknapp for kompatibilitet."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Nettverksdetaljer"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Trykk på et nettverk for å koble til"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås opp for å se nettverk"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Søker etter nettverk …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kunne ikke koble til nettverket"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index a142df8ed9de..f245cbb01061 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"जारी राख्न आफ्नो फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"फिंगरप्रिन्ट पहिचान गर्न सकिएन। बरु स्क्रिन लक प्रयोग गर्नुहोस्।"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"तपाईंलाई खोज्दै…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"अनुहारको आइकन"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"मिलाउने जुम बटन।"</string>
@@ -452,8 +454,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
<string name="tap_again" msgid="1315420114387908655">"फेरि ट्याप गर्नुहोस्"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"खोल्न माथितिर स्वाइप गर्नुहोस्"</string>
- <!-- no translation found for keyguard_unlock_press (8488350566398524740) -->
- <skip />
+ <string name="keyguard_unlock_press" msgid="8488350566398524740">"अनलक गर्न प्रेस गर्नुहोस्"</string>
<string name="keyguard_retry" msgid="886802522584053523">"फेरि प्रयास गर्न माथितिर स्वाइप गर्नुहोस्"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"NFC प्रयोग गर्न स्क्रिन अनलक गर्नुहोस्"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"यो डिभाइस तपाईंको सङ्गठनको स्वामित्वमा छ"</string>
@@ -1171,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"नेटवर्कसम्बन्धी विवरण"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"इन्टरनेट कनेक्ट गर्न कुनै नेटवर्कमा ट्याप गर्नुहोस्"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"नेटवर्कहरू खोजिँदै छन्…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"नेटवर्कमा कनेक्ट गर्न सकिएन"</string>
<string name="see_all_networks" msgid="3773666844913168122">"सबै नेटवर्क हेर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e75151262365..5d98fa7fc5c2 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Gebruik je vingerafdruk om door te gaan."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Vingerafdruk niet herkend. Gebruik in plaats daarvan de schermvergrendeling."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Jouw gezicht zoeken…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Gezichtspictogram"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Knop voor compatibiliteitszoom."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Netwerkgegevens"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tik op een netwerk om verbinding te maken"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ontgrendel het scherm om netwerken te bekijken"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Netwerken zoeken…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Kan geen verbinding maken met het netwerk"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Alles tonen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 5763a341cec5..6cb4412e63b5 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ଟିପଚିହ୍ନକୁ ଚିହ୍ନଟ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ମୁହଁ ଆଇକନ୍"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"କମ୍ପାଟିବିଲିଟୀ ଜୁମ୍ ବଟନ୍।"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"ୱାଇ-ଫାଇ"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ନେଟୱାର୍କ ବିବରଣୀ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ସଂଯୋଗ କରିବାକୁ ଏକ ନେଟୱାର୍କରେ ଟାପ୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ନେଟୱାର୍କଗୁଡ଼ିକ ସନ୍ଧାନ କରାଯାଉଛି…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ନେଟୱାର୍କକୁ ସଂଯୋଗ କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ସବୁ ଦେଖନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0fe6f8a6b64c..110a3eed90c3 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪਛਾਣ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ।"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ਤੁਹਾਡੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ਅਨੁਰੂਪਤਾ ਜ਼ੂਮ ਬਟਨ।"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"ਵਾਈ-ਫਾਈ"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ਨੈੱਟਵਰਕ ਵੇਰਵੇ"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"ਕਨੈਕਟ ਕਰਨ ਲਈ ਕਿਸੇ ਨੈੱਟਵਰਕ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ਨੈੱਟਵਰਕ ਖੋਜੇ ਜਾ ਰਹੇ ਹਨ…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ਸਭ ਦੇਖੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 220cd806c188..d4eeab0d2d56 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Użyj odcisku palca, aby kontynuować"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Nie rozpoznaję odcisku palca. Użyj blokady ekranu."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Szukam Cię…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona twarzy"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Przycisk powiększenia na potrzeby zgodności."</string>
@@ -1182,6 +1184,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Szczegóły sieci"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Kliknij sieć, aby połączyć"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odblokuj, by wyświetlić sieci"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Szukam sieci…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nie udało się połączyć z siecią"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Pokaż wszystko"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 39911ca2d76d..6017eaef5753 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use sua impressão digital para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Não foi possível reconhecer a impressão digital. Use o bloqueio de tela."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Procurando você…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ícone facial"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botão de zoom da compatibilidade."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque em uma rede para se conectar"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Procurando redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Falha ao conectar à rede"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d475e5d97b9a..b3207c84752f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impos. reconh. rosto. Utilize a impressão digital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Utilize a sua impressão digital para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Não é possível reconhecer a impressão digital. Em alternativa, utilize o bloqueio de ecrã."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"À sua procura…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ícone de rosto"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botão zoom de compatibilidade."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque numa rede para estabelecer ligação"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"A procurar redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Não foi possível estabelecer ligação à rede"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Veja tudo"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 39911ca2d76d..6017eaef5753 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Use sua impressão digital para continuar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Não foi possível reconhecer a impressão digital. Use o bloqueio de tela."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Procurando você…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ícone facial"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Botão de zoom da compatibilidade."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalhes da rede"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Toque em uma rede para se conectar"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Desbloqueie para ver as redes"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Procurando redes…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Falha ao conectar à rede"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 26a8cce72294..b64eed5a6637 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Chipul nu a fost recunoscut. Folosiți amprenta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Folosiți amprenta pentru a continua"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Amprenta nu a fost recunoscută. Folosiți blocarea ecranului."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Vă căutăm…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Pictograma chip"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Buton zoom pentru compatibilitate."</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detalii despre rețea"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Atingeți o rețea pentru a vă conecta"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Deblocați pentru a vedea rețelele"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Se caută rețele…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nu s-a realizat conexiunea la rețea"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Afișează-le pe toate"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 533b81c03801..f99e52a05a72 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не удалось распознать лицо. Используйте отпечаток."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Чтобы продолжить, прикоснитесь пальцем к сканеру."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Не удалось распознать отпечаток пальца. Используйте другой способ разблокировки экрана."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Поиск лица…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Значок лица"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Кнопка масштабирования (режим совместимости)"</string>
@@ -1182,6 +1184,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Сведения о сети"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Выберите сеть, чтобы подключиться"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Поиск сетей…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не удалось подключиться к сети"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Показать все"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 63baa6d1c574..f6645f261007 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ඉදිරියට යාමට ඔබගේ ඇඟිලි සලකුණ භාවිත කරන්න"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ඇඟිලි සලකුණ හඳුනා ගත නොහැකිය. ඒ වෙනුවට තිර අගුල භාවිත කරන්න."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"ඔබව සොයමින්…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"මුහුණ නිරූපකය"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ගැළපෙන විශාලන බොත්තම."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"ජාල විස්තර"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"සම්බන්ධ වීමට ජාලයක් තට්ටු කරන්න"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ජාල බැලීමට අගුලු හරින්න"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ජාල සඳහා සොයමින්…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"ජාලය වෙත සම්බන්ධ වීම අසාර්ථක විය"</string>
<string name="see_all_networks" msgid="3773666844913168122">"සියල්ල බලන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 3a2208594802..f4b657ee8e0b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Pokračujte nasnímaním odtlačku prsta"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Odtlačok prsta sa nedá rozpoznať. Použite radšej zámku obrazovky."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Hľadáme vás…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona tváre"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
@@ -1182,6 +1184,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Podrobnosti siete"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ak sa chcete pripojiť, klepnite na sieť"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odomknutím si zobrazte siete"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Vyhľadávajú sa siete…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Nepodarilo sa pripojiť k sieti"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Zobraziť všetko"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 5b8f826bb9d0..05022d2a72e6 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Uporabite prstni odtis, če želite nadaljevati."</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Prstnega odtisa ni mogoče prepoznati. Uporabite odklepanje s poverilnico."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Preverjanje vašega obraza …"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona obraza"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Gumb povečave za združljivost."</string>
@@ -1182,6 +1184,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Podatki o omrežju"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Za vzpostavitev povezave se dotaknite omrežja."</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Odklenite za ogled omrežij"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Iskanje omrežij …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Vzpostavljanje povezave z omrežjem ni uspelo."</string>
<string name="see_all_networks" msgid="3773666844913168122">"Prikaz vseh omrežij"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index dab089512d4d..0d197cc66f54 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Përdor gjurmën e gishtit për të vazhduar"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Nuk mund ta dallojë gjurmën e gishtit. Përdor më mirë kyçjen e ekranit."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Po të kërkojmë…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ikona e fytyrës"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Butoni i zmadhimit të pajtueshmërisë."</string>
@@ -452,8 +454,7 @@
<string name="notification_tap_again" msgid="4477318164947497249">"Trokit përsëri për ta hapur"</string>
<string name="tap_again" msgid="1315420114387908655">"Trokit sërish"</string>
<string name="keyguard_unlock" msgid="8031975796351361601">"Rrëshqit lart për ta hapur"</string>
- <!-- no translation found for keyguard_unlock_press (8488350566398524740) -->
- <skip />
+ <string name="keyguard_unlock_press" msgid="8488350566398524740">"Shtyp për të hapur"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Rrëshqit lart për të provuar përsëri"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"Shkyçe për të përdorur NFC-në"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Kjo pajisje i përket organizatës sate"</string>
@@ -1171,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Detajet e rrjetit"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Trokit te një rrjet për t\'u lidhur"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Po kërkon për rrjete…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Lidhja me rrjetin dështoi"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Shiko të gjitha"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index e5ec321338a0..eab01649f153 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лице није препознато. Користите отисак прста."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Наставите помоћу отиска прста"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Препознавање отиска прста није успело. Користите закључавање екрана уместо тога."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Тражимо вас…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Икона лица"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Дугме Зум компатибилности."</string>
@@ -1176,6 +1178,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WiFi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Детаљи о мрежи"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Додирните мрежу да бисте се повезали"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Откључајте да бисте видели мреже"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Траже се мреже…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Повезивање са мрежом није успело"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Погледајте све"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e7b41f5502ec..c4bddb897c86 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet kändes inte igen. Använd fingeravtryck."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Fortsätt med hjälp av ditt fingeravtryck"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Fingeravtrycket kändes inte igen. Använd låsskärmen i stället."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Håller utkik efter dig …"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Ansiktsikon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Knapp för kompatibilitetszoom."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wifi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Nätverksinformation"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Tryck på ett nätverk för att ansluta"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Lås upp för att visa nätverk"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Söker efter nätverk …"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Det gick inte att ansluta till nätverket"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Visa alla"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index f58ababc4d96..a5283bb63226 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Tumia alama ya kidole chako ili uendelee"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Imeshindwa kutambua alama ya kidole. Tumia mbinu ya kufunga skrini badala yake."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Inakutafuta…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Aikoni ya uso"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Kichupo cha kukuza kwa utangamanifu"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Maelezo ya mtandao"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Gusa mtandao ili uunganishe"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Fungua ili uangalie mitandao"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Inatafuta mitandao…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Imeshindwa kuunganisha kwenye mtandao"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Angalia yote"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index ac210447e050..eaf716841517 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"தொடர்வதற்குக் கைரேகையைப் பயன்படுத்தவும்"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"கைரேகையை அடையாளம் காண முடியவில்லை. அதற்குப் பதிலாகத் திரைப்பூட்டைப் பயன்படுத்தவும்."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"உங்கள் முகத்தைத் தேடுகிறது…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"முக ஐகான்"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"பொருந்துமாறு அளவை மாற்றும் பட்டன்."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"வைஃபை"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"நெட்வொர்க் விவரங்கள்"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"இணையத்துடன் இணைய நெட்வொர்க்கைத் தட்டுங்கள்"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"நெட்வொர்க்குகளைப் பார்க்க அன்லாக் செய்யுங்கள்"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"நெட்வொர்க்குகளைத் தேடுகிறது…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"நெட்வொர்க்குடன் இணைக்க முடியவில்லை"</string>
<string name="see_all_networks" msgid="3773666844913168122">"அனைத்தையும் காட்டு"</string>
diff --git a/packages/SystemUI/res/values-te-ldrtl/strings.xml b/packages/SystemUI/res/values-te-ldrtl/strings.xml
index 1c1b56274c8e..94bdbcf19038 100644
--- a/packages/SystemUI/res/values-te-ldrtl/strings.xml
+++ b/packages/SystemUI/res/values-te-ldrtl/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"యాప్‌లను శీఘ్రంగా స్విచ్ చేయడానికి ఎడమ వైపుకు లాగండి"</string>
+ <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"యాప్‌లను శీఘ్రంగా స్విచ్ చేయడానికి ఎడమ వైపునకు లాగండి"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index ff3f02cb161c..729a237a5561 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -103,7 +103,7 @@
<string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్‌పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నైనా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్‌వర్డ్‌లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్‌లు, ఆడియో ఉంటాయి."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"ఆడియోను రికార్డ్ చేయి"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"పరికరం ఆడియో"</string>
- <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే సంగీతం, కాల్‌లు, రింగ్‌టోన్‌ల వంటి ధ్వనులు"</string>
+ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే సంగీతం, కాల్స్‌, రింగ్‌టోన్‌ల వంటి ధ్వనులు"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"మైక్రోఫోన్"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"పరికరం ఆడియో, మైక్రోఫోన్"</string>
<string name="screenrecord_start" msgid="330991441575775004">"ప్రారంభించు"</string>
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"కొనసాగించడానికి మీ వేలిముద్రను ఉపయోగించండి"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"వేలిముద్రను గుర్తించడం సాధ్యపడదు. బదులుగా స్క్రీన్ లాక్‌ను ఉపయోగించండి."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"మీ కోసం చూస్తోంది…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ముఖ చిహ్నం"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"అనుకూలత జూమ్ బటన్."</string>
@@ -317,10 +319,10 @@
<string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"నోటిఫికేషన్ సెట్టింగ్‌లు"</string>
<string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> సెట్టింగ్‌లు"</string>
- <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"స్క్రీన్ స్వయంచాలకంగా తిప్పబడుతుంది."</string>
+ <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"స్క్రీన్ ఆటోమేటిక్‌గా తిప్పబడుతుంది."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"స్క్రీన్ ల్యాండ్‌స్కేప్ దృగ్విన్యాసంలో లాక్ చేయబడుతుంది."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"స్క్రీన్ పోర్ట్రెయిట్ దృగ్విన్యాసంలో లాక్ చేయబడుతుంది."</string>
- <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"స్క్రీన్ ఇప్పుడు స్వయంచాలకంగా తిరుగుతుంది."</string>
+ <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"స్క్రీన్ ఇప్పుడు ఆటోమేటిక్‌గా తిరుగుతుంది."</string>
<string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"స్క్రీన్ ఇప్పుడు ల్యాండ్‌స్కేప్ దృగ్విన్యాసంలో లాక్ చేయబడింది."</string>
<string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"స్క్రీన్ ఇప్పుడు పోర్ట్రెయిట్ దృగ్విన్యాసంలో లాక్ చేయబడింది."</string>
<string name="dessert_case" msgid="9104973640704357717">"డెజర్ట్ కేస్"</string>
@@ -445,7 +447,7 @@
<string name="zen_priority_introduction" msgid="3159291973383796646">"మీరు పేర్కొనే అలారాలు, రిమైండర్‌లు, ఈవెంట్‌లు మరియు కాలర్‌ల నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్‌లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్‌లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"అలారాలు నుండి మినహా మరే ఇతర ధ్వనులు మరియు వైబ్రేషన్‌లతో మీకు అంతరాయం కలగదు. మీరు ఇప్పటికీ సంగీతం, వీడియోలు మరియు గేమ్‌లతో సహా మీరు ప్లే చేయడానికి ఎంచుకున్నవి ఏవైనా వింటారు."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"అనుకూలీకరించు"</string>
- <string name="zen_silence_introduction_voice" msgid="853573681302712348">"ఇది అలారాలు, సంగీతం, వీడియోలు మరియు గేమ్‌లతో సహా అన్ని ధ్వనులు మరియు వైబ్రేషన్‌లను బ్లాక్ చేస్తుంది. మీరు ఇప్పటికీ ఫోన్ కాల్‌లు చేయగలుగుతారు."</string>
+ <string name="zen_silence_introduction_voice" msgid="853573681302712348">"ఇది అలారాలు, సంగీతం, వీడియోలు మరియు గేమ్‌లతో సహా అన్ని ధ్వనులు మరియు వైబ్రేషన్‌లను బ్లాక్ చేస్తుంది. మీరు ఇప్పటికీ ఫోన్ కాల్స్‌ చేయగలుగుతారు."</string>
<string name="zen_silence_introduction" msgid="6117517737057344014">"ఇది అలారాలు, సంగీతం, వీడియోలు మరియు గేమ్‌లతో సహా అన్ని ధ్వనులు మరియు వైబ్రేషన్‌లను బ్లాక్ చేస్తుంది."</string>
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"తక్కువ అత్యవసర నోటిఫికేషన్‌లు దిగువన"</string>
@@ -629,7 +631,7 @@
<string name="stream_bluetooth_sco" msgid="6234562365528664331">"బ్లూటూత్"</string>
<string name="stream_dtmf" msgid="7322536356554673067">"డ్యూయల్ మల్టీ టోన్ ఫ్రీక్వెన్సీ"</string>
<string name="stream_accessibility" msgid="3873610336741987152">"యాక్సెసిబిలిటీ"</string>
- <string name="ring_toggle_title" msgid="5973120187287633224">"కాల్‌లు"</string>
+ <string name="ring_toggle_title" msgid="5973120187287633224">"కాల్స్‌"</string>
<string name="volume_ringer_status_normal" msgid="1339039682222461143">"రింగ్"</string>
<string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"వైబ్రేట్"</string>
<string name="volume_ringer_status_silent" msgid="3691324657849880883">"మ్యూట్"</string>
@@ -645,7 +647,7 @@
<string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"అన్‌మ్యూట్ చేయి"</string>
<string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"వైబ్రేట్"</string>
<string name="volume_dialog_title" msgid="6502703403483577940">"%s వాల్యూమ్ నియంత్రణలు"</string>
- <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"కాల్‌లు మరియు నోటిఫికేషన్‌లు రింగ్ అవుతాయి (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
+ <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"కాల్స్‌ మరియు నోటిఫికేషన్‌లు రింగ్ అవుతాయి (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
<string name="output_title" msgid="3938776561655668350">"మీడియా అవుట్‌పుట్"</string>
<string name="output_calls_title" msgid="7085583034267889109">"ఫోన్ కాల్ అవుట్‌పుట్"</string>
<string name="output_none_found" msgid="5488087293120982770">"పరికరాలు ఏవీ కనుగొనబడలేదు"</string>
@@ -935,11 +937,11 @@
<string name="tuner_lock_screen" msgid="2267383813241144544">"లాక్ స్క్రీన్"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"వేడెక్కినందుకు ఫోన్ ఆఫ్ చేయబడింది"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"మీ ఫోన్ ఇప్పుడు సాధారణంగా పని చేస్తోంది.\nమరింత సమాచారం కోసం ట్యాప్ చేయండి"</string>
- <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"మీ ఫోన్ చాలా వేడిగా ఉంది, కనుక చల్లబర్చడానికి ఆఫ్ చేయబడింది. మీ ఫోన్ ఇప్పుడు సాధారణంగా పని చేస్తుంది.\n\nమీరు ఇలా చేస్తే మీ ఫోన్ చాలా వేడెక్కవచ్చు:\n • వనరు-ఆధారిత యాప్‌లు (గేమింగ్, వీడియో లేదా నావిగేషన్ వంటి యాప్‌లు) ఉపయోగించడం\n • పెద్ద ఫైల్‌లను డౌన్‌లోడ్ లేదా అప్‌లోడ్ చేయడం\n • అధిక ఉష్ణోగ్రతలలో మీ ఫోన్‌ని ఉపయోగించడం"</string>
+ <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"మీ ఫోన్ చాలా వేడిగా ఉంది, కనుక చల్లబర్చడానికి ఆఫ్ చేయబడింది. మీ ఫోన్ ఇప్పుడు సాధారణంగా పని చేస్తుంది.\n\nమీరు ఇలా చేస్తే మీ ఫోన్ చాలా వేడెక్కవచ్చు:\n • వనరు-ఆధారిత యాప్‌లు (గేమింగ్, వీడియో లేదా నావిగేషన్ వంటి యాప్‌లు) ఉపయోగించడం\n • పెద్ద ఫైళ్లను డౌన్‌లోడ్ లేదా అప్‌లోడ్ చేయడం\n • అధిక ఉష్ణోగ్రతలలో మీ ఫోన్‌ని ఉపయోగించడం"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
<string name="high_temp_title" msgid="2218333576838496100">"ఫోన్ వేడెక్కుతోంది"</string>
<string name="high_temp_notif_message" msgid="1277346543068257549">"ఫోన్‌ను చల్లబరిచే క్రమంలో కొన్ని ఫీచర్లు పరిమితం చేయబడ్డాయి.\nమరింత సమాచారం కోసం ట్యాప్ చేయండి"</string>
- <string name="high_temp_dialog_message" msgid="3793606072661253968">"మీ ఫోన్ స్వయంచాలకంగా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్‌ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string>
+ <string name="high_temp_dialog_message" msgid="3793606072661253968">"మీ ఫోన్ ఆటోమేటిక్‌గా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్‌ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
<string name="high_temp_alarm_title" msgid="2359958549570161495">"ప్లగ్ నుండి ఛార్జర్‌ తీసివేయండి"</string>
<string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ఈ పరికరాన్ని ఛార్జ్ చేయడంలో సమస్య ఉంది. పవర్ అడాప్టర్‌ను ప్లగ్ నుండి తీసివేసి, కేబుల్ ఏమైనా వేడిగా అయితే తగిన జాగ్రత్తలు తీసుకోండి."</string>
@@ -1142,7 +1144,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"కంటెంట్ త్వరలో కనిపిస్తుంది"</string>
<string name="missed_call" msgid="4228016077700161689">"మిస్డ్ కాల్"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్‌లు, మిస్డ్ కాల్‌లు, అలాగే స్టేటస్ అప్‌డేట్‌లను చూడండి"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్‌లు, మిస్డ్ కాల్స్‌, అలాగే స్టేటస్ అప్‌డేట్‌లను చూడండి"</string>
<string name="people_tile_title" msgid="6589377493334871272">"సంభాషణ"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"అంతరాయం కలిగించవద్దు ద్వారా పాజ్ చేయబడింది"</string>
<string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> మెసేజ్‌ను పంపారు: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"నెట్‌వర్క్ వివరాలు"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"కనెక్ట్ చేయడానికి నెట్‌వర్క్‌ను ట్యాప్ చేయండి"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"నెట్‌వర్క్‌ల కోసం సెర్చ్ చేస్తోంది…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"నెట్‌వర్క్‌కు కనెక్ట్ చేయడం విఫలమైంది"</string>
<string name="see_all_networks" msgid="3773666844913168122">"అన్నీ చూడండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 13e88c5c866b..02325eae8b91 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"ใช้ลายนิ้วมือของคุณเพื่อดำเนินการต่อ"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"ไม่รู้จักลายนิ้วมือ ใช้การล็อกหน้าจอแทน"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"กำลังหาใบหน้าคุณ…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"ไอคอนใบหน้า"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"รายละเอียดเครือข่าย"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"แตะเครือข่ายเพื่อเชื่อมต่อ"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ปลดล็อกเพื่อดูเครือข่าย"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"กำลังค้นหาเครือข่าย…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"เชื่อมต่อเครือข่ายไม่สำเร็จ"</string>
<string name="see_all_networks" msgid="3773666844913168122">"ดูทั้งหมด"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 261f56821d16..64056632f041 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Gamitin ang iyong fingerprint para magpatuloy"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Hindi makilala ang fingerprint. Gamitin na lang ang lock ng screen."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Hinahanap ka…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Face icon"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Button ng zoom ng pagiging tugma."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Mga detalye ng network"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Mag-tap ng network para kumonekta"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"I-unlock para tingnan ang mga network"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Naghahanap ng mga network…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Hind nakakonekta sa network"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Tingnan lahat"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a96c62d3dd03..3aa118323f6d 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Devam etmek için parmak izinizi kullanın"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Parmak izi tanınamadı. Bunun yerine ekran kilidini kullanın."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Yüzünüz tanınmaya çalışılıyor…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Yüz simgesi"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Uyumluluk zum düğmesi."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Kablosuz"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Ağ bilgileri"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Bağlanmak için bir ağa dokunun"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Ağları görmek için kilidi açın"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Ağlar aranıyor…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Ağa bağlanılamadı"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Tümünü göster"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8637ad723e1c..56370a07bb2d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Щоб продовжити, скористайтеся відбитком пальця"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Відбиток пальця не розпізнано. Використайте натомість дані для розблокування екрана."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Пошук обличчя…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Значок обличчя"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Кнопка масштабування сумісності."</string>
@@ -1182,6 +1184,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Деталі мережі"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Натисніть мережу, до якої потрібно підключитися"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Розблокувати, щоб переглянути мережі"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Пошук мереж…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Не вдалося підключитися до мережі"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Показати все"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 4321c3ec0949..a0d4a7b49828 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"جاری رکھنے کے لیے اپنا فنگر پرنٹ استعمال کریں"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"فنگر پرنٹ کی شناخت نہیں کی جا سکی۔ اس کے بجائے اسکرین لاک کا استعمال کریں۔"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"آپ کے لیے تلاش کیا جا رہا ہے…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"چہرے کا آئیکن"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"مطابقت پذیری زوم بٹن۔"</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"نیٹ ورک کی تفصیلات"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"منسلک کرنے کے لیے نیٹ ورک پر تھپتھپائیں"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"نیٹ ورکس تلاش کیے جا رہے ہیں…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"نیٹ ورک سے منسلک ہونے میں ناکام ہو گیا"</string>
<string name="see_all_networks" msgid="3773666844913168122">"سبھی دیکھیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ee68d27d30bd..6cab2b2e186d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Bu yuz notanish. Barmoq izi orqali urining."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Davom etish uchun barmoq izingizdan foydalaning"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Bu barmoq izi notanish. Ekran qulfi orqali urining."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Yuzingiz tekshirilmoqda…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Yuz belgisi"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Kattalashtirish tugmasi mosligi."</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Tarmoq tafsilotlari"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Ulanish uchun tarmoq ustiga bosing"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Tarmoqlarni koʻrish uchun qulfdan chiqaring"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Tarmoqlar qidirilmoqda…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Tarmoqqa ulanmadi"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Hammasi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index c528165ffcff..abaffb8dcdd5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Hãy dùng vân tay để tiếp tục"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Không thể nhận dạng vân tay. Hãy dùng phương thức khóa màn hình."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Đang tìm kiếm bạn…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Biểu tượng khuôn mặt"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Nút thu phóng khả năng tương thích."</string>
@@ -1170,6 +1172,8 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Thông tin chi tiết về mạng"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Nhấn vào một mạng để kết nối"</string>
+ <!-- no translation found for unlock_to_view_networks (5072880496312015676) -->
+ <skip />
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Đang tìm mạng…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Không kết nối được với mạng"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Xem tất cả"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 4d7cdee70da5..417ed5d03077 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"无法识别人脸。请改用指纹。"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"使用指纹验证身份后才能继续"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"无法识别指纹。请改用屏幕锁定功能。"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"正在查找您的面孔…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"面孔图标"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"兼容性缩放按钮。"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"WLAN"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"网络详情"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"点按要连接的网络"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"解锁即可查看网络"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜索网络…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"未能连接到网络"</string>
<string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ff4dddc09b3e..94470d2e4041 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識面孔,請改用指紋完成驗證。"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"請使用您的指紋繼續"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"無法辨識指紋,請改用螢幕鎖定完成驗證。"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"正在搜尋您的臉孔…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"面孔圖示"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"相容性縮放按鈕。"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi-Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"網絡詳細資料"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"輕按網絡以連線"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"解鎖即可查看網絡"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜尋網絡…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"無法連接網絡"</string>
<string name="see_all_networks" msgid="3773666844913168122">"顯示全部"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 88b35a693dd6..38ac96ff49f8 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識臉孔,請改用指紋完成驗證。"</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"使用指紋完成驗證才能繼續操作"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"無法辨識指紋,請改用螢幕鎖定完成驗證。"</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"正在尋找你的臉孔…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"臉孔圖示"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"相容性縮放按鈕。"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"網路詳細資料"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"輕觸要連線的網路"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"解鎖螢幕即可查看網路"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"正在搜尋網路…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"無法連上網路"</string>
<string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0e0e8930da1d..018ca9e0fc65 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -184,6 +184,8 @@
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string>
<string name="fingerprint_dialog_use_fingerprint" msgid="923777032861374285">"Sebenzisa izigxivizo zakho zeminwe ukuze uqhubeke"</string>
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock" msgid="4805522676254378353">"Ayizazi izigxivizo zeminwe. Sebenzisa ukukhiya isikrini kunalokho."</string>
+ <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
+ <skip />
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"Kufunwa wena…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"Isithonjana sobuso"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"Inkinobho evumelekile yokusondeza"</string>
@@ -1170,6 +1172,7 @@
<string name="turn_on_wifi" msgid="1308379840799281023">"Wi‑Fi"</string>
<string name="pref_title_network_details" msgid="1639455355897668883">"Imininingwane yenethiwekhi"</string>
<string name="tap_a_network_to_connect" msgid="1565073330852369558">"Thepha inethiwekhi ukuze uxhume"</string>
+ <string name="unlock_to_view_networks" msgid="5072880496312015676">"Vula ukuze ubuke amanethiwekhi"</string>
<string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"Iseshela amanethiwekhi…"</string>
<string name="wifi_failed_connect_message" msgid="4161863112079000071">"Yehlulekile ukuxhuma kunethiwekhi"</string>
<string name="see_all_networks" msgid="3773666844913168122">"Bona konke"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bbbaf65f861b..a4c1d94f9176 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -291,6 +291,6 @@
<color name="settingslib_track_on_color">?androidprv:attr/colorAccentPrimaryVariant</color>
<!-- Material next track off color-->
<color name="settingslib_track_off_color">?androidprv:attr/colorAccentSecondaryVariant</color>
- <color name="connected_network_primary_color">#ff000000</color>
- <color name="connected_network_tertiary_color">#808080</color>
+ <color name="connected_network_primary_color">#191C18</color>
+ <color name="connected_network_secondary_color">#41493D</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 721e1f3810a4..0aba7ce01a5c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -110,7 +110,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- internet,wifi,cell,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
+ internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness
</string>
<!-- The tiles to display in QuickSettings -->
@@ -700,4 +700,7 @@
source. This value is used as the base value in an exponential backoff in subsequent
attempts. -->
<integer name="config_communalSourceReconnectBaseDelay">1000</integer>
+
+ <!-- Flag to activate notification to contents feature -->
+ <bool name="config_notificationToContents">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a12fd2b9dfc3..0ae191d9a390 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -538,6 +538,9 @@
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
+ <!-- Padding for the lock icon on the keyguard. In pixels - should not scale with display size. -->
+ <dimen name="lock_icon_padding">48px</dimen>
+
<!-- Height of the carrier/wifi name label -->
<dimen name="carrier_label_height">24dp</dimen>
@@ -1595,7 +1598,8 @@
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_margin">12dp</dimen>
- <dimen name="internet_dialog_list_max_height">614dp</dimen>
+ <dimen name="internet_dialog_list_max_height">646dp</dimen>
+ <dimen name="internet_dialog_list_max_width">412dp</dimen>
<!-- Signal icon in internet dialog -->
<dimen name="signal_strength_icon_size">24dp</dimen>
@@ -1606,24 +1610,26 @@
<!-- Size of internet dialog -->
<dimen name="settingslib_switchbar_margin">16dp</dimen>
<!-- Minimum width of switch -->
- <dimen name="settingslib_min_switch_width">48dp</dimen>
+ <dimen name="settingslib_min_switch_width">52dp</dimen>
<!-- Size of layout margin left -->
<dimen name="settingslib_switchbar_padding_left">20dp</dimen>
<!-- Size of layout margin right -->
<dimen name="settingslib_switchbar_padding_right">20dp</dimen>
<!-- Radius of switch bar -->
- <dimen name="settingslib_switch_bar_radius">24dp</dimen>
+ <dimen name="settingslib_switch_bar_radius">35dp</dimen>
<!-- Margin of switch thumb -->
<dimen name="settingslib_switch_thumb_margin">4dp</dimen>
<!-- Size of switch thumb -->
- <dimen name="settingslib_switch_thumb_size">16dp</dimen>
+ <dimen name="settingslib_switch_thumb_size">20dp</dimen>
<!-- Width of switch track -->
- <dimen name="settingslib_switch_track_width">48dp</dimen>
+ <dimen name="settingslib_switch_track_width">52dp</dimen>
<!-- Height of switch track -->
- <dimen name="settingslib_switch_track_height">24dp</dimen>
+ <dimen name="settingslib_switch_track_height">28dp</dimen>
<!-- Radius of switch track -->
- <dimen name="settingslib_switch_track_radius">31dp</dimen>
+ <dimen name="settingslib_switch_track_radius">35dp</dimen>
<!-- Height percentage of the parent container occupied by the communal view -->
<item name="communal_source_height_percentage" format="float" type="dimen">0.80</item>
+
+ <dimen name="drag_and_drop_icon_size">70dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a8812bf4a293..b9002c3db399 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -438,6 +438,8 @@
<string name="fingerprint_dialog_use_fingerprint">Use your fingerprint to continue</string>
<!-- Message shown to ask the user to use screenlock to continue.[CHAR LIMIT=NONE] -->
<string name="fingerprint_dialog_cant_recognize_fp_use_screenlock">Can\u2019t recognize fingerprint. Use screen lock instead.</string>
+ <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
+ <string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
<!-- Message shown when the system-provided face dialog is shown, asking for authentication [CHAR LIMIT=30] -->
<string name="face_dialog_looking_for_face">Looking for you\u2026</string>
@@ -3012,6 +3014,8 @@
<string name="pref_title_network_details" msgid="7329759534269363308">"Network details"</string>
<!-- Provider Model: Panel subtitle for tapping a network to connect to internet. [CHAR LIMIT=60] -->
<string name="tap_a_network_to_connect">Tap a network to connect</string>
+ <!-- Provider Model: Panel subtitle for unlocking screen to view networks. [CHAR LIMIT=60] -->
+ <string name="unlock_to_view_networks">Unlock to view networks</string>
<!-- Provider Model: Wi-Fi settings. text displayed when Wi-Fi is on and network list is empty [CHAR LIMIT=50]-->
<string name="wifi_empty_list_wifi_on">Searching for networks\u2026</string>
<!-- Provider Model: Failure notification for connect -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
new file mode 100644
index 000000000000..4bb4eb9c020e
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 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.shared.animation
+
+import android.graphics.Point
+import android.util.MathUtils.lerp
+import android.view.Surface
+import android.view.View
+import android.view.WindowManager
+import com.android.unfold.UnfoldTransitionProgressProvider
+import java.lang.ref.WeakReference
+
+/**
+ * Creates an animation where all registered views are moved into their final location
+ * by moving from the center of the screen to the sides
+ */
+class UnfoldMoveFromCenterAnimator(
+ private val windowManager: WindowManager,
+ /**
+ * Allows to set custom translation applier
+ * Could be useful when a view could be translated from
+ * several sources and we want to set the translation
+ * using custom methods instead of [View.setTranslationX] or
+ * [View.setTranslationY]
+ */
+ var translationApplier: TranslationApplier = object : TranslationApplier {}
+) : UnfoldTransitionProgressProvider.TransitionProgressListener {
+
+ private val screenSize = Point()
+ private var isVerticalFold = false
+
+ private val animatedViews: MutableList<AnimatedView> = arrayListOf()
+ private val tmpArray = IntArray(2)
+
+ /**
+ * Updates display properties in order to calculate the initial position for the views
+ * Must be called before [registerViewForAnimation]
+ */
+ fun updateDisplayProperties() {
+ windowManager.defaultDisplay.getSize(screenSize)
+
+ // Simple implementation to get current fold orientation,
+ // this might not be correct on all devices
+ // TODO: use JetPack WindowManager library to get the fold orientation
+ isVerticalFold = windowManager.defaultDisplay.rotation == Surface.ROTATION_0 ||
+ windowManager.defaultDisplay.rotation == Surface.ROTATION_180
+ }
+
+ /**
+ * Registers a view to be animated, the view should be measured and layouted
+ * After finishing the animation it is necessary to clear
+ * the views using [clearRegisteredViews]
+ */
+ fun registerViewForAnimation(view: View) {
+ val animatedView = createAnimatedView(view)
+ animatedViews.add(animatedView)
+ }
+
+ /**
+ * Unregisters all registered views and resets their translation
+ */
+ fun clearRegisteredViews() {
+ onTransitionProgress(1f)
+ animatedViews.clear()
+ }
+
+ override fun onTransitionProgress(progress: Float) {
+ animatedViews.forEach {
+ it.view.get()?.let { view ->
+ translationApplier.apply(
+ view = view,
+ x = lerp(it.startTranslationX, it.finishTranslationX, progress),
+ y = lerp(it.startTranslationY, it.finishTranslationY, progress)
+ )
+ }
+ }
+ }
+
+ private fun createAnimatedView(view: View): AnimatedView {
+ val viewLocation = tmpArray
+ view.getLocationOnScreen(viewLocation)
+
+ val viewX = viewLocation[0].toFloat()
+ val viewY = viewLocation[1].toFloat()
+
+ val viewCenterX = viewX + view.width / 2
+ val viewCenterY = viewY + view.height / 2
+
+ val translationXDiff: Float
+ val translationYDiff: Float
+
+ if (isVerticalFold) {
+ val distanceFromScreenCenterToViewCenter = screenSize.x / 2 - viewCenterX
+ translationXDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+ translationYDiff = 0f
+ } else {
+ val distanceFromScreenCenterToViewCenter = screenSize.y / 2 - viewCenterY
+ translationXDiff = 0f
+ translationYDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+ }
+
+ return AnimatedView(
+ view = WeakReference(view),
+ startTranslationX = view.translationX + translationXDiff,
+ startTranslationY = view.translationY + translationYDiff,
+ finishTranslationX = view.translationX,
+ finishTranslationY = view.translationY
+ )
+ }
+
+ /**
+ * Interface that allows to use custom logic to apply translation to view
+ */
+ interface TranslationApplier {
+ /**
+ * Called when we need to apply [x] and [y] translation to [view]
+ */
+ fun apply(view: View, x: Float, y: Float) {
+ view.translationX = x
+ view.translationY = y
+ }
+ }
+
+ private class AnimatedView(
+ val view: WeakReference<View>,
+ val startTranslationX: Float,
+ val startTranslationY: Float,
+ val finishTranslationX: Float,
+ val finishTranslationY: Float
+ )
+}
+
+private const val TRANSLATION_PERCENTAGE = 0.3f
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index de9558ebca47..8bd0f910dac3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -90,4 +90,9 @@ oneway interface IOverviewProxy {
* Sent when behavior changes. See WindowInsetsController#@Behavior
*/
void onSystemBarAttributesChanged(int displayId, int behavior) = 20;
+
+ /**
+ * Sent when screen turned on and ready to use (blocker scrim is hidden)
+ */
+ void onScreenTurnedOn() = 21;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 23a365a1acef..68905f795563 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -216,7 +216,7 @@ public class RemoteAnimationTargetCompat {
activityType = ACTIVITY_TYPE_UNDEFINED;
}
taskInfo = change.getTaskInfo();
- allowEnterPip = false; /* always false in shell-transition case */
+ allowEnterPip = change.getAllowEnterPip();
mStartLeash = null;
rotationChange = change.getEndRotation() - change.getStartRotation();
windowType = INVALID_WINDOW_TYPE;
diff --git a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt
index 2ddb49c2e693..4a6a9ac266f2 100644
--- a/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/unfold/UnfoldTransitionProgressProvider.kt
@@ -31,8 +31,8 @@ interface UnfoldTransitionProgressProvider : CallbackController<TransitionProgre
fun destroy()
interface TransitionProgressListener {
- fun onTransitionStarted()
- fun onTransitionFinished()
- fun onTransitionProgress(@FloatRange(from = 0.0, to = 1.0) progress: Float)
+ fun onTransitionStarted() {}
+ fun onTransitionFinished() {}
+ fun onTransitionProgress(@FloatRange(from = 0.0, to = 1.0) progress: Float) {}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 9e456cf55500..27b6182d1aa2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -17,13 +17,13 @@
package com.android.keyguard;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import android.app.WallpaperManager;
import android.text.TextUtils;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
@@ -93,8 +93,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private final ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
- // If set, will replace keyguard_status_area
- private View mSmartspaceView;
+ private ViewGroup mSmartspaceContainer;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private SmartspaceTransitionController mSmartspaceTransitionController;
@@ -139,6 +138,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large);
+ mSmartspaceContainer = mView.findViewById(R.id.keyguard_smartspace_container);
+ mSmartspaceController.setKeyguardStatusContainer(mSmartspaceContainer);
mClockViewController =
new AnimatableClockController(
@@ -170,35 +171,25 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mView.updateColors(getGradientColors());
updateAodIcons();
- if (mSmartspaceController.isEnabled()) {
- mSmartspaceView = mSmartspaceController.buildAndConnectView(mView);
+ if (mSmartspaceController.isSmartspaceEnabled()) {
+ // "Enabled" doesn't mean smartspace is displayed here - inside mSmartspaceContainer -
+ // it might be a part of another view when in split shade. But it means that it CAN be
+ // displayed here, so we want to hide keyguard_status_area and set views relations
+ // accordingly.
View ksa = mView.findViewById(R.id.keyguard_status_area);
- int ksaIndex = mView.indexOfChild(ksa);
+ // we show either keyguard_status_area or smartspace, so when smartspace can be visible,
+ // keyguard_status_area should be hidden
ksa.setVisibility(View.GONE);
- // Place smartspace view below normal clock...
- RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
- MATCH_PARENT, WRAP_CONTENT);
- lp.addRule(RelativeLayout.BELOW, R.id.lockscreen_clock_view);
-
- mView.addView(mSmartspaceView, ksaIndex, lp);
- int startPadding = getContext().getResources()
- .getDimensionPixelSize(R.dimen.below_clock_padding_start);
- int endPadding = getContext().getResources()
- .getDimensionPixelSize(R.dimen.below_clock_padding_end);
- mSmartspaceView.setPaddingRelative(startPadding, 0, endPadding, 0);
-
updateClockLayout();
- View nic = mView.findViewById(
- R.id.left_aligned_notification_icon_container);
- lp = (RelativeLayout.LayoutParams) nic.getLayoutParams();
- lp.addRule(RelativeLayout.BELOW, mSmartspaceView.getId());
+ View nic = mView.findViewById(R.id.left_aligned_notification_icon_container);
+ RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) nic.getLayoutParams();
+ lp.addRule(RelativeLayout.BELOW, mSmartspaceContainer.getId());
nic.setLayoutParams(lp);
-
- mView.setSmartspaceView(mSmartspaceView);
- mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceView);
+ mView.setSmartspaceView(mSmartspaceContainer);
+ mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceContainer);
}
}
@@ -221,10 +212,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
// instance of this class. In order to fix this, we need to modify the plugin so that
// (a) we get a new view each time and (b) we can properly clean up an old view by making
// it unregister itself as a plugin listener.
- if (mSmartspaceView != null) {
- mView.removeView(mSmartspaceView);
- mSmartspaceView = null;
- }
+ mSmartspaceContainer.removeAllViews();
}
/**
@@ -237,7 +225,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
}
private void updateClockLayout() {
- if (mSmartspaceController.isEnabled()) {
+ if (mSmartspaceController.isSmartspaceEnabled()) {
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT,
MATCH_PARENT);
lp.topMargin = getContext().getResources().getDimensionPixelSize(
@@ -302,8 +290,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_Y,
scale, props, animate);
- if (mSmartspaceView != null) {
- PropertyAnimator.setProperty(mSmartspaceView, AnimatableProperty.TRANSLATION_X,
+ if (mSmartspaceContainer != null) {
+ PropertyAnimator.setProperty(mSmartspaceContainer, AnimatableProperty.TRANSLATION_X,
x, props, animate);
// If we're unlocking with the SmartSpace shared element transition, let the controller
@@ -321,8 +309,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
public void setChildrenAlphaExcludingSmartspace(float alpha) {
final Set<View> excludedViews = new HashSet<>();
- if (mSmartspaceView != null) {
- excludedViews.add(mSmartspaceView);
+ if (mSmartspaceContainer != null) {
+ excludedViews.add(mSmartspaceContainer);
}
setChildrenAlphaExcluding(alpha, excludedViews);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
deleted file mode 100644
index 0785cc3c04d2..000000000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.android.keyguard
-
-import android.annotation.CurrentTimeMillisLong
-
-/**
- * Data class for tracking information associated with [KeyguardUpdateMonitor.shouldListenForFace]
- * method calls.
- */
-data class KeyguardFaceListenModel(
- @CurrentTimeMillisLong val timeMillis: Long,
- val userId: Int,
- val isListeningForFace: Boolean,
- val isBouncer: Boolean,
- val isAuthInterruptActive: Boolean,
- val isOccludingAppRequestingFaceAuth: Boolean,
- val isKeyguardAwake: Boolean,
- val isListeningForFaceAssistant: Boolean,
- val isSwitchingUser: Boolean,
- val isFaceDisabled: Boolean,
- val isBecauseCannotSkipBouncer: Boolean,
- val isKeyguardGoingAway: Boolean,
- val isBiometricSettingEnabledForUser: Boolean,
- val isLockIconPressed: Boolean,
- val isScanningAllowedByStrongAuth: Boolean,
- val isPrimaryUser: Boolean,
- val isSecureCameraLaunched: Boolean,
- val isFaceAuthenticated: Boolean
-)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index b473f6d36c5c..75425e1e6ca3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -204,7 +204,8 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
- emergencyButtonController, mMessageAreaControllerFactory);
+ emergencyButtonController, mMessageAreaControllerFactory,
+ mDevicePostureController);
} else if (keyguardInputView instanceof KeyguardPasswordView) {
return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
new file mode 100644
index 000000000000..9286175cc2ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -0,0 +1,77 @@
+package com.android.keyguard
+
+import android.annotation.CurrentTimeMillisLong
+import android.hardware.biometrics.BiometricAuthenticator.Modality
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE
+import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT
+
+/** Verbose logging for various keyguard listening states. */
+sealed class KeyguardListenModel {
+ /** Timestamp of the state change. */
+ abstract val timeMillis: Long
+ /** Current user */
+ abstract val userId: Int
+ /** If keyguard is listening for the given [modality]. */
+ abstract val listening: Boolean
+ /** Sensor type */
+ @Modality abstract val modality: Int
+}
+
+/**
+ * Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFingerprint].
+ */
+data class KeyguardFingerprintListenModel(
+ @CurrentTimeMillisLong override val timeMillis: Long,
+ override val userId: Int,
+ override val listening: Boolean,
+ // keep sorted
+ val biometricEnabledForUser: Boolean,
+ val bouncer: Boolean,
+ val canSkipBouncer: Boolean,
+ val credentialAttempted: Boolean,
+ val deviceInteractive: Boolean,
+ val dreaming: Boolean,
+ val encryptedOrLockdown: Boolean,
+ val fingerprintDisabled: Boolean,
+ val fingerprintLockedOut: Boolean,
+ val goingToSleep: Boolean,
+ val keyguardGoingAway: Boolean,
+ val keyguardIsVisible: Boolean,
+ val keyguardOccluded: Boolean,
+ val occludingAppRequestingFp: Boolean,
+ val primaryUser: Boolean,
+ val shouldListenForFingerprintAssistant: Boolean,
+ val switchingUser: Boolean,
+ val udfps: Boolean,
+ val userDoesNotHaveTrust: Boolean,
+ val userNeedsStrongAuth: Boolean
+) : KeyguardListenModel() {
+ override val modality: Int = TYPE_FACE
+}
+
+/**
+ * Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFace].
+ */
+data class KeyguardFaceListenModel(
+ @CurrentTimeMillisLong override val timeMillis: Long,
+ override val userId: Int,
+ override val listening: Boolean,
+ // keep sorted
+ val authInterruptActive: Boolean,
+ val becauseCannotSkipBouncer: Boolean,
+ val biometricSettingEnabledForUser: Boolean,
+ val bouncer: Boolean,
+ val faceAuthenticated: Boolean,
+ val faceDisabled: Boolean,
+ val keyguardAwake: Boolean,
+ val keyguardGoingAway: Boolean,
+ val listeningForFaceAssistant: Boolean,
+ val lockIconPressed: Boolean,
+ val occludingAppRequestingFaceAuth: Boolean,
+ val primaryUser: Boolean,
+ val scanningAllowedByStrongAuth: Boolean,
+ val secureCameraLaunched: Boolean,
+ val switchingUser: Boolean
+) : KeyguardListenModel() {
+ override val modality: Int = TYPE_FINGERPRINT
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
new file mode 100644
index 000000000000..f13a59a84811
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import androidx.annotation.VisibleForTesting
+import java.io.PrintWriter
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+import kotlin.collections.ArrayDeque
+
+private val DEFAULT_FORMATTING = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US)
+
+/** Queue for verbose logging checks for the listening state. */
+class KeyguardListenQueue(
+ val sizePerModality: Int = 20
+) {
+ private val faceQueue = ArrayDeque<KeyguardFaceListenModel>()
+ private val fingerprintQueue = ArrayDeque<KeyguardFingerprintListenModel>()
+
+ @get:VisibleForTesting val models: List<KeyguardListenModel>
+ get() = faceQueue + fingerprintQueue
+
+ /** Push a [model] to the queue (will be logged until the queue exceeds [sizePerModality]). */
+ fun add(model: KeyguardListenModel) {
+ val queue = when (model) {
+ is KeyguardFaceListenModel -> faceQueue.apply { add(model) }
+ is KeyguardFingerprintListenModel -> fingerprintQueue.apply { add(model) }
+ }
+
+ if (queue.size > sizePerModality) {
+ queue.removeFirstOrNull()
+ }
+ }
+
+ /** Print verbose logs via the [writer]. */
+ @JvmOverloads
+ fun print(writer: PrintWriter, dateFormat: DateFormat = DEFAULT_FORMATTING) {
+ val stringify: (KeyguardListenModel) -> String = { model ->
+ " ${dateFormat.format(Date(model.timeMillis))} $model"
+ }
+
+ writer.println(" Face listen results (last ${faceQueue.size} calls):")
+ for (model in faceQueue) {
+ writer.println(stringify(model))
+ }
+ writer.println(" Fingerprint listen results (last ${fingerprintQueue.size} calls):")
+ for (model in fingerprintQueue) {
+ writer.println(stringify(model))
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 98e7fb48b7a6..a35aedf6f503 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -15,6 +15,8 @@
*/
package com.android.keyguard;
+import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
+
import android.content.Context;
import android.graphics.Rect;
import android.os.SystemClock;
@@ -22,16 +24,19 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.constraintlayout.widget.ConstraintSet;
+
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternView;
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt;
public class KeyguardPatternView extends KeyguardInputView
implements AppearAnimationCreator<LockPatternView.CellState> {
@@ -68,7 +73,7 @@ public class KeyguardPatternView extends KeyguardInputView
KeyguardMessageArea mSecurityMessageDisplay;
private View mEcaView;
- private ViewGroup mContainer;
+ private ConstraintLayout mContainer;
public KeyguardPatternView(Context context) {
this(context, null);
@@ -90,6 +95,18 @@ public class KeyguardPatternView extends KeyguardInputView
mContext, android.R.interpolator.fast_out_linear_in));
}
+ void onDevicePostureChanged(@DevicePostureInt int posture) {
+ // Update the guideline based on the device posture...
+ float halfOpenPercentage =
+ mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio);
+
+ ConstraintSet cs = new ConstraintSet();
+ cs.clone(mContainer);
+ cs.setGuidelinePercent(R.id.pin_pad_top_guideline, posture == DEVICE_POSTURE_HALF_OPENED
+ ? halfOpenPercentage : 0.0f);
+ cs.applyTo(mContainer);
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index d5be7bacaadc..94e07b713915 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -38,6 +38,7 @@ import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingClassifier;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.statusbar.policy.DevicePostureController;
import java.util.List;
@@ -56,6 +57,9 @@ public class KeyguardPatternViewController
private final FalsingCollector mFalsingCollector;
private final EmergencyButtonController mEmergencyButtonController;
private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
+ private final DevicePostureController mPostureController;
+ private final DevicePostureController.Callback mPostureCallback =
+ posture -> mView.onDevicePostureChanged(posture);
private KeyguardMessageAreaController mMessageAreaController;
private LockPatternView mLockPatternView;
@@ -192,7 +196,8 @@ public class KeyguardPatternViewController
LatencyTracker latencyTracker,
FalsingCollector falsingCollector,
EmergencyButtonController emergencyButtonController,
- KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ DevicePostureController postureController) {
super(view, securityMode, keyguardSecurityCallback, emergencyButtonController);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
@@ -203,6 +208,7 @@ public class KeyguardPatternViewController
KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
mMessageAreaController = mMessageAreaControllerFactory.create(kma);
mLockPatternView = mView.findViewById(R.id.lockPatternView);
+ mPostureController = postureController;
}
@Override
@@ -235,6 +241,7 @@ public class KeyguardPatternViewController
getKeyguardSecurityCallback().onCancelClicked();
});
}
+ mPostureController.addCallback(mPostureCallback);
}
@Override
@@ -247,6 +254,7 @@ public class KeyguardPatternViewController
if (cancelBtn != null) {
cancelBtn.setOnClickListener(null);
}
+ mPostureController.removeCallback(mPostureCallback);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index cb5c6c3a0090..0df2d65d2acb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -162,7 +162,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
try {
Thread.sleep(5000);
} catch (InterruptedException ignored) { }
- Runtime.getRuntime().gc();
+ System.gc();
+ System.runFinalization();
+ System.gc();
});
} else {
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ad196efdf1d6..92d1bc4173d8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -118,15 +118,11 @@ import com.google.android.collect.Lists;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.text.SimpleDateFormat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -148,6 +144,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE;
private static final boolean DEBUG_SPEW = false;
private static final int FINGERPRINT_LOCKOUT_RESET_DELAY_MS = 600;
@@ -347,13 +344,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
private static final int HAL_ERROR_RETRY_MAX = 20;
- private final Runnable mCancelNotReceived = new Runnable() {
- @Override
- public void run() {
- Log.w(TAG, "Cancel not received, transitioning to STOPPED");
- mFingerprintRunningState = mFaceRunningState = BIOMETRIC_STATE_STOPPED;
- updateBiometricListeningState();
- }
+ private final Runnable mFpCancelNotReceived = () -> {
+ Log.e(TAG, "Fp cancellation not received, transitioning to STOPPED");
+ mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
+ updateFingerprintListeningState();
+ };
+
+ private final Runnable mFaceCancelNotReceived = () -> {
+ Log.e(TAG, "Face cancellation not received, transitioning to STOPPED");
+ mFaceRunningState = BIOMETRIC_STATE_STOPPED;
+ updateFaceListeningState();
};
private final Handler mHandler;
@@ -419,9 +419,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>();
- // Keep track of recent calls to shouldListenForFace() for debugging.
- private static final int FACE_LISTEN_CALLS_QUEUE_SIZE = 20;
- private ArrayDeque<KeyguardFaceListenModel> mFaceListenModels;
+ // Keep track of recent calls to shouldListenFor*() for debugging.
+ private final KeyguardListenQueue mListenModels = new KeyguardListenQueue();
private static int sCurrentUser;
private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState;
@@ -791,19 +790,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void handleFingerprintError(int msgId, String errString) {
Assert.isMainThread();
- if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks(
- mCancelNotReceived)) {
- mHandler.removeCallbacks(mCancelNotReceived);
+ if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+ mHandler.removeCallbacks(mFpCancelNotReceived);
}
+ // Error is always the end of authentication lifecycle.
+ mFingerprintCancelSignal = null;
+
if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
&& mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
updateFingerprintListeningState();
} else {
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
- mFingerprintCancelSignal = null;
- mFaceCancelSignal = null;
}
if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
@@ -905,6 +904,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void handleFaceAuthFailed() {
Assert.isMainThread();
+ mFaceCancelSignal = null;
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -983,10 +983,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void handleFaceError(int msgId, String errString) {
Assert.isMainThread();
if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
- if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.removeCallbacks(mCancelNotReceived);
+ if (mHandler.hasCallbacks(mFaceCancelNotReceived)) {
+ mHandler.removeCallbacks(mFaceCancelNotReceived);
}
+ // Error is always the end of authentication lifecycle
+ mFaceCancelSignal = null;
+
if (msgId == FaceManager.FACE_ERROR_CANCELED
&& mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
@@ -2222,37 +2225,75 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
protected boolean shouldListenForFingerprint(boolean isUdfps) {
- final boolean userDoesNotHaveTrust = !getUserHasTrust(getCurrentUser());
+ final int user = getCurrentUser();
+ final boolean userDoesNotHaveTrust = !getUserHasTrust(user);
+ final boolean shouldListenForFingerprintAssistant = shouldListenForFingerprintAssistant();
final boolean shouldListenKeyguardState =
mKeyguardIsVisible
|| !mDeviceInteractive
|| (mBouncer && !mKeyguardGoingAway)
|| mGoingToSleep
- || shouldListenForFingerprintAssistant()
+ || shouldListenForFingerprintAssistant
|| (mKeyguardOccluded && mIsDreaming)
|| (mKeyguardOccluded && userDoesNotHaveTrust
&& (mOccludingAppRequestingFp || isUdfps));
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
+ final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
+ final boolean userCanSkipBouncer = getUserCanSkipBouncer(user);
+ final boolean fingerprintDisabledForUser = isFingerprintDisabled(user);
final boolean shouldListenUserState =
!mSwitchingUser
- && !isFingerprintDisabled(getCurrentUser())
+ && !fingerprintDisabledForUser
&& (!mKeyguardGoingAway || !mDeviceInteractive)
&& mIsPrimaryUser
- && mBiometricEnabledForUser.get(getCurrentUser());
+ && biometricEnabledForUser;
final boolean shouldListenBouncerState =
!(mFingerprintLockedOut && mBouncer && mCredentialAttempted);
+ final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user);
+ final boolean userNeedsStrongAuth = userNeedsStrongAuth();
final boolean shouldListenUdfpsState = !isUdfps
- || (!getUserCanSkipBouncer(getCurrentUser())
- && !isEncryptedOrLockdown(getCurrentUser())
- && !userNeedsStrongAuth()
+ || (!userCanSkipBouncer
+ && !isEncryptedOrLockdownForUser
+ && !userNeedsStrongAuth
&& userDoesNotHaveTrust
&& !mFingerprintLockedOut);
- return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState
- && shouldListenUdfpsState;
+
+ final boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
+ && shouldListenBouncerState && shouldListenUdfpsState;
+
+ if (DEBUG_FINGERPRINT || DEBUG_SPEW) {
+ maybeLogListenerModelData(
+ new KeyguardFingerprintListenModel(
+ System.currentTimeMillis(),
+ user,
+ shouldListen,
+ biometricEnabledForUser,
+ mBouncer,
+ userCanSkipBouncer,
+ mCredentialAttempted,
+ mDeviceInteractive,
+ mIsDreaming,
+ isEncryptedOrLockdownForUser,
+ fingerprintDisabledForUser,
+ mFingerprintLockedOut,
+ mGoingToSleep,
+ mKeyguardGoingAway,
+ mKeyguardIsVisible,
+ mKeyguardOccluded,
+ mOccludingAppRequestingFp,
+ mIsPrimaryUser,
+ shouldListenForFingerprintAssistant,
+ mSwitchingUser,
+ isUdfps,
+ userDoesNotHaveTrust,
+ userNeedsStrongAuth));
+ }
+
+ return shouldListen;
}
/**
@@ -2276,12 +2317,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
- boolean canBypass = mKeyguardBypassController != null
+ final boolean canBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
// There's no reason to ask the HAL for authentication when the user can dismiss the
// bouncer, unless we're bypassing and need to auto-dismiss the lock screen even when
// TrustAgents or biometrics are keeping the device unlocked.
- boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;
+ final boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;
// Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
// Lock-down mode shouldn't scan, since it is more explicit.
@@ -2289,69 +2330,72 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// If the device supports face detection (without authentication), allow it to happen
// if the device is in lockdown mode. Otherwise, prevent scanning.
- boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty()
+ final boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
if (isLockDown && !supportsDetectOnly) {
strongAuthAllowsScanning = false;
}
// If the face has recently been authenticated do not attempt to authenticate again.
- boolean faceAuthenticated = getIsFaceAuthenticated();
+ final boolean faceAuthenticated = getIsFaceAuthenticated();
+ final boolean faceDisabledForUser = isFaceDisabled(user);
+ final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
+ final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen =
(mBouncer || mAuthInterruptActive || mOccludingAppRequestingFace || awakeKeyguard
- || shouldListenForFaceAssistant())
- && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
- && !mKeyguardGoingAway && mBiometricEnabledForUser.get(user) && !mLockIconPressed
+ || shouldListenForFaceAssistant)
+ && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer
+ && !mKeyguardGoingAway && biometricEnabledForUser && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
&& (!mSecureCameraLaunched || mOccludingAppRequestingFace)
&& !faceAuthenticated;
// Aggregate relevant fields for debug logging.
if (DEBUG_FACE || DEBUG_SPEW) {
- final KeyguardFaceListenModel model = new KeyguardFaceListenModel(
- System.currentTimeMillis(),
- user,
- shouldListen,
- mBouncer,
- mAuthInterruptActive,
- mOccludingAppRequestingFace,
- awakeKeyguard,
- shouldListenForFaceAssistant(),
- mSwitchingUser,
- isFaceDisabled(user),
- becauseCannotSkipBouncer,
- mKeyguardGoingAway,
- mBiometricEnabledForUser.get(user),
- mLockIconPressed,
- strongAuthAllowsScanning,
- mIsPrimaryUser,
- mSecureCameraLaunched,
- faceAuthenticated);
- maybeLogFaceListenerModelData(model);
+ maybeLogListenerModelData(
+ new KeyguardFaceListenModel(
+ System.currentTimeMillis(),
+ user,
+ shouldListen,
+ mAuthInterruptActive,
+ becauseCannotSkipBouncer,
+ biometricEnabledForUser,
+ mBouncer,
+ faceAuthenticated,
+ faceDisabledForUser,
+ awakeKeyguard,
+ mKeyguardGoingAway,
+ shouldListenForFaceAssistant,
+ mLockIconPressed,
+ mOccludingAppRequestingFace,
+ mIsPrimaryUser,
+ strongAuthAllowsScanning,
+ mSecureCameraLaunched,
+ mSwitchingUser));
}
return shouldListen;
}
- private void maybeLogFaceListenerModelData(KeyguardFaceListenModel model) {
+ private void maybeLogListenerModelData(KeyguardListenModel model) {
// Too chatty, but very useful when debugging issues.
if (DEBUG_SPEW) {
Log.v(TAG, model.toString());
}
// Add model data to the historical buffer.
- if (DEBUG_FACE && mFaceRunningState != BIOMETRIC_STATE_RUNNING
- && model.isListeningForFace()) {
- if (mFaceListenModels == null) {
- mFaceListenModels = new ArrayDeque<>(FACE_LISTEN_CALLS_QUEUE_SIZE);
- }
- if (mFaceListenModels.size() >= FACE_LISTEN_CALLS_QUEUE_SIZE) {
- mFaceListenModels.remove();
- }
- mFaceListenModels.add(model);
+ final boolean notYetRunning =
+ (DEBUG_FACE
+ && model instanceof KeyguardFaceListenModel
+ && mFaceRunningState != BIOMETRIC_STATE_RUNNING)
+ || (DEBUG_FINGERPRINT
+ && model instanceof KeyguardFingerprintListenModel
+ && mFingerprintRunningState != BIOMETRIC_STATE_RUNNING);
+ if (notYetRunning && model.getListening()) {
+ mListenModels.add(model);
}
}
@@ -2368,6 +2412,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
private void startListeningForFingerprint() {
+ final int userId = getCurrentUser();
+ final boolean unlockPossible = isUnlockWithFingerprintPossible(userId);
+ if (mFingerprintCancelSignal != null) {
+ Log.e(TAG, "Cancellation signal is not null, high chance of bug in fp auth lifecycle"
+ + " management. FP state: " + mFingerprintRunningState
+ + ", unlockPossible: " + unlockPossible);
+ }
+
if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) {
setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
return;
@@ -2377,11 +2429,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
- int userId = getCurrentUser();
- if (isUnlockWithFingerprintPossible(userId)) {
- if (mFingerprintCancelSignal != null) {
- mFingerprintCancelSignal.cancel();
- }
+
+ if (unlockPossible) {
mFingerprintCancelSignal = new CancellationSignal();
if (isEncryptedOrLockdown(userId)) {
@@ -2397,6 +2446,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
private void startListeningForFace() {
+ final int userId = getCurrentUser();
+ final boolean unlockPossible = isUnlockWithFacePossible(userId);
+ if (mFaceCancelSignal != null) {
+ Log.e(TAG, "Cancellation signal is not null, high chance of bug in face auth lifecycle"
+ + " management. Face state: " + mFaceRunningState
+ + ", unlockPossible: " + unlockPossible);
+ }
+
if (mFaceRunningState == BIOMETRIC_STATE_CANCELLING) {
setFaceRunningState(BIOMETRIC_STATE_CANCELLING_RESTARTING);
return;
@@ -2405,11 +2462,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFace(): " + mFaceRunningState);
- int userId = getCurrentUser();
- if (isUnlockWithFacePossible(userId)) {
- if (mFaceCancelSignal != null) {
- mFaceCancelSignal.cancel();
- }
+
+ if (unlockPossible) {
mFaceCancelSignal = new CancellationSignal();
// This would need to be updated for multi-sensor devices
@@ -2461,9 +2515,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
mFingerprintCancelSignal = null;
- if (!mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
- }
+ mHandler.removeCallbacks(mFpCancelNotReceived);
+ mHandler.postDelayed(mFpCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
}
setFingerprintRunningState(BIOMETRIC_STATE_CANCELLING);
}
@@ -2478,9 +2531,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mFaceCancelSignal != null) {
mFaceCancelSignal.cancel();
mFaceCancelSignal = null;
- if (!mHandler.hasCallbacks(mCancelNotReceived)) {
- mHandler.postDelayed(mCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
- }
+ mHandler.removeCallbacks(mFaceCancelNotReceived);
+ mHandler.postDelayed(mFaceCancelNotReceived, DEFAULT_CANCEL_SIGNAL_TIMEOUT);
}
setFaceRunningState(BIOMETRIC_STATE_CANCELLING);
}
@@ -2842,6 +2894,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mSecureCameraLaunched = false;
}
+ if (mKeyguardBypassController != null) {
+ // LS visibility has changed, so reset deviceEntryIntent
+ mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
+ }
+
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -3432,15 +3489,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
pw.println(" enabledByUser=" + mBiometricEnabledForUser.get(userId));
pw.println(" mSecureCameraLaunched=" + mSecureCameraLaunched);
}
- if (mFaceListenModels != null && !mFaceListenModels.isEmpty()) {
- final SimpleDateFormat dateFormat =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
- pw.println(" Face listen results (last " + FACE_LISTEN_CALLS_QUEUE_SIZE + " calls):");
- for (final KeyguardFaceListenModel model : mFaceListenModels) {
- final String time = dateFormat.format(new Date(model.getTimeMillis()));
- pw.println(" " + time + " " + model.toString());
- }
- }
+ mListenModels.print(pw);
+
if (mIsAutomotive) {
pw.println(" Running on Automotive build");
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 4317e258d8f7..509ac8a6d9fe 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -514,7 +514,15 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
if (!wasClickableOnDownEvent()) {
return false;
}
+ onAffordanceClick();
+ return true;
+ }
+ public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+ if (!wasClickableOnDownEvent()) {
+ return false;
+ }
onAffordanceClick();
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index affad7a57d86..b126cddf8eec 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -25,6 +25,8 @@ import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.res.Resources;
import android.graphics.RectF;
import android.os.Handler;
@@ -73,6 +75,9 @@ public class SwipeHelper implements Gefingerpoken {
private final FlingAnimationUtils mFlingAnimationUtils;
private float mPagingTouchSlop;
private final float mSlopMultiplier;
+ private int mTouchSlop;
+ private float mTouchSlopMultiplier;
+
private final Callback mCallback;
private final int mSwipeDirection;
private final VelocityTracker mVelocityTracker;
@@ -105,6 +110,10 @@ public class SwipeHelper implements Gefingerpoken {
final int y = (int) mDownLocation[1] - mViewOffset[1];
mTouchedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
((ExpandableNotificationRow) mTouchedView).doLongClickCallback(x, y);
+
+ if (isAvailableToDragAndDrop(mTouchedView)) {
+ mCallback.onLongPressSent(mTouchedView);
+ }
}
}
}
@@ -126,6 +135,8 @@ public class SwipeHelper implements Gefingerpoken {
mVelocityTracker = VelocityTracker.obtain();
mPagingTouchSlop = viewConfiguration.getScaledPagingTouchSlop();
mSlopMultiplier = viewConfiguration.getScaledAmbiguousGestureMultiplier();
+ mTouchSlop = viewConfiguration.getScaledTouchSlop();
+ mTouchSlopMultiplier = viewConfiguration.getAmbiguousGestureMultiplier();
// Extra long-press!
mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f);
@@ -297,7 +308,9 @@ public class SwipeHelper implements Gefingerpoken {
mIsSwiping = false;
mSnappingChild = false;
mLongPressSent = false;
+ mCallback.onLongPressSent(null);
mVelocityTracker.clear();
+ cancelLongPress();
mTouchedView = mCallback.getChildAtPosition(ev);
if (mTouchedView != null) {
@@ -349,6 +362,7 @@ public class SwipeHelper implements Gefingerpoken {
mIsSwiping = false;
mTouchedView = null;
mLongPressSent = false;
+ mCallback.onLongPressSent(null);
mMenuRowIntercepting = false;
cancelLongPress();
if (captured) return true;
@@ -593,11 +607,7 @@ public class SwipeHelper implements Gefingerpoken {
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mLongPressSent && !mMenuRowIntercepting) {
- return true;
- }
-
- if (!mIsSwiping && !mMenuRowIntercepting) {
+ if (!mIsSwiping && !mMenuRowIntercepting && !mLongPressSent) {
if (mCallback.getChildAtPosition(ev) != null) {
// We are dragging directly over a card, make sure that we also catch the gesture
// even if nobody else wants the touch event.
@@ -623,30 +633,40 @@ public class SwipeHelper implements Gefingerpoken {
if (absDelta >= getFalsingThreshold()) {
mTouchAboveFalsingThreshold = true;
}
- // don't let items that can't be dismissed be dragged more than
- // maxScrollDistance
- if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(
- mTouchedView,
- delta > 0)) {
- float size = getSize(mTouchedView);
- float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
- if (absDelta >= size) {
- delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
- } else {
- int startPosition = mCallback.getConstrainSwipeStartPosition();
- if (absDelta > startPosition) {
- int signedStartPosition =
- (int) (startPosition * Math.signum(delta));
- delta = signedStartPosition
- + maxScrollDistance * (float) Math.sin(
- ((delta - signedStartPosition) / size) * (Math.PI / 2));
+
+ if (mLongPressSent) {
+ if (absDelta >= getTouchSlop(ev)) {
+ if (mTouchedView instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) mTouchedView)
+ .doDragCallback(ev.getX(), ev.getY());
+ }
+ }
+ } else {
+ // don't let items that can't be dismissed be dragged more than
+ // maxScrollDistance
+ if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(
+ mTouchedView,
+ delta > 0)) {
+ float size = getSize(mTouchedView);
+ float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
+ if (absDelta >= size) {
+ delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
+ } else {
+ int startPosition = mCallback.getConstrainSwipeStartPosition();
+ if (absDelta > startPosition) {
+ int signedStartPosition =
+ (int) (startPosition * Math.signum(delta));
+ delta = signedStartPosition
+ + maxScrollDistance * (float) Math.sin(
+ ((delta - signedStartPosition) / size) * (Math.PI / 2));
+ }
}
}
- }
- setTranslation(mTouchedView, mTranslation + delta);
- updateSwipeProgressFromOffset(mTouchedView, mCanCurrViewBeDimissed);
- onMoveUpdate(mTouchedView, ev, mTranslation + delta, delta);
+ setTranslation(mTouchedView, mTranslation + delta);
+ updateSwipeProgressFromOffset(mTouchedView, mCanCurrViewBeDimissed);
+ onMoveUpdate(mTouchedView, ev, mTranslation + delta, delta);
+ }
}
break;
case MotionEvent.ACTION_UP:
@@ -747,6 +767,29 @@ public class SwipeHelper implements Gefingerpoken {
mIsSwiping = false;
}
+ private float getTouchSlop(MotionEvent event) {
+ // Adjust the touch slop if another gesture may be being performed.
+ return event.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
+ ? mTouchSlop * mTouchSlopMultiplier
+ : mTouchSlop;
+ }
+
+ private boolean isAvailableToDragAndDrop(View v) {
+ if (v.getResources().getBoolean(R.bool.config_notificationToContents)) {
+ if (v instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow enr = (ExpandableNotificationRow) v;
+ boolean canBubble = enr.getEntry().canBubble();
+ Notification notif = enr.getEntry().getSbn().getNotification();
+ PendingIntent dragIntent = notif.contentIntent != null ? notif.contentIntent
+ : notif.fullScreenIntent;
+ if (dragIntent != null && dragIntent.isActivity() && !canBubble) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public interface Callback {
View getChildAtPosition(MotionEvent ev);
@@ -771,6 +814,13 @@ public class SwipeHelper implements Gefingerpoken {
void onDragCancelled(View v);
/**
+ * Called when the child is long pressed and available to start drag and drop.
+ *
+ * @param v the view that was long pressed.
+ */
+ void onLongPressSent(View v);
+
+ /**
* Called when the child is snapped to a position.
*
* @param animView the view that was snapped.
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 88c09dc0fcf5..b9440c5e3975 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -18,30 +18,23 @@ package com.android.systemui.battery;
import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.util.SysuiLifecycle.viewAttachLifecycle;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
+import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -54,17 +47,10 @@ import com.android.systemui.Dependency;
import com.android.systemui.DualToneHandler;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.settings.CurrentUserTracker;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -72,8 +58,7 @@ import java.lang.annotation.Retention;
import java.text.NumberFormat;
public class BatteryMeterView extends LinearLayout implements
- BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
-
+ BatteryStateChangeCallback, DarkReceiver {
@Retention(SOURCE)
@IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF, MODE_ESTIMATE})
@@ -84,21 +69,15 @@ public class BatteryMeterView extends LinearLayout implements
public static final int MODE_ESTIMATE = 3;
private final ThemedBatteryDrawable mDrawable;
- private final String mSlotBattery;
private final ImageView mBatteryIconView;
- private final CurrentUserTracker mUserTracker;
private TextView mBatteryPercentView;
private BatteryController mBatteryController;
- private SettingObserver mSettingObserver;
private final @StyleRes int mPercentageStyleId;
private int mTextColor;
private int mLevel;
private int mShowPercentMode = MODE_DEFAULT;
private boolean mShowPercentAvailable;
- // Some places may need to show the battery conditionally, and not obey the tuner
- private boolean mIgnoreTunerUpdates;
- private boolean mIsSubscribedForTunerUpdates;
private boolean mCharging;
// Error state where we know nothing about the current battery state
private boolean mBatteryStateUnknown;
@@ -106,7 +85,6 @@ public class BatteryMeterView extends LinearLayout implements
private Drawable mUnknownStateDrawable;
private DualToneHandler mDualToneHandler;
- private int mUser;
private int mNonAdaptedSingleToneColor;
private int mNonAdaptedForegroundColor;
@@ -118,7 +96,6 @@ public class BatteryMeterView extends LinearLayout implements
public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- BroadcastDispatcher broadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
@@ -131,14 +108,11 @@ public class BatteryMeterView extends LinearLayout implements
mDrawable = new ThemedBatteryDrawable(context, frameColor);
atts.recycle();
- mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
mShowPercentAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_battery_percentage_setting_available);
setupLayoutTransition();
- mSlotBattery = context.getString(
- com.android.internal.R.string.status_bar_battery);
mBatteryIconView = new ImageView(context);
mBatteryIconView.setImageDrawable(mDrawable);
final MarginLayoutParams mlp = new MarginLayoutParams(
@@ -153,21 +127,8 @@ public class BatteryMeterView extends LinearLayout implements
// Init to not dark at all.
onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
- mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
- @Override
- public void onUserSwitched(int newUserId) {
- mUser = newUserId;
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
- getContext().getContentResolver().registerContentObserver(
- Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver,
- newUserId);
- updateShowPercent();
- }
- };
-
setClipChildren(false);
setClipToPadding(false);
- Dependency.get(ConfigurationController.class).observe(viewAttachLifecycle(this), this);
}
private void setupLayoutTransition() {
@@ -204,44 +165,6 @@ public class BatteryMeterView extends LinearLayout implements
updateShowPercent();
}
- /**
- * Set {@code true} to turn off BatteryMeterView's subscribing to the tuner for updates, and
- * thus avoid it controlling its own visibility
- *
- * @param ignore whether to ignore the tuner or not
- */
- public void setIgnoreTunerUpdates(boolean ignore) {
- mIgnoreTunerUpdates = ignore;
- updateTunerSubscription();
- }
-
- private void updateTunerSubscription() {
- if (mIgnoreTunerUpdates) {
- unsubscribeFromTunerUpdates();
- } else {
- subscribeForTunerUpdates();
- }
- }
-
- private void subscribeForTunerUpdates() {
- if (mIsSubscribedForTunerUpdates || mIgnoreTunerUpdates) {
- return;
- }
-
- Dependency.get(TunerService.class)
- .addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
- mIsSubscribedForTunerUpdates = true;
- }
-
- private void unsubscribeFromTunerUpdates() {
- if (!mIsSubscribedForTunerUpdates) {
- return;
- }
-
- Dependency.get(TunerService.class).removeTunable(this);
- mIsSubscribedForTunerUpdates = false;
- }
-
public void setColorsFromContext(Context context) {
if (context == null) {
return;
@@ -256,37 +179,17 @@ public class BatteryMeterView extends LinearLayout implements
}
@Override
- public void onTuningChanged(String key, String newValue) {
- if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
- ArraySet<String> icons = StatusBarIconController.getIconHideList(
- getContext(), newValue);
- setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
- }
- }
-
- @Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
mBatteryController = Dependency.get(BatteryController.class);
mBatteryController.addCallback(this);
- mUser = ActivityManager.getCurrentUser();
- getContext().getContentResolver().registerContentObserver(
- Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, mUser);
- getContext().getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),
- false, mSettingObserver);
updateShowPercent();
- subscribeForTunerUpdates();
- mUserTracker.startTracking();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mUserTracker.stopTracking();
mBatteryController.removeCallback(this);
- getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
- unsubscribeFromTunerUpdates();
}
@Override
@@ -319,7 +222,7 @@ public class BatteryMeterView extends LinearLayout implements
updateShowPercent();
}
- private void updatePercentText() {
+ void updatePercentText() {
if (mBatteryStateUnknown) {
setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
return;
@@ -365,12 +268,12 @@ public class BatteryMeterView extends LinearLayout implements
: R.string.accessibility_battery_level, mLevel));
}
- private void updateShowPercent() {
+ void updateShowPercent() {
final boolean showing = mBatteryPercentView != null;
// TODO(b/140051051)
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
.getIntForUser(getContext().getContentResolver(),
- SHOW_BATTERY_PERCENT, 0, mUser));
+ SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
boolean shouldShow =
(mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
|| mShowPercentMode == MODE_ON
@@ -398,11 +301,6 @@ public class BatteryMeterView extends LinearLayout implements
}
}
- @Override
- public void onDensityOrFontScaleChanged() {
- scaleBatteryMeterViews();
- }
-
private Drawable getUnknownStateDrawable() {
if (mUnknownStateDrawable == null) {
mUnknownStateDrawable = mContext.getDrawable(R.drawable.ic_battery_unknown);
@@ -432,7 +330,7 @@ public class BatteryMeterView extends LinearLayout implements
/**
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
*/
- private void scaleBatteryMeterViews() {
+ void scaleBatteryMeterViews() {
Resources res = getContext().getResources();
TypedValue typedValue = new TypedValue();
@@ -492,21 +390,5 @@ public class BatteryMeterView extends LinearLayout implements
pw.println(" mLevel: " + mLevel);
pw.println(" mMode: " + mShowPercentMode);
}
-
- private final class SettingObserver extends ContentObserver {
- public SettingObserver(Handler handler) {
- super(handler);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- super.onChange(selfChange, uri);
- updateShowPercent();
- if (TextUtils.equals(uri.getLastPathSegment(),
- Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME)) {
- // update the text for sure if the estimate in the cache was updated
- updatePercentText();
- }
- }
- }
}
+
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index 27a6b3c18bbb..4664423c4422 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -15,22 +15,166 @@
*/
package com.android.systemui.battery;
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.view.View;
+
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
+
/** Controller for {@link BatteryMeterView}. **/
public class BatteryMeterViewController extends ViewController<BatteryMeterView> {
+ private final ConfigurationController mConfigurationController;
+ private final TunerService mTunerService;
+ private final ContentResolver mContentResolver;
+
+ private final String mSlotBattery;
+ private final SettingObserver mSettingObserver;
+ private final CurrentUserTracker mCurrentUserTracker;
+
+ private final ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ mView.scaleBatteryMeterViews();
+ }
+ };
+
+ private final TunerService.Tunable mTunable = new TunerService.Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
+ ArraySet<String> icons = StatusBarIconController.getIconHideList(
+ getContext(), newValue);
+ mView.setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
+ }
+ }
+ };
+
+ // Some places may need to show the battery conditionally, and not obey the tuner
+ private boolean mIgnoreTunerUpdates;
+ private boolean mIsSubscribedForTunerUpdates;
@Inject
- public BatteryMeterViewController(BatteryMeterView view) {
+ public BatteryMeterViewController(
+ BatteryMeterView view,
+ ConfigurationController configurationController,
+ TunerService tunerService,
+ BroadcastDispatcher broadcastDispatcher,
+ @Main Handler mainHandler,
+ ContentResolver contentResolver) {
super(view);
+ mConfigurationController = configurationController;
+ mTunerService = tunerService;
+ mContentResolver = contentResolver;
+
+ mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
+ mSettingObserver = new SettingObserver(mainHandler);
+ mCurrentUserTracker = new CurrentUserTracker(broadcastDispatcher) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ contentResolver.unregisterContentObserver(mSettingObserver);
+ registerShowBatteryPercentObserver(newUserId);
+ mView.updateShowPercent();
+ }
+ };
}
@Override
protected void onViewAttached() {
+ mConfigurationController.addCallback(mConfigurationListener);
+ subscribeForTunerUpdates();
+
+ registerShowBatteryPercentObserver(ActivityManager.getCurrentUser());
+ registerGlobalBatteryUpdateObserver();
+ mCurrentUserTracker.startTracking();
}
@Override
protected void onViewDetached() {
+ destroy();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ mConfigurationController.removeCallback(mConfigurationListener);
+ unsubscribeFromTunerUpdates();
+ mCurrentUserTracker.stopTracking();
+ mContentResolver.unregisterContentObserver(mSettingObserver);
+ }
+
+ /**
+ * Turn off {@link BatteryMeterView}'s subscribing to the tuner for updates, and thus avoid it
+ * controlling its own visibility.
+ */
+ public void ignoreTunerUpdates() {
+ mIgnoreTunerUpdates = true;
+ unsubscribeFromTunerUpdates();
+ }
+
+ private void subscribeForTunerUpdates() {
+ if (mIsSubscribedForTunerUpdates || mIgnoreTunerUpdates) {
+ return;
+ }
+
+ mTunerService.addTunable(mTunable, StatusBarIconController.ICON_HIDE_LIST);
+ mIsSubscribedForTunerUpdates = true;
+ }
+
+ private void unsubscribeFromTunerUpdates() {
+ if (!mIsSubscribedForTunerUpdates) {
+ return;
+ }
+
+ mTunerService.removeTunable(mTunable);
+ mIsSubscribedForTunerUpdates = false;
+ }
+
+ private void registerShowBatteryPercentObserver(int user) {
+ mContentResolver.registerContentObserver(
+ Settings.System.getUriFor(SHOW_BATTERY_PERCENT),
+ false,
+ mSettingObserver,
+ user);
+ }
+
+ private void registerGlobalBatteryUpdateObserver() {
+ mContentResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),
+ false,
+ mSettingObserver);
+ }
+
+ private final class SettingObserver extends ContentObserver {
+ public SettingObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ mView.updateShowPercent();
+ if (TextUtils.equals(uri.getLastPathSegment(),
+ Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME)) {
+ // update the text for sure if the estimate in the cache was updated
+ mView.updatePercentText();
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
index 98ad87506819..ae3e94b9a1cb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java
@@ -44,11 +44,17 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
private static final String TAG = "BiometricPrompt/AuthBiometricFaceToFingerprintView";
protected static class UdfpsIconController extends IconController {
+ @BiometricState private int mIconState = STATE_IDLE;
+
protected UdfpsIconController(
@NonNull Context context, @NonNull ImageView iconView, @NonNull TextView textView) {
super(context, iconView, textView);
}
+ void updateState(@BiometricState int newState) {
+ updateState(mIconState, newState);
+ }
+
@Override
protected void updateState(int lastState, int newState) {
final boolean lastStateIsErrorIcon =
@@ -86,6 +92,7 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
}
mState = newState;
+ mIconState = newState;
}
}
@@ -191,11 +198,11 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
// Deactivate the face icon controller so it stops drawing to the view
mFaceIconController.deactivate();
- // Then, activate this icon controller. We need to start in the "error" state
- mUdfpsIconController.updateState(mState, newState);
+ // Then, activate this icon controller. We need to start in the "idle" state
+ mUdfpsIconController.updateState(STATE_IDLE);
}
} else { // Fingerprint
- mUdfpsIconController.updateState(mState, newState);
+ mUdfpsIconController.updateState(newState);
}
super.updateState(newState);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index d122610c395d..d46426a03621 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -23,7 +23,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -68,8 +67,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
private float mBurnInProgress;
private float mInterpolatedDarkAmount;
- private ValueAnimator mHintAnimator;
-
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -94,9 +91,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
new KeyPath("**"), LottieProperty.COLOR_FILTER,
frameInfo -> new PorterDuffColorFilter(mTextColorPrimary, PorterDuff.Mode.SRC_ATOP)
);
-
- mHintAnimator = ObjectAnimator.ofFloat(mLockScreenFp, "progress", 1f, 0f, 1f);
- mHintAnimator.setDuration(4000);
}
@Override
@@ -183,19 +177,11 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
}
void onDozeAmountChanged(float linear, float eased) {
- mHintAnimator.cancel();
mInterpolatedDarkAmount = eased;
updateAlpha();
updateBurnInOffsets();
}
- void animateHint() {
- if (!isShadeLocked() && !mUdfpsRequested && mAlpha == 255
- && mLockScreenFp.isVisibleToUser()) {
- mHintAnimator.start();
- }
- }
-
/**
* Animates in the bg protection circle behind the fp icon to highlight the icon.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 102dc414d08d..79a4a0bd51ab 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -20,14 +20,10 @@ import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.annotation.NonNull;
import android.content.res.Configuration;
-import android.hardware.biometrics.BiometricSourceType;
import android.util.MathUtils;
import android.view.MotionEvent;
-import androidx.annotation.Nullable;
-
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -47,14 +43,8 @@ import java.util.Optional;
/**
* Class that coordinates non-HBM animations during keyguard authentication.
- *
- * Highlights the udfps icon when:
- * - Face authentication has failed
- * - Face authentication has been run for > 2 seconds
*/
public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
- private static final long AFTER_FACE_AUTH_HINT_DELAY = 2000;
-
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final DelayableExecutor mExecutor;
@@ -63,12 +53,10 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull private final ConfigurationController mConfigurationController;
@NonNull private final UdfpsController mUdfpsController;
- @Nullable private Runnable mCancelDelayedHintRunnable;
private boolean mShowingUdfpsBouncer;
private boolean mUdfpsRequested;
private boolean mQsExpanded;
private boolean mFaceDetectRunning;
- private boolean mHintShown;
private int mStatusBarState;
private float mTransitionToFullShadeProgress;
private float mLastDozeAmount;
@@ -111,10 +99,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@Override
protected void onViewAttached() {
super.onViewAttached();
- mHintShown = false;
- mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
- updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
-
final float dozeAmount = mStatusBarStateController.getDozeAmount();
mLastDozeAmount = dozeAmount;
mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
@@ -137,7 +121,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@Override
protected void onViewDetached() {
super.onViewDetached();
- mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mFaceDetectRunning = false;
mStatusBarStateController.removeCallback(mStateListener);
@@ -147,11 +130,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
}
-
- if (mCancelDelayedHintRunnable != null) {
- mCancelDelayedHintRunnable.run();
- mCancelDelayedHintRunnable = null;
- }
}
@Override
@@ -250,36 +228,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
}
}
- private void cancelDelayedHint() {
- if (mCancelDelayedHintRunnable != null) {
- mCancelDelayedHintRunnable.run();
- mCancelDelayedHintRunnable = null;
- }
- }
-
- private void updateFaceDetectRunning(boolean running) {
- if (mFaceDetectRunning == running) {
- return;
- }
-
- // show udfps hint a few seconds after face auth started running
- if (!mFaceDetectRunning && running && !mHintShown && mCancelDelayedHintRunnable == null) {
- // Face detect started running, show udfps hint after a delay
- mCancelDelayedHintRunnable = mExecutor.executeDelayed(() -> showHint(false),
- AFTER_FACE_AUTH_HINT_DELAY);
- }
-
- mFaceDetectRunning = running;
- }
-
- private void showHint(boolean forceShow) {
- cancelDelayedHint();
- if (!mHintShown || forceShow) {
- mHintShown = true;
- mView.animateHint();
- }
- }
-
/**
* Set the progress we're currently transitioning to the full shade. 0.0f means we're not
* transitioning yet, while 1.0f means we've fully dragged down.
@@ -319,39 +267,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
}
};
- private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
- new KeyguardUpdateMonitorCallback() {
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- updateFaceDetectRunning(running);
- }
- }
-
- public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // show udfps hint when face auth fails
- showHint(true);
- }
- }
-
- public void onBiometricError(int msgId, String errString,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // show udfps hint when face auth fails
- showHint(true);
- }
- }
-
- public void onBiometricAuthenticated(int userId,
- BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
- if (biometricSourceType == BiometricSourceType.FACE) {
- // cancel delayed hint if face auth succeeded
- cancelDelayedHint();
- }
- }
- };
-
private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 23c44131ab60..b2db86f16104 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -115,6 +115,7 @@ public class DozeSensors {
mSecureSettings = secureSettings;
mCallback = callback;
mProximitySensor = proximitySensor;
+ mProximitySensor.setTag(TAG);
mSelectivelyRegisterProxSensors = dozeParameters.getSelectivelyRegisterSensorsUsingProx();
mListeningProxSensors = !mSelectivelyRegisterProxSensors;
mScreenOffUdfpsEnabled =
diff --git a/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt b/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
index 15e3f3a6b1e9..5c6478ed0895 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
@@ -21,8 +21,8 @@ import android.util.MathUtils
private const val MILLIS_PER_MINUTES = 1000 * 60f
private const val BURN_IN_PREVENTION_PERIOD_Y = 521f
private const val BURN_IN_PREVENTION_PERIOD_X = 83f
-private const val BURN_IN_PREVENTION_PERIOD_SCALE = 180f
-private const val BURN_IN_PREVENTION_PERIOD_PROGRESS = 120f
+private const val BURN_IN_PREVENTION_PERIOD_SCALE = 181f
+private const val BURN_IN_PREVENTION_PERIOD_PROGRESS = 89f
/**
* Returns the translation offset that should be used to avoid burn in at
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
index 1fec7a669cc8..d4d01c8d97b5 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagReader.java
@@ -16,6 +16,7 @@
package com.android.systemui.flags;
+import android.content.Context;
import android.content.res.Resources;
import android.util.SparseArray;
@@ -25,6 +26,9 @@ import androidx.annotation.Nullable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.FlagReaderPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.wrapper.BuildInfo;
import javax.inject.Inject;
@@ -54,18 +58,68 @@ import javax.inject.Inject;
public class FeatureFlagReader {
private final Resources mResources;
private final boolean mAreFlagsOverrideable;
+ private final PluginManager mPluginManager;
private final SystemPropertiesHelper mSystemPropertiesHelper;
private final SparseArray<CachedFlag> mCachedFlags = new SparseArray<>();
+ private FlagReaderPlugin mPlugin = new FlagReaderPlugin(){};
+
@Inject
public FeatureFlagReader(
@Main Resources resources,
BuildInfo build,
+ PluginManager pluginManager,
SystemPropertiesHelper systemPropertiesHelper) {
mResources = resources;
+ mPluginManager = pluginManager;
mSystemPropertiesHelper = systemPropertiesHelper;
mAreFlagsOverrideable =
build.isDebuggable() && mResources.getBoolean(R.bool.are_flags_overrideable);
+
+ mPluginManager.addPluginListener(mPluginListener, FlagReaderPlugin.class);
+ }
+
+ private final PluginListener<FlagReaderPlugin> mPluginListener =
+ new PluginListener<FlagReaderPlugin>() {
+ public void onPluginConnected(FlagReaderPlugin plugin, Context context) {
+ mPlugin = plugin;
+ }
+
+ public void onPluginDisconnected(FlagReaderPlugin plugin) {
+ mPlugin = new FlagReaderPlugin() {};
+ }
+ };
+
+ boolean isEnabled(BooleanFlag flag) {
+ return mPlugin.isEnabled(flag.getId(), flag.getDefault());
+ }
+
+ String getValue(StringFlag flag) {
+ return mPlugin.getValue(flag.getId(), flag.getDefault());
+ }
+
+ int getValue(IntFlag flag) {
+ return mPlugin.getValue(flag.getId(), flag.getDefault());
+ }
+
+ long getValue(LongFlag flag) {
+ return mPlugin.getValue(flag.getId(), flag.getDefault());
+ }
+
+ float getValue(FloatFlag flag) {
+ return mPlugin.getValue(flag.getId(), flag.getDefault());
+ }
+
+ double getValue(DoubleFlag flag) {
+ return mPlugin.getValue(flag.getId(), flag.getDefault());
+ }
+
+ void addListener(FlagReaderPlugin.Listener listener) {
+ mPlugin.addListener(listener);
+ }
+
+ void removeListener(FlagReaderPlugin.Listener listener) {
+ mPlugin.removeListener(listener);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
index 5882179226c9..e51f90f9c73b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -19,8 +19,15 @@ package com.android.systemui.flags;
import android.content.Context;
import android.util.FeatureFlagUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.plugins.FlagReaderPlugin;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import javax.inject.Inject;
@@ -33,11 +40,88 @@ import javax.inject.Inject;
public class FeatureFlags {
private final FeatureFlagReader mFlagReader;
private final Context mContext;
+ private final Map<Integer, Flag<?>> mFlagMap = new HashMap<>();
+ private final Map<Integer, List<Listener>> mListeners = new HashMap<>();
@Inject
public FeatureFlags(FeatureFlagReader flagReader, Context context) {
mFlagReader = flagReader;
mContext = context;
+
+ flagReader.addListener(mListener);
+ }
+
+ private final FlagReaderPlugin.Listener mListener = id -> {
+ if (mListeners.containsKey(id) && mFlagMap.containsKey(id)) {
+ mListeners.get(id).forEach(listener -> listener.onFlagChanged(mFlagMap.get(id)));
+ }
+ };
+
+ @VisibleForTesting
+ void addFlag(Flag flag) {
+ mFlagMap.put(flag.getId(), flag);
+ }
+
+ /**
+ * @param flag The {@link BooleanFlag} of interest.
+ * @return The value of the flag.
+ */
+ public boolean isEnabled(BooleanFlag flag) {
+ return mFlagReader.isEnabled(flag);
+ }
+
+ /**
+ * @param flag The {@link StringFlag} of interest.
+ * @return The value of the flag.
+ */
+ public String getValue(StringFlag flag) {
+ return mFlagReader.getValue(flag);
+ }
+
+ /**
+ * @param flag The {@link IntFlag} of interest.
+ * @return The value of the flag.
+ */
+ public int getValue(IntFlag flag) {
+ return mFlagReader.getValue(flag);
+ }
+
+ /**
+ * @param flag The {@link LongFlag} of interest.
+ * @return The value of the flag.
+ */
+ public long getValue(LongFlag flag) {
+ return mFlagReader.getValue(flag);
+ }
+
+ /**
+ * @param flag The {@link FloatFlag} of interest.
+ * @return The value of the flag.
+ */
+ public float getValue(FloatFlag flag) {
+ return mFlagReader.getValue(flag);
+ }
+
+ /**
+ * @param flag The {@link DoubleFlag} of interest.
+ * @return The value of the flag.
+ */
+ public double getValue(DoubleFlag flag) {
+ return mFlagReader.getValue(flag);
+ }
+
+ /** Add a listener for a specific flag. */
+ public void addFlagListener(Flag<?> flag, Listener listener) {
+ mListeners.putIfAbsent(flag.getId(), new ArrayList<>());
+ mListeners.get(flag.getId()).add(listener);
+ mFlagMap.putIfAbsent(flag.getId(), flag);
+ }
+
+ /** Remove a listener for a specific flag. */
+ public void removeFlagListener(Flag<?> flag, Listener listener) {
+ if (mListeners.containsKey(flag.getId())) {
+ mListeners.get(flag.getId()).remove(listener);
+ }
}
public boolean isNewNotifPipelineEnabled() {
@@ -107,4 +191,10 @@ public class FeatureFlags {
public static boolean isProviderModelSettingEnabled(Context context) {
return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
}
+
+ /** Simple interface for beinga alerted when a specific flag changes value. */
+ public interface Listener {
+ /** */
+ void onFlagChanged(Flag<?> flag);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
deleted file mode 100644
index 04a0226aa0b4..000000000000
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ /dev/null
@@ -1,594 +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.systemui.globalactions;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.annotation.Nullable;
-import android.app.IActivityManager;
-import android.app.PendingIntent;
-import android.app.admin.DevicePolicyManager;
-import android.app.trust.TrustManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.os.UserManager;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.service.dreams.IDreamManager;
-import android.telecom.TelecomManager;
-import android.transition.AutoTransition;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.view.IWindowManager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import androidx.lifecycle.LifecycleOwner;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.view.RotationPolicy;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.animation.Interpolators;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
-import com.android.systemui.plugins.GlobalActionsPanelPlugin;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.telephony.TelephonyListenerManager;
-import com.android.systemui.util.RingerModeTracker;
-import com.android.systemui.util.leak.RotationUtils;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SecureSettings;
-
-import java.util.Optional;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-import javax.inject.Provider;
-
-/**
- * Helper to show the global actions dialog. Each item is an {@link Action} that may show depending
- * on whether the keyguard is showing, and whether the device is provisioned.
- * This version includes wallet.
- */
-public class GlobalActionsDialog extends GlobalActionsDialogLite
- implements DialogInterface.OnDismissListener,
- DialogInterface.OnShowListener,
- ConfigurationController.ConfigurationListener,
- GlobalActionsPanelPlugin.Callbacks,
- LifecycleOwner {
-
- private static final String TAG = "GlobalActionsDialog";
-
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardStateController mKeyguardStateController;
- private final SysUiState mSysUiState;
- private final ActivityStarter mActivityStarter;
- private final SysuiColorExtractor mSysuiColorExtractor;
- private final IStatusBarService mStatusBarService;
- private final NotificationShadeWindowController mNotificationShadeWindowController;
- private GlobalActionsPanelPlugin mWalletPlugin;
-
- @VisibleForTesting
- boolean mShowLockScreenCards = false;
-
- private final KeyguardStateController.Callback mKeyguardStateControllerListener =
- new KeyguardStateController.Callback() {
- @Override
- public void onUnlockedChanged() {
- if (mDialog != null) {
- ActionsDialog dialog = (ActionsDialog) mDialog;
- boolean unlocked = mKeyguardStateController.isUnlocked();
- if (dialog.mWalletViewController != null) {
- dialog.mWalletViewController.onDeviceLockStateChanged(!unlocked);
- }
-
- if (unlocked) {
- dialog.hideLockMessage();
- }
- }
- }
- };
-
- private final ContentObserver mSettingsObserver = new ContentObserver(mMainHandler) {
- @Override
- public void onChange(boolean selfChange) {
- onPowerMenuLockScreenSettingsChanged();
- }
- };
-
- /**
- * @param context everything needs a context :(
- */
- @Inject
- public GlobalActionsDialog(
- Context context,
- GlobalActionsManager windowManagerFuncs,
- AudioManager audioManager,
- IDreamManager iDreamManager,
- DevicePolicyManager devicePolicyManager,
- LockPatternUtils lockPatternUtils,
- BroadcastDispatcher broadcastDispatcher,
- TelephonyListenerManager telephonyListenerManager,
- GlobalSettings globalSettings,
- SecureSettings secureSettings,
- @Nullable Vibrator vibrator,
- @Main Resources resources,
- ConfigurationController configurationController,
- ActivityStarter activityStarter,
- KeyguardStateController keyguardStateController,
- UserManager userManager,
- TrustManager trustManager,
- IActivityManager iActivityManager,
- @Nullable TelecomManager telecomManager,
- MetricsLogger metricsLogger,
- SysuiColorExtractor colorExtractor,
- IStatusBarService statusBarService,
- NotificationShadeWindowController notificationShadeWindowController,
- IWindowManager iWindowManager,
- @Background Executor backgroundExecutor,
- UiEventLogger uiEventLogger,
- RingerModeTracker ringerModeTracker,
- SysUiState sysUiState,
- @Main Handler handler,
- PackageManager packageManager,
- Optional<StatusBar> statusBarOptional) {
-
- super(context,
- windowManagerFuncs,
- audioManager,
- iDreamManager,
- devicePolicyManager,
- lockPatternUtils,
- broadcastDispatcher,
- telephonyListenerManager,
- globalSettings,
- secureSettings,
- vibrator,
- resources,
- configurationController,
- keyguardStateController,
- userManager,
- trustManager,
- iActivityManager,
- telecomManager,
- metricsLogger,
- colorExtractor,
- statusBarService,
- notificationShadeWindowController,
- iWindowManager,
- backgroundExecutor,
- uiEventLogger,
- ringerModeTracker,
- sysUiState,
- handler,
- packageManager,
- statusBarOptional);
-
- mLockPatternUtils = lockPatternUtils;
- mKeyguardStateController = keyguardStateController;
- mSysuiColorExtractor = colorExtractor;
- mStatusBarService = statusBarService;
- mNotificationShadeWindowController = notificationShadeWindowController;
- mSysUiState = sysUiState;
- mActivityStarter = activityStarter;
-
- mKeyguardStateController.addCallback(mKeyguardStateControllerListener);
-
- // Listen for changes to show pay on the power menu while locked
- onPowerMenuLockScreenSettingsChanged();
- mGlobalSettings.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT),
- false /* notifyForDescendants */,
- mSettingsObserver);
- }
-
- @Override
- public void destroy() {
- super.destroy();
- mKeyguardStateController.removeCallback(mKeyguardStateControllerListener);
- mGlobalSettings.unregisterContentObserver(mSettingsObserver);
- }
-
- /**
- * Show the global actions dialog (creating if necessary)
- *
- * @param keyguardShowing True if keyguard is showing
- */
- public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned,
- GlobalActionsPanelPlugin walletPlugin) {
- mWalletPlugin = walletPlugin;
- super.showOrHideDialog(keyguardShowing, isDeviceProvisioned);
- }
-
- /**
- * Returns the maximum number of power menu items to show based on which GlobalActions
- * layout is being used.
- */
- @VisibleForTesting
- @Override
- protected int getMaxShownPowerItems() {
- return getContext().getResources().getInteger(
- com.android.systemui.R.integer.power_menu_max_columns);
- }
-
- /**
- * Create the global actions dialog.
- *
- * @return A new dialog.
- */
- @Override
- protected ActionsDialogLite createDialog() {
- initDialogItems();
-
- ActionsDialog dialog = new ActionsDialog(getContext(), mAdapter, mOverflowAdapter,
- this::getWalletViewController, mSysuiColorExtractor,
- mStatusBarService, mNotificationShadeWindowController,
- mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger(),
- getStatusBar());
-
- if (shouldShowLockMessage(dialog)) {
- dialog.showLockMessage();
- }
- dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
- dialog.setOnDismissListener(this);
- dialog.setOnShowListener(this);
-
- return dialog;
- }
-
- @Nullable
- private GlobalActionsPanelPlugin.PanelViewController getWalletViewController() {
- if (mWalletPlugin == null) {
- return null;
- }
- return mWalletPlugin.onPanelShown(this, !mKeyguardStateController.isUnlocked());
- }
-
- /**
- * Implements {@link GlobalActionsPanelPlugin.Callbacks#dismissGlobalActionsMenu()}, which is
- * called when the quick access wallet requests that an intent be started (with lock screen
- * shown first if needed).
- */
- @Override
- public void startPendingIntentDismissingKeyguard(PendingIntent pendingIntent) {
- mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent);
- }
-
- @Override
- protected int getEmergencyTextColor(Context context) {
- return context.getResources().getColor(
- com.android.systemui.R.color.global_actions_emergency_text);
- }
-
- @Override
- protected int getEmergencyIconColor(Context context) {
- return getContext().getResources().getColor(
- com.android.systemui.R.color.global_actions_emergency_text);
- }
-
- @Override
- protected int getEmergencyBackgroundColor(Context context) {
- return getContext().getResources().getColor(
- com.android.systemui.R.color.global_actions_emergency_background);
- }
-
- @Override
- protected int getGridItemLayoutResource() {
- return com.android.systemui.R.layout.global_actions_grid_item_v2;
- }
-
- @VisibleForTesting
- static class ActionsDialog extends ActionsDialogLite {
-
- private final Provider<GlobalActionsPanelPlugin.PanelViewController> mWalletFactory;
- @Nullable private GlobalActionsPanelPlugin.PanelViewController mWalletViewController;
- private ResetOrientationData mResetOrientationData;
- @VisibleForTesting ViewGroup mLockMessageContainer;
- private TextView mLockMessage;
-
- ActionsDialog(Context context, MyAdapter adapter, MyOverflowAdapter overflowAdapter,
- Provider<GlobalActionsPanelPlugin.PanelViewController> walletFactory,
- SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
- NotificationShadeWindowController notificationShadeWindowController,
- SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing,
- MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
- Optional<StatusBar> statusBarOptional) {
- super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions,
- adapter, overflowAdapter, sysuiColorExtractor, statusBarService,
- notificationShadeWindowController, sysuiState, onRotateCallback,
- keyguardShowing, powerAdapter, uiEventLogger, statusBarOptional);
- mWalletFactory = walletFactory;
-
- // Update window attributes
- Window window = getWindow();
- window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- window.setLayout(MATCH_PARENT, MATCH_PARENT);
- window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- window.addFlags(
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- setTitle(R.string.global_actions);
- initializeLayout();
- }
-
- private boolean isWalletViewAvailable() {
- return mWalletViewController != null && mWalletViewController.getPanelContent() != null;
- }
-
- private void initializeWalletView() {
- if (mWalletFactory == null) {
- return;
- }
- mWalletViewController = mWalletFactory.get();
- if (!isWalletViewAvailable()) {
- return;
- }
-
- boolean isLandscapeWalletViewShown = mContext.getResources().getBoolean(
- com.android.systemui.R.bool.global_actions_show_landscape_wallet_view);
-
- int rotation = RotationUtils.getRotation(mContext);
- boolean rotationLocked = RotationPolicy.isRotationLocked(mContext);
- if (rotation != RotationUtils.ROTATION_NONE) {
- if (rotationLocked) {
- if (mResetOrientationData == null) {
- mResetOrientationData = new ResetOrientationData();
- mResetOrientationData.locked = true;
- mResetOrientationData.rotation = rotation;
- }
-
- // Unlock rotation, so user can choose to rotate to portrait to see the panel.
- // This call is posted so that the rotation does not change until post-layout,
- // otherwise onConfigurationChanged() may not get invoked.
- mGlobalActionsLayout.post(() ->
- RotationPolicy.setRotationLockAtAngle(
- mContext, false, RotationUtils.ROTATION_NONE));
-
- if (!isLandscapeWalletViewShown) {
- return;
- }
- }
- } else {
- if (!rotationLocked) {
- if (mResetOrientationData == null) {
- mResetOrientationData = new ResetOrientationData();
- mResetOrientationData.locked = false;
- }
- }
-
- boolean shouldLockRotation = !isLandscapeWalletViewShown;
- if (rotationLocked != shouldLockRotation) {
- // Locks the screen to portrait if the landscape / seascape orientation does not
- // show the wallet view, so the user doesn't accidentally hide the panel.
- // This call is posted so that the rotation does not change until post-layout,
- // otherwise onConfigurationChanged() may not get invoked.
- mGlobalActionsLayout.post(() ->
- RotationPolicy.setRotationLockAtAngle(
- mContext, shouldLockRotation, RotationUtils.ROTATION_NONE));
- }
- }
-
- // Disable rotation suggestions, if enabled
- setRotationSuggestionsEnabled(false);
-
- FrameLayout panelContainer =
- findViewById(com.android.systemui.R.id.global_actions_wallet);
- FrameLayout.LayoutParams panelParams =
- new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.MATCH_PARENT);
- panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
- com.android.systemui.R.dimen.global_actions_wallet_top_margin);
- View walletView = mWalletViewController.getPanelContent();
- panelContainer.addView(walletView, panelParams);
- // Smooth transitions when wallet is resized, which can happen when a card is added
- ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root);
- if (root != null) {
- walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> {
- int oldHeight = ob - ot;
- int newHeight = b - t;
- if (oldHeight > 0 && oldHeight != newHeight) {
- TransitionSet transition = new AutoTransition()
- .setDuration(250)
- .setOrdering(TransitionSet.ORDERING_TOGETHER);
- TransitionManager.beginDelayedTransition(root, transition);
- }
- });
- }
- }
-
- @Override
- protected int getLayoutResource() {
- return com.android.systemui.R.layout.global_actions_grid_v2;
- }
-
- @Override
- protected void initializeLayout() {
- super.initializeLayout();
- mLockMessageContainer = requireViewById(
- com.android.systemui.R.id.global_actions_lock_message_container);
- mLockMessage = requireViewById(com.android.systemui.R.id.global_actions_lock_message);
- initializeWalletView();
- getWindow().setBackgroundDrawable(mBackgroundDrawable);
- }
-
- @Override
- protected void showDialog() {
- mShowing = true;
- mNotificationShadeWindowController.setRequestTopUi(true, TAG);
- mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true)
- .commitUpdate(mContext.getDisplayId());
-
- ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView();
- root.setOnApplyWindowInsetsListener((v, windowInsets) -> {
- root.setPadding(windowInsets.getStableInsetLeft(),
- windowInsets.getStableInsetTop(),
- windowInsets.getStableInsetRight(),
- windowInsets.getStableInsetBottom());
- return WindowInsets.CONSUMED;
- });
-
- mBackgroundDrawable.setAlpha(0);
- float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
- ObjectAnimator alphaAnimator =
- ObjectAnimator.ofFloat(mContainer, "alpha", 0f, 1f);
- alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- alphaAnimator.setDuration(183);
- alphaAnimator.addUpdateListener((animation) -> {
- float animatedValue = animation.getAnimatedFraction();
- int alpha = (int) (animatedValue * mScrimAlpha * 255);
- mBackgroundDrawable.setAlpha(alpha);
- });
-
- ObjectAnimator xAnimator =
- ObjectAnimator.ofFloat(mContainer, "translationX", xOffset, 0f);
- xAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- xAnimator.setDuration(350);
-
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(alphaAnimator, xAnimator);
- animatorSet.start();
- }
-
- @Override
- protected void dismissInternal() {
- super.dismissInternal();
- }
-
- @Override
- protected void completeDismiss() {
- dismissWallet();
- resetOrientation();
- super.completeDismiss();
- }
-
- private void dismissWallet() {
- if (mWalletViewController != null) {
- mWalletViewController.onDismissed();
- // The wallet controller should not be re-used after being dismissed.
- mWalletViewController = null;
- }
- }
-
- private void resetOrientation() {
- if (mResetOrientationData != null) {
- RotationPolicy.setRotationLockAtAngle(mContext, mResetOrientationData.locked,
- mResetOrientationData.rotation);
- }
- setRotationSuggestionsEnabled(true);
- }
-
- @Override
- public void refreshDialog() {
- // ensure dropdown menus are dismissed before re-initializing the dialog
- dismissWallet();
- super.refreshDialog();
- }
-
- void hideLockMessage() {
- if (mLockMessageContainer.getVisibility() == View.VISIBLE) {
- mLockMessageContainer.animate().alpha(0).setDuration(150).setListener(
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLockMessageContainer.setVisibility(View.GONE);
- }
- }).start();
- }
- }
-
- void showLockMessage() {
- Drawable lockIcon = mContext.getDrawable(com.android.internal.R.drawable.ic_lock);
- lockIcon.setTint(mContext.getColor(com.android.systemui.R.color.control_primary_text));
- mLockMessage.setCompoundDrawablesWithIntrinsicBounds(null, lockIcon, null, null);
- mLockMessageContainer.setVisibility(View.VISIBLE);
- }
-
- private static class ResetOrientationData {
- public boolean locked;
- public int rotation;
- }
- }
-
- /**
- * Determines whether or not debug mode has been activated for the Global Actions Panel.
- */
- private static boolean isPanelDebugModeEnabled(Context context) {
- return Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.GLOBAL_ACTIONS_PANEL_DEBUG_ENABLED, 0) == 1;
- }
-
- /**
- * Determines whether or not the Global Actions menu should be forced to use the newer
- * grid-style layout.
- */
- private static boolean isForceGridEnabled(Context context) {
- return isPanelDebugModeEnabled(context);
- }
-
- private boolean shouldShowLockMessage(ActionsDialog dialog) {
- return isWalletAvailableAfterUnlock(dialog);
- }
-
- // Temporary while we move items out of the power menu
- private boolean isWalletAvailableAfterUnlock(ActionsDialog dialog) {
- boolean isLockedAfterBoot = mLockPatternUtils.getStrongAuthForUser(getCurrentUser().id)
- == STRONG_AUTH_REQUIRED_AFTER_BOOT;
- return !mKeyguardStateController.isUnlocked()
- && (!mShowLockScreenCards || isLockedAfterBoot)
- && dialog.isWalletViewAvailable();
- }
-
- private void onPowerMenuLockScreenSettingsChanged() {
- mShowLockScreenCards = mSecureSettings.getInt(
- Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 0) != 0;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 85f2366db166..281771860cb7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2603,7 +2603,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_guestUserAutoCreated)) {
// TODO(b/191067027): Move post-boot guest creation to system_server
- mUserSwitcherController.guaranteeGuestPresent();
+ mUserSwitcherController.schedulePostBootGuestCreation();
}
mBootCompleted = true;
adjustStatusBarLocked(false, true);
@@ -2759,7 +2759,10 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable,
// Don't hide the keyguard due to a doze change if there's a lock pending, because we're
// just going to show it again.
- if (mShowing || !mPendingLock) {
+ // If the device is not capable of controlling the screen off animation, SysUI needs to
+ // update lock screen state in ATMS here, otherwise ATMS tries to resume activities when
+ // enabling doze state.
+ if (mShowing || !mPendingLock || !mDozeParameters.canControlUnlockedScreenOff()) {
setShowingLocked(mShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 5293c8850267..b2def7a8596a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -466,7 +466,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
}
boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
- return !device.getFeatures().contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK);
+ return !isActiveRemoteDevice(device);
}
private final MediaController.Callback mCb = new MediaController.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 543004eecb8e..1ca2217638f7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -116,7 +116,7 @@ public class NavigationBarController implements Callbacks,
private final TaskbarDelegate mTaskbarDelegate;
private final NotificationShadeDepthController mNotificationShadeDepthController;
private int mNavMode;
- private boolean mIsTablet;
+ @VisibleForTesting boolean mIsTablet;
private final UserTracker mUserTracker;
/** A displayId - nav bar maps. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
new file mode 100644
index 000000000000..bedb33038134
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2021 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.qs
+
+import android.content.Intent
+import android.os.UserManager
+import android.provider.Settings
+import android.view.View
+import android.widget.Toast
+import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.nano.MetricsProto
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.FooterActionsController.ExpansionState.COLLAPSED
+import com.android.systemui.qs.FooterActionsController.ExpansionState.EXPANDED
+import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.phone.SettingsButton
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.ViewController
+import javax.inject.Inject
+import javax.inject.Named
+
+/**
+ * Manages [FooterActionsView] behaviour, both when it's placed in QS or QQS (split shade).
+ * Main difference between QS and QQS behaviour is condition when buttons should be visible,
+ * determined by [buttonsVisibleState]
+ */
+class FooterActionsController @Inject constructor(
+ view: FooterActionsView,
+ private val qsPanelController: QSPanelController,
+ private val activityStarter: ActivityStarter,
+ private val userManager: UserManager,
+ private val userInfoController: UserInfoController,
+ private val multiUserSwitchController: MultiUserSwitchController,
+ private val deviceProvisionedController: DeviceProvisionedController,
+ private val falsingManager: FalsingManager,
+ private val metricsLogger: MetricsLogger,
+ private val tunerService: TunerService,
+ private val globalActionsDialog: GlobalActionsDialogLite,
+ private val uiEventLogger: UiEventLogger,
+ @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
+ private val buttonsVisibleState: ExpansionState
+) : ViewController<FooterActionsView>(view) {
+
+ enum class ExpansionState { COLLAPSED, EXPANDED }
+
+ private var listening: Boolean = false
+
+ var expanded = false
+ set(value) {
+ if (field != value) {
+ field = value
+ updateView()
+ }
+ }
+
+ private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button)
+ private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container)
+ private val editButton: View = view.findViewById(android.R.id.edit)
+ private val powerMenuLite: View = view.findViewById(R.id.pm_lite)
+
+ private val onUserInfoChangedListener = OnUserInfoChangedListener { _, picture, _ ->
+ val isGuestUser: Boolean = userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser())
+ mView.onUserInfoChanged(picture, isGuestUser)
+ }
+
+ private val onClickListener = View.OnClickListener { v ->
+ // Don't do anything until views are unhidden. Don't do anything if the tap looks
+ // suspicious.
+ if (!buttonsVisible() || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return@OnClickListener
+ }
+ if (v === settingsButton) {
+ if (!deviceProvisionedController.isCurrentUserSetup) {
+ // If user isn't setup just unlock the device and dump them back at SUW.
+ activityStarter.postQSRunnableDismissingKeyguard {}
+ return@OnClickListener
+ }
+ metricsLogger.action(
+ if (expanded) MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ else MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH)
+ if (settingsButton.isTunerClick) {
+ activityStarter.postQSRunnableDismissingKeyguard {
+ if (isTunerEnabled()) {
+ tunerService.showResetRequest {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity()
+ }
+ } else {
+ Toast.makeText(context, R.string.tuner_toast, Toast.LENGTH_LONG).show()
+ tunerService.isTunerEnabled = true
+ }
+ startSettingsActivity()
+ }
+ } else {
+ startSettingsActivity()
+ }
+ } else if (v === powerMenuLite) {
+ uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+ globalActionsDialog.showOrHideDialog(false, true)
+ }
+ }
+
+ private fun buttonsVisible(): Boolean {
+ return when (buttonsVisibleState) {
+ EXPANDED -> expanded
+ COLLAPSED -> !expanded
+ }
+ }
+
+ override fun onInit() {
+ multiUserSwitchController.init()
+ }
+
+ fun hideFooter() {
+ mView.visibility = View.GONE
+ }
+
+ fun showFooter() {
+ mView.visibility = View.VISIBLE
+ updateView()
+ }
+
+ private fun startSettingsActivity() {
+ val animationController = settingsButtonContainer?.let {
+ ActivityLaunchAnimator.Controller.fromView(
+ it,
+ InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON)
+ }
+ activityStarter.startActivity(Intent(Settings.ACTION_SETTINGS),
+ true /* dismissShade */, animationController)
+ }
+
+ @VisibleForTesting
+ public override fun onViewAttached() {
+ if (showPMLiteButton) {
+ powerMenuLite.visibility = View.VISIBLE
+ powerMenuLite.setOnClickListener(onClickListener)
+ } else {
+ powerMenuLite.visibility = View.GONE
+ }
+ settingsButton.setOnClickListener(onClickListener)
+ editButton.setOnClickListener(View.OnClickListener { view: View? ->
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ return@OnClickListener
+ }
+ activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) }
+ })
+
+ updateView()
+ }
+
+ private fun updateView() {
+ mView.updateEverything(buttonsVisible(), isTunerEnabled(),
+ multiUserSwitchController.isMultiUserEnabled)
+ }
+
+ override fun onViewDetached() {
+ setListening(false)
+ }
+
+ fun setListening(listening: Boolean) {
+ if (this.listening == listening) {
+ return
+ }
+ this.listening = listening
+ if (this.listening) {
+ userInfoController.addCallback(onUserInfoChangedListener)
+ } else {
+ userInfoController.removeCallback(onUserInfoChangedListener)
+ }
+ }
+
+ fun disable(state2: Int) {
+ mView.disable(buttonsVisible(), state2, isTunerEnabled(),
+ multiUserSwitchController.isMultiUserEnabled)
+ }
+
+ fun setExpansion(headerExpansionFraction: Float) {
+ mView.setExpansion(headerExpansionFraction)
+ }
+
+ fun updateAnimator(width: Int, numTiles: Int) {
+ mView.updateAnimator(width, numTiles)
+ }
+
+ fun setKeyguardShowing() {
+ mView.setKeyguardShowing()
+ }
+
+ private fun isTunerEnabled() = tunerService.isTunerEnabled
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
new file mode 100644
index 000000000000..fcfa72a82acb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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.qs
+
+import android.os.UserManager
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.qs.FooterActionsController.ExpansionState
+import com.android.systemui.qs.dagger.QSFlagsModule
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.tuner.TunerService
+import javax.inject.Inject
+import javax.inject.Named
+
+class FooterActionsControllerBuilder @Inject constructor(
+ private val qsPanelController: QSPanelController,
+ private val activityStarter: ActivityStarter,
+ private val userManager: UserManager,
+ private val userInfoController: UserInfoController,
+ private val multiUserSwitchController: MultiUserSwitchController,
+ private val deviceProvisionedController: DeviceProvisionedController,
+ private val falsingManager: FalsingManager,
+ private val metricsLogger: MetricsLogger,
+ private val tunerService: TunerService,
+ private val globalActionsDialog: GlobalActionsDialogLite,
+ private val uiEventLogger: UiEventLogger,
+ @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean
+) {
+ private lateinit var view: FooterActionsView
+ private lateinit var buttonsVisibleState: ExpansionState
+
+ fun withView(view: FooterActionsView): FooterActionsControllerBuilder {
+ this.view = view
+ return this
+ }
+
+ fun withButtonsVisibleWhen(state: ExpansionState): FooterActionsControllerBuilder {
+ buttonsVisibleState = state
+ return this
+ }
+
+ fun build(): FooterActionsController {
+ return FooterActionsController(view, qsPanelController, activityStarter, userManager,
+ userInfoController, multiUserSwitchController, deviceProvisionedController,
+ falsingManager, metricsLogger, tunerService, globalActionsDialog, uiEventLogger,
+ showPMLiteButton, buttonsVisibleState)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
new file mode 100644
index 000000000000..941e54a55393
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 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.qs
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.PorterDuff
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.RippleDrawable
+import android.os.UserManager
+import android.util.AttributeSet
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import com.android.settingslib.Utils
+import com.android.settingslib.drawable.UserIconDrawable
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.MultiUserSwitch
+import com.android.systemui.statusbar.phone.SettingsButton
+
+/**
+ * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS,
+ * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings,
+ * edit tiles, power off and conditionally: user switch and tuner
+ */
+class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+ private lateinit var settingsContainer: View
+ private lateinit var settingsButton: SettingsButton
+ private lateinit var multiUserSwitch: MultiUserSwitch
+ private lateinit var multiUserAvatar: ImageView
+ private lateinit var tunerIcon: View
+ private lateinit var editTilesButton: View
+
+ private var settingsCogAnimator: TouchAnimator? = null
+
+ private var qsDisabled = false
+ private var expansionAmount = 0f
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ editTilesButton = requireViewById(android.R.id.edit)
+ settingsButton = findViewById(R.id.settings_button)
+ settingsContainer = findViewById(R.id.settings_button_container)
+ multiUserSwitch = findViewById(R.id.multi_user_switch)
+ multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar)
+ tunerIcon = requireViewById(R.id.tuner_icon)
+
+ // RenderThread is doing more harm than good when touching the header (to expand quick
+ // settings), so disable it for this view
+ if (settingsButton.background is RippleDrawable) {
+ (settingsButton.background as RippleDrawable).setForceSoftware(true)
+ }
+ updateResources()
+ importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
+ }
+
+ fun updateAnimator(width: Int, numTiles: Int) {
+ val size = (mContext.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) -
+ mContext.resources.getDimensionPixelSize(R.dimen.qs_tile_padding))
+ val remaining = (width - numTiles * size) / (numTiles - 1)
+ val defSpace = mContext.resources.getDimensionPixelOffset(R.dimen.default_gear_space)
+ val translation = if (isLayoutRtl) (remaining - defSpace) else -(remaining - defSpace)
+ settingsCogAnimator = TouchAnimator.Builder()
+ .addFloat(settingsButton, "translationX", translation.toFloat(), 0f)
+ .addFloat(settingsButton, "rotation", -120f, 0f)
+ .build()
+ setExpansion(expansionAmount)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ override fun onRtlPropertiesChanged(layoutDirection: Int) {
+ super.onRtlPropertiesChanged(layoutDirection)
+ updateResources()
+ }
+
+ private fun updateResources() {
+ val tunerIconTranslation = mContext.resources
+ .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation).toFloat()
+ tunerIcon.translationX = if (isLayoutRtl) (-tunerIconTranslation) else tunerIconTranslation
+ }
+
+ fun setKeyguardShowing() {
+ setExpansion(expansionAmount)
+ }
+
+ fun setExpansion(headerExpansionFraction: Float) {
+ expansionAmount = headerExpansionFraction
+ if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction)
+ }
+
+ fun disable(
+ buttonsVisible: Boolean,
+ state2: Int,
+ isTunerEnabled: Boolean,
+ multiUserEnabled: Boolean
+ ) {
+ val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
+ if (disabled == qsDisabled) return
+ qsDisabled = disabled
+ updateEverything(buttonsVisible, isTunerEnabled, multiUserEnabled)
+ }
+
+ fun updateEverything(
+ buttonsVisible: Boolean,
+ isTunerEnabled: Boolean,
+ multiUserEnabled: Boolean
+ ) {
+ post {
+ updateVisibilities(buttonsVisible, isTunerEnabled, multiUserEnabled)
+ updateClickabilities()
+ isClickable = false
+ }
+ }
+
+ private fun updateClickabilities() {
+ multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE
+ editTilesButton.isClickable = editTilesButton.visibility == VISIBLE
+ settingsButton.isClickable = settingsButton.visibility == VISIBLE
+ }
+
+ private fun updateVisibilities(
+ buttonsVisible: Boolean,
+ isTunerEnabled: Boolean,
+ multiUserEnabled: Boolean
+ ) {
+ settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
+ tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE
+ multiUserSwitch.visibility = if (buttonsVisible && multiUserEnabled) VISIBLE else GONE
+ val isDemo = UserManager.isDeviceInDemoMode(context)
+ settingsButton.visibility = if (isDemo || !buttonsVisible) INVISIBLE else VISIBLE
+ }
+
+ fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {
+ var pictureToSet = picture
+ if (picture != null && isGuestUser && picture !is UserIconDrawable) {
+ pictureToSet = picture.constantState.newDrawable(resources).mutate()
+ pictureToSet.setColorFilter(
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
+ PorterDuff.Mode.SRC_IN)
+ }
+ multiUserAvatar.setImageDrawable(pictureToSet)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index ce1066ee41c2..1bd36644bbc5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -268,7 +268,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
}
@Override
- public void setExpansion(float expansion) {
+ public void setExpansion(float expansion, float proposedTranslation) {
mLastExpansion = expansion;
updateSelected();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 4fcd46c96fe3..8659b8b868d4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,6 +14,9 @@
package com.android.systemui.qs;
+import static com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER;
+import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER;
+
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.util.Log;
@@ -43,6 +46,7 @@ import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
+import javax.inject.Named;
/** */
@QSScope
@@ -67,13 +71,15 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
* position to the normal QS panel. These views will only show once the animation is complete,
* to prevent overlapping of semi transparent views
*/
- private final ArrayList<View> mQuickQsViews = new ArrayList<>();
+ private final ArrayList<View> mAnimatedQsViews = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel;
private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController;
private final QuickStatusBarHeader mQuickStatusBarHeader;
private final QSSecurityFooter mSecurityFooter;
private final QS mQs;
+ private final View mQSFooterActions;
+ private final View mQQSFooterActions;
private PagedTileLayout mPagedLayout;
@@ -88,6 +94,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// This animates fading of SecurityFooter and media divider
private TouchAnimator mAllPagesDelayedAnimator;
private TouchAnimator mBrightnessAnimator;
+ private TouchAnimator mQQSFooterActionsAnimator;
private HeightExpansionAnimator mQQSTileHeightAnimator;
private HeightExpansionAnimator mOtherTilesExpandAnimator;
@@ -110,12 +117,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
QSPanelController qsPanelController,
QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
- QSExpansionPathInterpolator qsExpansionPathInterpolator) {
+ QSExpansionPathInterpolator qsExpansionPathInterpolator,
+ @Named(QS_FOOTER) FooterActionsView qsFooterActionsView,
+ @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) {
mQs = qs;
mQuickQsPanel = quickPanel;
mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController;
mQuickStatusBarHeader = quickStatusBarHeader;
+ mQQSFooterActions = qqsFooterActionsView;
+ mQSFooterActions = qsFooterActionsView;
mSecurityFooter = securityFooter;
mHost = qsTileHost;
mExecutor = executor;
@@ -262,7 +273,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
clearAnimationState();
mAllViews.clear();
- mQuickQsViews.clear();
+ mAnimatedQsViews.clear();
mQQSTileHeightAnimator = null;
mOtherTilesExpandAnimator = null;
@@ -360,7 +371,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
firstPageBuilder.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1);
- mQuickQsViews.add(tileView);
+ mAnimatedQsViews.add(tileView);
mAllViews.add(quickTileView);
mAllViews.add(quickTileView.getSecondaryLabel());
} else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -417,6 +428,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
.addFloat(tileLayout, "alpha", 0, 1);
mFirstPageDelayedAnimator = builder.build();
+ if (mQQSFooterActions.getVisibility() != View.GONE) {
+ // only when qqs footer is present (which means split shade mode) it needs to
+ // be animated
+ updateQQSFooterAnimation();
+ }
+
+
// Fade in the security footer and the divider as we reach the final position
builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
@@ -452,6 +470,20 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
.addFloat(tileLayout, "alpha", 0, 1).build();
}
+ private void updateQQSFooterAnimation() {
+ int[] qsPosition = new int[2];
+ int[] qqsPosition = new int[2];
+ View commonView = mQs.getView();
+ getRelativePositionInt(qsPosition, mQSFooterActions, commonView);
+ getRelativePositionInt(qqsPosition, mQQSFooterActions, commonView);
+ int translationY = (qsPosition[1] - qqsPosition[1])
+ - mQuickStatusBarHeader.getOffsetTranslation();
+ mQQSFooterActionsAnimator = new TouchAnimator.Builder()
+ .addFloat(mQQSFooterActions, "translationY", 0, translationY)
+ .build();
+ mAnimatedQsViews.add(mQSFooterActions);
+ }
+
private boolean isIconInAnimatedRow(int count) {
if (mPagedLayout == null) {
return false;
@@ -521,6 +553,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mBrightnessAnimator != null) {
mBrightnessAnimator.setPosition(position);
}
+ if (mQQSFooterActionsAnimator != null) {
+ mQQSFooterActionsAnimator.setPosition(position);
+ }
}
}
@@ -532,9 +567,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
@Override
public void onAnimationAtEnd() {
mQuickQsPanel.setVisibility(View.INVISIBLE);
- final int N = mQuickQsViews.size();
+ final int N = mAnimatedQsViews.size();
for (int i = 0; i < N; i++) {
- mQuickQsViews.get(i).setVisibility(View.VISIBLE);
+ mAnimatedQsViews.get(i).setVisibility(View.VISIBLE);
}
}
@@ -542,9 +577,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
public void onAnimationStarted() {
updateQQSVisibility();
if (mOnFirstPage) {
- final int N = mQuickQsViews.size();
+ final int N = mAnimatedQsViews.size();
for (int i = 0; i < N; i++) {
- mQuickQsViews.get(i).setVisibility(View.INVISIBLE);
+ mAnimatedQsViews.get(i).setVisibility(View.INVISIBLE);
}
}
}
@@ -569,9 +604,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mOtherTilesExpandAnimator != null) {
mOtherTilesExpandAnimator.resetViewsHeights();
}
- final int N2 = mQuickQsViews.size();
+ final int N2 = mAnimatedQsViews.size();
for (int i = 0; i < N2; i++) {
- mQuickQsViews.get(i).setVisibility(View.VISIBLE);
+ mAnimatedQsViews.get(i).setVisibility(View.VISIBLE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index e38bd4bd9a38..0e0681b94c62 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -35,11 +35,6 @@ public interface QSFooter {
void setExpanded(boolean expanded);
/**
- * Returns the full height of the footer.
- */
- int getHeight();
-
- /**
* Sets the percentage amount that the quick settings has been expanded.
*
* @param expansion A value from 1 to 0 that indicates how much the quick settings have been
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index 57438d189b22..4d23958d56ab 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -21,60 +21,40 @@ import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import android.content.Context;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.android.settingslib.Utils;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
-import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
-import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.statusbar.phone.MultiUserSwitch;
-import com.android.systemui.statusbar.phone.SettingsButton;
-/** */
+/**
+ * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and
+ * {@link FooterActionsView}
+ */
public class QSFooterView extends FrameLayout {
- private SettingsButton mSettingsButton;
- protected View mSettingsContainer;
private PageIndicator mPageIndicator;
private TextView mBuildText;
- private boolean mShouldShowBuildText;
+ private View mActionsContainer;
- private boolean mQsDisabled;
+ protected TouchAnimator mFooterAnimator;
+ private boolean mQsDisabled;
private boolean mExpanded;
-
- private boolean mListening;
-
- protected MultiUserSwitch mMultiUserSwitch;
- private ImageView mMultiUserAvatar;
-
- protected TouchAnimator mFooterAnimator;
private float mExpansionAmount;
- protected View mEdit;
- private TouchAnimator mSettingsCogAnimator;
-
- private View mActionsContainer;
- private View mTunerIcon;
- private int mTunerIconTranslation;
+ private boolean mShouldShowBuildText;
private OnClickListener mExpandClickListener;
@@ -94,27 +74,11 @@ public class QSFooterView extends FrameLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mEdit = requireViewById(android.R.id.edit);
-
mPageIndicator = findViewById(R.id.footer_page_indicator);
-
- mSettingsButton = findViewById(R.id.settings_button);
- mSettingsContainer = findViewById(R.id.settings_button_container);
-
- mMultiUserSwitch = findViewById(R.id.multi_user_switch);
- mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
-
- mActionsContainer = requireViewById(R.id.qs_footer_actions_container);
+ mActionsContainer = requireViewById(R.id.qs_footer_actions);
mBuildText = findViewById(R.id.build);
- mTunerIcon = requireViewById(R.id.tuner_icon);
- // RenderThread is doing more harm than good when touching the header (to expand quick
- // settings), so disable it for this view
- if (mSettingsButton.getBackground() instanceof RippleDrawable) {
- ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- }
updateResources();
-
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
setBuildText();
}
@@ -137,18 +101,7 @@ public class QSFooterView extends FrameLayout {
}
}
- void updateAnimator(int width, int numTiles) {
- int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
- - mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding);
- int remaining = (width - numTiles * size) / (numTiles - 1);
- int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
-
- mSettingsCogAnimator = new Builder()
- .addFloat(mSettingsButton, "translationX",
- isLayoutRtl() ? (remaining - defSpace) : -(remaining - defSpace), 0)
- .addFloat(mSettingsButton, "rotation", -120, 0)
- .build();
-
+ void updateExpansion() {
setExpansion(mExpansionAmount);
}
@@ -158,20 +111,11 @@ public class QSFooterView extends FrameLayout {
updateResources();
}
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- updateResources();
- }
-
private void updateResources() {
updateFooterAnimator();
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.bottomMargin = getResources().getDimensionPixelSize(R.dimen.qs_footers_margin_bottom);
setLayoutParams(lp);
- mTunerIconTranslation = mContext.getResources()
- .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation);
- mTunerIcon.setTranslationX(isLayoutRtl() ? -mTunerIconTranslation : mTunerIconTranslation);
}
private void updateFooterAnimator() {
@@ -197,17 +141,15 @@ public class QSFooterView extends FrameLayout {
mExpandClickListener = onClickListener;
}
- void setExpanded(boolean expanded, boolean isTunerEnabled, boolean multiUserEnabled) {
+ void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
- updateEverything(isTunerEnabled, multiUserEnabled);
+ updateEverything();
}
/** */
public void setExpansion(float headerExpansionFraction) {
mExpansionAmount = headerExpansionFraction;
- if (mSettingsCogAnimator != null) mSettingsCogAnimator.setPosition(headerExpansionFraction);
-
if (mFooterAnimator != null) {
mFooterAnimator.setPosition(headerExpansionFraction);
}
@@ -228,14 +170,6 @@ public class QSFooterView extends FrameLayout {
super.onDetachedFromWindow();
}
- /** */
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mListening = listening;
- }
-
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
@@ -253,50 +187,26 @@ public class QSFooterView extends FrameLayout {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
}
- void disable(int state2, boolean isTunerEnabled, boolean multiUserEnabled) {
+ void disable(int state2) {
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
- updateEverything(isTunerEnabled, multiUserEnabled);
+ updateEverything();
}
- void updateEverything(boolean isTunerEnabled, boolean multiUserEnabled) {
+ void updateEverything() {
post(() -> {
- updateVisibilities(isTunerEnabled, multiUserEnabled);
+ updateVisibilities();
updateClickabilities();
setClickable(false);
});
}
private void updateClickabilities() {
- mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE);
- mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE);
- mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE);
mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE);
}
- private void updateVisibilities(boolean isTunerEnabled, boolean multiUserEnabled) {
- mSettingsContainer.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
- mTunerIcon.setVisibility(isTunerEnabled ? View.VISIBLE : View.INVISIBLE);
- final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
- mMultiUserSwitch.setVisibility(
- showUserSwitcher(multiUserEnabled) ? View.VISIBLE : View.GONE);
- mSettingsButton.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
-
+ private void updateVisibilities() {
mBuildText.setVisibility(mExpanded && mShouldShowBuildText ? View.VISIBLE : View.INVISIBLE);
}
-
- private boolean showUserSwitcher(boolean multiUserEnabled) {
- return mExpanded && multiUserEnabled;
- }
-
- void onUserInfoChanged(Drawable picture, boolean isGuestUser) {
- if (picture != null && isGuestUser && !(picture instanceof UserIconDrawable)) {
- picture = picture.getConstantState().newDrawable(getResources()).mutate();
- picture.setColorFilter(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
- Mode.SRC_IN);
- }
- mMultiUserAvatar.setImageDrawable(picture);
- }
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index 929aedae6706..e7c06e3c7ede 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -16,35 +16,18 @@
package com.android.systemui.qs;
-import static com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED;
+import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER;
import android.content.ClipData;
import android.content.ClipboardManager;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.os.UserManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -56,137 +39,45 @@ import javax.inject.Named;
@QSScope
public class QSFooterViewController extends ViewController<QSFooterView> implements QSFooter {
- private final UserManager mUserManager;
- private final UserInfoController mUserInfoController;
- private final ActivityStarter mActivityStarter;
- private final DeviceProvisionedController mDeviceProvisionedController;
private final UserTracker mUserTracker;
private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController;
- private final TunerService mTunerService;
- private final MetricsLogger mMetricsLogger;
- private final FalsingManager mFalsingManager;
- private final MultiUserSwitchController mMultiUserSwitchController;
- private final SettingsButton mSettingsButton;
- private final View mSettingsButtonContainer;
+ private final FooterActionsController mFooterActionsController;
private final TextView mBuildText;
- private final View mEdit;
private final PageIndicator mPageIndicator;
- private final View mPowerMenuLite;
- private final boolean mShowPMLiteButton;
- private final GlobalActionsDialogLite mGlobalActionsDialog;
- private final UiEventLogger mUiEventLogger;
-
- private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
- new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- boolean isGuestUser = mUserManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser());
- mView.onUserInfoChanged(picture, isGuestUser);
- }
- };
-
- private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Don't do anything until views are unhidden. Don't do anything if the tap looks
- // suspicious.
- if (!mExpanded || mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return;
- }
-
- if (v == mSettingsButton) {
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
- // If user isn't setup just unlock the device and dump them back at SUW.
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- });
- return;
- }
- mMetricsLogger.action(
- mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
- : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
- if (mSettingsButton.isTunerClick()) {
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- if (isTunerEnabled()) {
- mTunerService.showResetRequest(
- () -> {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast,
- Toast.LENGTH_LONG).show();
- mTunerService.setTunerEnabled(true);
- }
- startSettingsActivity();
-
- });
- } else {
- startSettingsActivity();
- }
- } else if (v == mPowerMenuLite) {
- mUiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
- mGlobalActionsDialog.showOrHideDialog(false, true);
- }
- }
- };
-
- private boolean mListening;
- private boolean mExpanded;
@Inject
- QSFooterViewController(QSFooterView view, UserManager userManager,
- UserInfoController userInfoController, ActivityStarter activityStarter,
- DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
+ QSFooterViewController(QSFooterView view,
+ UserTracker userTracker,
QSPanelController qsPanelController,
- MultiUserSwitchController multiUserSwitchController,
QuickQSPanelController quickQSPanelController,
- TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager,
- @Named(PM_LITE_ENABLED) boolean showPMLiteButton,
- GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger) {
+ @Named(QS_FOOTER) FooterActionsController footerActionsController) {
super(view);
- mUserManager = userManager;
- mUserInfoController = userInfoController;
- mActivityStarter = activityStarter;
- mDeviceProvisionedController = deviceProvisionedController;
mUserTracker = userTracker;
mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController;
- mTunerService = tunerService;
- mMetricsLogger = metricsLogger;
- mFalsingManager = falsingManager;
- mMultiUserSwitchController = multiUserSwitchController;
+ mFooterActionsController = footerActionsController;
- mSettingsButton = mView.findViewById(R.id.settings_button);
- mSettingsButtonContainer = mView.findViewById(R.id.settings_button_container);
mBuildText = mView.findViewById(R.id.build);
- mEdit = mView.findViewById(android.R.id.edit);
mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
- mPowerMenuLite = mView.findViewById(R.id.pm_lite);
- mShowPMLiteButton = showPMLiteButton;
- mGlobalActionsDialog = globalActionsDialog;
- mUiEventLogger = uiEventLogger;
}
@Override
protected void onInit() {
super.onInit();
- mMultiUserSwitchController.init();
+ mFooterActionsController.init();
}
@Override
protected void onViewAttached() {
- if (mShowPMLiteButton) {
- mPowerMenuLite.setVisibility(View.VISIBLE);
- mPowerMenuLite.setOnClickListener(mSettingsOnClickListener);
- } else {
- mPowerMenuLite.setVisibility(View.GONE);
- }
mView.addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
- mView.updateAnimator(
- right - left, mQuickQSPanelController.getNumQuickTiles()));
- mSettingsButton.setOnClickListener(mSettingsOnClickListener);
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ mView.updateExpansion();
+ mFooterActionsController.updateAnimator(right - left,
+ mQuickQSPanelController.getNumQuickTiles());
+ }
+ );
+
mBuildText.setOnLongClickListener(view -> {
CharSequence buildText = mBuildText.getText();
if (!TextUtils.isEmpty(buildText)) {
@@ -200,17 +91,8 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
}
return false;
});
-
- mEdit.setOnClickListener(view -> {
- if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
- return;
- }
- mActivityStarter.postQSRunnableDismissingKeyguard(() ->
- mQsPanelController.showEdit(view));
- });
-
mQsPanelController.setFooterPageIndicator(mPageIndicator);
- mView.updateEverything(isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
+ mView.updateEverything();
}
@Override
@@ -225,38 +107,25 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
@Override
public void setExpanded(boolean expanded) {
- mExpanded = expanded;
- mView.setExpanded(
- expanded, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
- }
-
- @Override
- public int getHeight() {
- return mView.getHeight();
+ mFooterActionsController.setExpanded(expanded);
+ mView.setExpanded(expanded);
}
@Override
public void setExpansion(float expansion) {
mView.setExpansion(expansion);
+ mFooterActionsController.setExpansion(expansion);
}
@Override
public void setListening(boolean listening) {
- if (mListening == listening) {
- return;
- }
-
- mListening = listening;
- if (mListening) {
- mUserInfoController.addCallback(mOnUserInfoChangedListener);
- } else {
- mUserInfoController.removeCallback(mOnUserInfoChangedListener);
- }
+ mFooterActionsController.setListening(listening);
}
@Override
public void setKeyguardShowing(boolean keyguardShowing) {
mView.setKeyguardShowing();
+ mFooterActionsController.setKeyguardShowing();
}
/** */
@@ -267,19 +136,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
@Override
public void disable(int state1, int state2, boolean animate) {
- mView.disable(state2, isTunerEnabled(), mMultiUserSwitchController.isMultiUserEnabled());
- }
-
- private void startSettingsActivity() {
- ActivityLaunchAnimator.Controller animationController =
- mSettingsButtonContainer != null ? ActivityLaunchAnimator.Controller.fromView(
- mSettingsButtonContainer,
- InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON) : null;
- mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */, animationController);
- }
-
- private boolean isTunerEnabled() {
- return mTunerService.isTunerEnabled();
+ mView.disable(state2);
+ mFooterActionsController.disable(state2);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f754494045d2..4242e1bb666b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.LifecycleFragment;
@@ -414,6 +415,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
return mQSPanelController;
}
+ public void setBrightnessMirrorController(
+ BrightnessMirrorController brightnessMirrorController) {
+ mQSPanelController.setBrightnessMirror(brightnessMirrorController);
+ mQuickQSPanelController.setBrightnessMirror(brightnessMirrorController);
+ }
+
@Override
public boolean isShowingDetail() {
return mQSCustomizerController.isCustomizing() || mQSDetail.isShowingDetail();
@@ -503,11 +510,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
: headerTranslation);
}
int currentHeight = getView().getHeight();
- mLastHeaderTranslation = headerTranslation;
- if (expansion == mLastQSExpansion && mLastKeyguardAndExpanded == onKeyguardAndExpanded
- && mLastViewHeight == currentHeight) {
+ if (expansion == mLastQSExpansion
+ && mLastKeyguardAndExpanded == onKeyguardAndExpanded
+ && mLastViewHeight == currentHeight
+ && mLastHeaderTranslation == headerTranslation) {
return;
}
+ mLastHeaderTranslation = headerTranslation;
mLastQSExpansion = expansion;
mLastKeyguardAndExpanded = onKeyguardAndExpanded;
mLastViewHeight = currentHeight;
@@ -527,8 +536,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
mQSPanelController.setRevealExpansion(expansion);
- mQSPanelController.getTileLayout().setExpansion(expansion);
- mQuickQSPanelController.getTileLayout().setExpansion(expansion);
+ mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
+ mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation);
mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
if (fullyCollapsed) {
mQSPanelScrollView.setScrollY(0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 63124ab2d80d..28aa884d6f9e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -736,7 +736,7 @@ public class QSPanel extends LinearLayout implements Tunable {
void setListening(boolean listening, UiEventLogger uiEventLogger);
/**
- * Set the minimum number of rows to show
+ * Sets the minimum number of rows to show
*
* @param minRows the minimum.
*/
@@ -745,7 +745,7 @@ public class QSPanel extends LinearLayout implements Tunable {
}
/**
- * Set the max number of columns to show
+ * Sets the max number of columns to show
*
* @param maxColumns the maximum
*
@@ -755,7 +755,10 @@ public class QSPanel extends LinearLayout implements Tunable {
return false;
}
- default void setExpansion(float expansion) {}
+ /**
+ * Sets the expansion value and proposedTranslation to panel.
+ */
+ default void setExpansion(float expansion, float proposedTranslation) {}
int getNumVisibleTiles();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index f3d071e900e3..6e09f22fba63 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -40,6 +40,7 @@ import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessController;
+import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
import com.android.systemui.settings.brightness.BrightnessSlider;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -60,10 +61,9 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
private final QSTileRevealController.Factory mQsTileRevealControllerFactory;
private final FalsingManager mFalsingManager;
private final BrightnessController mBrightnessController;
- private final BrightnessSlider.Factory mBrightnessSliderFactory;
private final BrightnessSlider mBrightnessSlider;
+ private final BrightnessMirrorHandler mBrightnessMirrorHandler;
- private BrightnessMirrorController mBrightnessMirrorController;
private boolean mGridContentVisible = true;
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
@@ -75,14 +75,10 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
if (mView.isListening()) {
refreshAllTiles();
}
- updateBrightnessMirror();
mView.switchSecurityFooter(mShouldUseSplitNotificationShade);
}
};
- private final BrightnessMirrorController.BrightnessMirrorListener mBrightnessMirrorListener =
- mirror -> updateBrightnessMirror();
-
private View.OnTouchListener mTileLayoutTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -110,12 +106,12 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mQsTileRevealControllerFactory = qsTileRevealControllerFactory;
mFalsingManager = falsingManager;
mQsSecurityFooter.setHostEnvironment(qstileHost);
- mBrightnessSliderFactory = brightnessSliderFactory;
- mBrightnessSlider = mBrightnessSliderFactory.create(getContext(), mView);
+ mBrightnessSlider = brightnessSliderFactory.create(getContext(), mView);
mView.setBrightnessView(mBrightnessSlider.getRootView());
mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
+ mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
}
@Override
@@ -142,9 +138,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
mView.setSecurityFooter(mQsSecurityFooter.getView(), mShouldUseSplitNotificationShade);
switchTileLayout(true);
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.addCallback(mBrightnessMirrorListener);
- }
+ mBrightnessMirrorHandler.onQsPanelAttached();
((PagedTileLayout) mView.getOrCreateTileLayout())
.setOnTouchListener(mTileLayoutTouchListener);
@@ -160,9 +154,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
protected void onViewDetached() {
mTunerService.removeTunable(mView);
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.removeCallback(mBrightnessMirrorListener);
- }
+ mBrightnessMirrorHandler.onQsPanelDettached();
super.onViewDetached();
}
@@ -196,23 +188,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
}
}
- /** */
public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
- mBrightnessMirrorController = brightnessMirrorController;
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.removeCallback(mBrightnessMirrorListener);
- }
- mBrightnessMirrorController = brightnessMirrorController;
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.addCallback(mBrightnessMirrorListener);
- }
- updateBrightnessMirror();
- }
-
- private void updateBrightnessMirror() {
- if (mBrightnessMirrorController != null) {
- mBrightnessSlider.setMirrorControllerAndMirror(mBrightnessMirrorController);
- }
+ mBrightnessMirrorHandler.setController(brightnessMirrorController);
}
/** Get the QSTileHost this panel uses. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 240cf93c77c6..541ee2c4fe8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -39,7 +39,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -512,33 +511,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
}
}
}
- // TODO(b/174753536): Move it into the config file.
- // Only do the below hacking when at least one of the below tiles exist
- // --InternetTile
- // --WiFiTile
- // --CellularTIle
- if (tiles.contains("internet") || tiles.contains("wifi") || tiles.contains("cell")) {
- if (FeatureFlags.isProviderModelSettingEnabled(context)) {
- if (!tiles.contains("internet")) {
- if (tiles.contains("wifi")) {
- // Replace the WiFi with Internet, and remove the Cell
- tiles.set(tiles.indexOf("wifi"), "internet");
- tiles.remove("cell");
- } else if (tiles.contains("cell")) {
- // Replace the Cell with Internet
- tiles.set(tiles.indexOf("cell"), "internet");
- }
- } else {
- tiles.remove("wifi");
- tiles.remove("cell");
- }
- } else {
- if (tiles.contains("internet")) {
- tiles.set(tiles.indexOf("internet"), "wifi");
- tiles.add("cell");
- }
- }
- }
return tiles;
}
@@ -558,14 +530,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
&& GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
}
- // TODO(b/174753536): Change the config file directly.
- // Filter out unused tiles from the default QS config.
- if (FeatureFlags.isProviderModelSettingEnabled(context)) {
- tiles.remove("cell");
- tiles.remove("wifi");
- } else {
- tiles.remove("internet");
- }
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
index 7c81abcfe584..14374ffe9f89 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
@@ -19,6 +19,8 @@ package com.android.systemui.qs
import androidx.annotation.VisibleForTesting
import com.android.systemui.settings.brightness.BrightnessController
import com.android.systemui.settings.brightness.BrightnessSlider
+import com.android.systemui.settings.brightness.MirroredBrightnessController
+import com.android.systemui.statusbar.policy.BrightnessMirrorController
import javax.inject.Inject
/**
@@ -27,7 +29,7 @@ import javax.inject.Inject
*/
class QuickQSBrightnessController @VisibleForTesting constructor(
private val brightnessControllerFactory: () -> BrightnessController
-) {
+) : MirroredBrightnessController {
@Inject constructor(
brightnessControllerFactory: BrightnessController.Factory,
@@ -42,6 +44,7 @@ class QuickQSBrightnessController @VisibleForTesting constructor(
private var isListening = false
private var brightnessController: BrightnessController? = null
+ private var mirrorController: BrightnessMirrorController? = null
fun init(shouldUseSplitNotificationShade: Boolean) {
refreshVisibility(shouldUseSplitNotificationShade)
@@ -77,6 +80,11 @@ class QuickQSBrightnessController @VisibleForTesting constructor(
}
}
+ override fun setMirror(controller: BrightnessMirrorController) {
+ mirrorController = controller
+ mirrorController?.let { brightnessController?.setMirror(it) }
+ }
+
private fun hideBrightnessSlider() {
brightnessController?.hideSlider()
}
@@ -84,11 +92,10 @@ class QuickQSBrightnessController @VisibleForTesting constructor(
private fun showBrightnessSlider() {
if (brightnessController == null) {
brightnessController = brightnessControllerFactory()
- }
- brightnessController?.showSlider()
- if (!isListening) {
+ mirrorController?.also { brightnessController?.setMirror(it) }
brightnessController?.registerCallbacks()
isListening = true
}
+ brightnessController?.showSlider()
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index f1c1e12b9648..613e7f87371c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -171,6 +171,8 @@ public class QuickQSPanel extends QSPanel {
static class QQSSideLabelTileLayout extends SideLabelTileLayout {
+ private boolean mLastSelected;
+
QQSSideLabelTileLayout(Context context) {
super(context, null);
setClipChildren(false);
@@ -216,5 +218,29 @@ public class QuickQSPanel extends QSPanel {
}
}
}
+
+ @Override
+ public void setExpansion(float expansion, float proposedTranslation) {
+ if (expansion > 0f && expansion < 1f) {
+ return;
+ }
+ // The cases we must set select for marquee when QQS/QS collapsed, and QS full expanded.
+ // Expansion == 0f is when QQS is fully showing (as opposed to 1f, which is QS). At this
+ // point we want them to be selected so the tiles will marquee (but not at other points
+ // of expansion.
+ boolean selected = (expansion == 1f || proposedTranslation < 0f);
+ if (mLastSelected == selected) {
+ return;
+ }
+ // We set it as not important while we change this, so setting each tile as selected
+ // will not cause them to announce themselves until the user has actually selected the
+ // item.
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).setSelected(selected);
+ }
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ mLastSelected = selected;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 74cd50c3f266..921ee35e3890 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs;
import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
+import static com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
import com.android.internal.logging.MetricsLogger;
@@ -29,6 +30,8 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +53,8 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
// brightness is visible only in split shade
private final QuickQSBrightnessController mBrightnessController;
+ private final BrightnessMirrorHandler mBrightnessMirrorHandler;
+ private final FooterActionsController mFooterActionsController;
@Inject
QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost,
@@ -58,11 +63,14 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager,
- QuickQSBrightnessController quickQSBrightnessController
+ QuickQSBrightnessController quickQSBrightnessController,
+ @Named(QQS_FOOTER) FooterActionsController footerActionsController
) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager);
mBrightnessController = quickQSBrightnessController;
+ mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
+ mFooterActionsController = footerActionsController;
}
@Override
@@ -72,30 +80,43 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
mMediaHost.setShowsOnlyActiveMedia(true);
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
mBrightnessController.init(mShouldUseSplitNotificationShade);
+ mFooterActionsController.init();
+ refreshFooterVisibility();
}
@Override
protected void onViewAttached() {
super.onViewAttached();
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ mBrightnessMirrorHandler.onQsPanelAttached();
}
@Override
protected void onViewDetached() {
super.onViewDetached();
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ mBrightnessMirrorHandler.onQsPanelDettached();
}
@Override
void setListening(boolean listening) {
super.setListening(listening);
mBrightnessController.setListening(listening);
+ mFooterActionsController.setListening(listening);
}
public boolean isListening() {
return mView.isListening();
}
+ private void refreshFooterVisibility() {
+ if (mShouldUseSplitNotificationShade) {
+ mFooterActionsController.showFooter();
+ } else {
+ mFooterActionsController.hideFooter();
+ }
+ }
+
private void setMaxTiles(int parseNumTiles) {
mView.setMaxTiles(parseNumTiles);
setTiles();
@@ -110,6 +131,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Override
protected void onScreenRotated() {
mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade);
+ refreshFooterVisibility();
}
@Override
@@ -132,4 +154,8 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
public int getNumQuickTiles() {
return mView.getNumQuickTiles();
}
+
+ public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
+ mBrightnessMirrorHandler.setController(brightnessMirrorController);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8cb9d46d273a..a85800bfa76e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -141,8 +141,6 @@ public class QuickStatusBarHeader extends FrameLayout {
updateResources();
- // Don't need to worry about tuner settings for this icon
- mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
// QS will always show the estimate, and BatteryMeterView handles the case where
// it's unavailable or charging
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 6c57c776089b..1841e605888d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -182,6 +182,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera);
mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone);
mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location);
+
+ // Don't need to worry about tuner settings for this icon
+ mBatteryMeterViewController.ignoreTunerUpdates();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 17708071c57c..3c2f35b954ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -34,7 +34,6 @@ import android.widget.Button;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.QSTileHost;
@@ -63,7 +62,6 @@ public class TileQueryHelper {
private final Executor mBgExecutor;
private final Context mContext;
private final UserTracker mUserTracker;
- private final FeatureFlags mFeatureFlags;
private TileStateListener mListener;
private boolean mFinished;
@@ -73,14 +71,12 @@ public class TileQueryHelper {
Context context,
UserTracker userTracker,
@Main Executor mainExecutor,
- @Background Executor bgExecutor,
- FeatureFlags featureFlags
+ @Background Executor bgExecutor
) {
mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
mUserTracker = userTracker;
- mFeatureFlags = featureFlags;
}
public void setListener(TileStateListener listener) {
@@ -121,19 +117,11 @@ public class TileQueryHelper {
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
- // TODO(b/174753536): Move it into the config file.
- if (mFeatureFlags.isProviderModelSettingEnabled()) {
- possibleTiles.remove("cell");
- possibleTiles.remove("wifi");
- } else {
- possibleTiles.remove("internet");
- }
for (String spec : possibleTiles) {
// Only add current and stock tiles that can be created from QSFactoryImpl.
// Do not include CustomTile. Those will be created by `addPackageTiles`.
if (spec.startsWith(CustomTile.PREFIX)) continue;
- // TODO(b/174753536): Move it into the config file.
final QSTile tile = host.createTile(spec);
if (tile == null) {
continue;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 2046550413d3..386769cd399e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -26,6 +26,10 @@ import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.FooterActionsController;
+import com.android.systemui.qs.FooterActionsController.ExpansionState;
+import com.android.systemui.qs.FooterActionsControllerBuilder;
+import com.android.systemui.qs.FooterActionsView;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFooterView;
@@ -49,6 +53,8 @@ import dagger.Provides;
@Module
public interface QSFragmentModule {
String QS_SECURITY_FOOTER_VIEW = "qs_security_footer";
+ String QQS_FOOTER = "qqs_footer";
+ String QS_FOOTER = "qs_footer";
String QS_USING_MEDIA_PLAYER = "qs_using_media_player";
/**
@@ -122,6 +128,44 @@ public interface QSFragmentModule {
/** */
@Provides
+ @Named(QS_FOOTER)
+ static FooterActionsView providesQSFooterActionsView(@RootView View view) {
+ return view.findViewById(R.id.qs_footer_actions);
+ }
+
+ /** */
+ @Provides
+ @Named(QQS_FOOTER)
+ static FooterActionsView providesQQSFooterActionsView(@RootView View view) {
+ return view.findViewById(R.id.qqs_footer_actions);
+ }
+
+ /** */
+ @Provides
+ @Named(QQS_FOOTER)
+ static FooterActionsController providesQQSFooterActionsController(
+ FooterActionsControllerBuilder footerActionsControllerBuilder,
+ @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) {
+ return footerActionsControllerBuilder
+ .withView(qqsFooterActionsView)
+ .withButtonsVisibleWhen(ExpansionState.COLLAPSED)
+ .build();
+ }
+
+ /** */
+ @Provides
+ @Named(QS_FOOTER)
+ static FooterActionsController providesQSFooterActionsController(
+ FooterActionsControllerBuilder footerActionsControllerBuilder,
+ @Named(QS_FOOTER) FooterActionsView qsFooterActionsView) {
+ return footerActionsControllerBuilder
+ .withView(qsFooterActionsView)
+ .withButtonsVisibleWhen(ExpansionState.EXPANDED)
+ .build();
+ }
+
+ /** */
+ @Provides
@QSScope
static QSFooter providesQSFooter(QSFooterViewController qsFooterViewController) {
qsFooterViewController.init();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 70685a68e182..222539d49526 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -195,9 +195,6 @@ open class QSTileViewImpl @JvmOverloads constructor(
// sibling methods to have special behavior for labelContainer.
labelContainer.forceUnspecifiedMeasure = true
secondaryLabel.alpha = 0f
- // Do not marque in QQS
- label.ellipsize = TextUtils.TruncateAt.END
- secondaryLabel.ellipsize = TextUtils.TruncateAt.END
}
setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE))
setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE))
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 92ae88db7c6d..d0a4b62b8a1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -438,7 +438,7 @@ public class InternetTile extends QSTileImpl<SignalState> {
state.icon = ResourceIcon.get(cb.mWifiSignalIconId);
}
} else if (cb.mNoDefaultNetwork) {
- if (cb.mNoNetworksAvailable) {
+ if (cb.mNoNetworksAvailable || !cb.mEnabled) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable);
state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable);
} else {
@@ -498,7 +498,7 @@ public class InternetTile extends QSTileImpl<SignalState> {
state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable);
state.secondaryLabel = r.getString(R.string.status_bar_airplane);
} else if (cb.mNoDefaultNetwork) {
- if (cb.mNoNetworksAvailable) {
+ if (cb.mNoNetworksAvailable || !mSignalCallback.mWifiInfo.mEnabled) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable);
state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index 13ee155d5af2..91c81bc506c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -97,7 +97,8 @@ public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.Intern
}
return mInternetDialogController.getWifiEntryList().stream()
- .filter(wifiEntry -> !wifiEntry.isDefaultNetwork())
+ .filter(wifiEntry -> (!wifiEntry.isDefaultNetwork()
+ || !wifiEntry.hasInternetAccess()))
.limit(getItemCount())
.collect(Collectors.toList());
}
@@ -107,21 +108,21 @@ public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.Intern
* {@link InternetDialog}.
*
* Airplane mode is ON (mobile network is gone):
- * Return four Wi-Fi's entries if no default Wi-Fi.
- * Return three Wi-Fi's entries if one default Wi-Fi.
+ * Return four Wi-Fi's entries if no internet Wi-Fi.
+ * Return three Wi-Fi's entries if one internet Wi-Fi.
* Airplane mode is OFF (mobile network is visible):
- * Return three Wi-Fi's entries if no default Wi-Fi.
- * Return two Wi-Fi's entries if one default Wi-Fi.
+ * Return three Wi-Fi's entries if no internet Wi-Fi.
+ * Return two Wi-Fi's entries if one internet Wi-Fi.
*
* @return The total number of networks.
*/
@Override
public int getItemCount() {
- final boolean hasDefaultWifi = mInternetDialogController.getDefaultWifiEntry() != null;
+ final boolean hasInternetWifi = mInternetDialogController.getInternetWifiEntry() != null;
if (mInternetDialogController.isAirplaneModeEnabled()) {
- return hasDefaultWifi ? 3 : 4;
+ return hasInternetWifi ? 3 : 4;
} else {
- return hasDefaultWifi ? 2 : 3;
+ return hasInternetWifi ? 2 : 3;
}
}
@@ -215,7 +216,7 @@ public class InternetAdapter extends RecyclerView.Adapter<InternetAdapter.Intern
return null;
}
drawable.setTint(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorTertiary));
final AtomicReference<Drawable> shared = new AtomicReference<>();
shared.set(drawable);
return shared.get();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 2a962bc90bab..e1e0ba7a8d03 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -112,7 +112,6 @@ public class InternetDialog extends SystemUIDialog implements
private LinearLayout mMobileNetworkList;
private LinearLayout mTurnWifiOnLayout;
private LinearLayout mSeeAllLayout;
- private Space mSpace;
private RecyclerView mWifiRecyclerView;
private ImageView mConnectedWifiIcon;
private ImageView mWifiSettingsIcon;
@@ -126,6 +125,7 @@ public class InternetDialog extends SystemUIDialog implements
private Button mDoneButton;
private Drawable mBackgroundOn;
private int mListMaxHeight;
+ private int mListMaxWidth;
private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mCanConfigMobileData;
@@ -174,6 +174,8 @@ public class InternetDialog extends SystemUIDialog implements
};
mListMaxHeight = context.getResources().getDimensionPixelSize(
R.dimen.internet_dialog_list_max_height);
+ mListMaxWidth = context.getResources().getDimensionPixelSize(
+ R.dimen.internet_dialog_list_max_width);
mUiEventLogger = uiEventLogger;
mAdapter = new InternetAdapter(mInternetDialogController);
if (!aboveStatusBar) {
@@ -200,7 +202,7 @@ public class InternetDialog extends SystemUIDialog implements
layoutParams.setFitInsetsIgnoringVisibility(true);
window.setAttributes(layoutParams);
window.setContentView(mDialogView);
- window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ window.setLayout(mListMaxWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
window.setWindowAnimations(R.style.Animation_InternetDialog);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.addFlags(FLAG_LAYOUT_NO_LIMITS);
@@ -221,7 +223,6 @@ public class InternetDialog extends SystemUIDialog implements
mWifiSettingsIcon = mDialogView.requireViewById(R.id.wifi_settings_icon);
mWifiRecyclerView = mDialogView.requireViewById(R.id.wifi_list_layout);
mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout);
- mSpace = mDialogView.requireViewById(R.id.space);
mDoneButton = mDialogView.requireViewById(R.id.done);
mSignalIcon = mDialogView.requireViewById(R.id.signal_icon);
mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title);
@@ -287,19 +288,27 @@ public class InternetDialog extends SystemUIDialog implements
}
showProgressBar();
setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular());
- setConnectedWifiLayout();
- boolean isWifiEnabled = mWifiManager.isWifiEnabled();
- mWiFiToggle.setChecked(isWifiEnabled);
- int visible = isWifiEnabled ? View.VISIBLE : View.GONE;
- mWifiRecyclerView.setVisibility(visible);
- mAdapter.notifyDataSetChanged();
- mSeeAllLayout.setVisibility(visible);
- mSpace.setVisibility(isWifiEnabled ? View.GONE : View.VISIBLE);
+
+ final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
+ final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+ updateWifiToggle(isWifiEnabled, isDeviceLocked);
+ updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+
+ List<WifiEntry> wifiEntryList = mInternetDialogController.getWifiEntryList();
+ final int wifiListVisibility =
+ (isDeviceLocked || wifiEntryList == null || wifiEntryList.size() <= 0)
+ ? View.GONE : View.VISIBLE;
+ mWifiRecyclerView.setVisibility(wifiListVisibility);
+ if (wifiListVisibility == View.VISIBLE) {
+ mAdapter.notifyDataSetChanged();
+ }
+ mSeeAllLayout.setVisibility(wifiListVisibility);
}
private void setOnClickListener() {
mMobileNetworkLayout.setOnClickListener(v -> {
- if (mInternetDialogController.isMobileDataEnabled()) {
+ if (mInternetDialogController.isMobileDataEnabled()
+ && !mInternetDialogController.isDeviceLocked()) {
if (!mInternetDialogController.activeNetworkIsCellular()) {
mInternetDialogController.connectCarrierNetwork();
}
@@ -320,7 +329,6 @@ public class InternetDialog extends SystemUIDialog implements
(buttonView, isChecked) -> {
buttonView.setChecked(isChecked);
mWifiManager.setWifiEnabled(isChecked);
- mSpace.setVisibility(isChecked ? View.GONE : View.VISIBLE);
});
mDoneButton.setOnClickListener(v -> dismiss());
}
@@ -341,35 +349,46 @@ public class InternetDialog extends SystemUIDialog implements
mMobileSummaryText.setVisibility(View.GONE);
}
mSignalIcon.setImageDrawable(getSignalStrengthDrawable());
- int titleColor = isCellularNetwork ? mContext.getColor(
- R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor(
- mContext, android.R.attr.textColorPrimary);
- int summaryColor = isCellularNetwork ? mContext.getColor(
- R.color.connected_network_tertiary_color) : Utils.getColorAttrDefaultColor(
- mContext, android.R.attr.textColorTertiary);
- mMobileTitleText.setTextColor(titleColor);
- mMobileSummaryText.setTextColor(summaryColor);
+ if (mInternetDialogController.isNightMode()) {
+ int titleColor = isCellularNetwork ? mContext.getColor(
+ R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor(
+ mContext, android.R.attr.textColorPrimary);
+ int summaryColor = isCellularNetwork ? mContext.getColor(
+ R.color.connected_network_secondary_color) : Utils.getColorAttrDefaultColor(
+ mContext, android.R.attr.textColorSecondary);
+
+ mMobileTitleText.setTextColor(titleColor);
+ mMobileSummaryText.setTextColor(summaryColor);
+ }
mMobileNetworkLayout.setBackground(isCellularNetwork ? mBackgroundOn : null);
mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
}
}
- private void setConnectedWifiLayout() {
- if (!mWifiManager.isWifiEnabled() || mConnectedWifiEntry == null) {
+ private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
+ mWiFiToggle.setChecked(isWifiEnabled);
+ mTurnWifiOnLayout.setBackground(
+ (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
+ }
+
+ private void updateConnectedWifi(boolean isWifiEnabled, boolean isDeviceLocked) {
+ if (!isWifiEnabled || mConnectedWifiEntry == null || isDeviceLocked) {
mConnectedWifListLayout.setBackground(null);
mConnectedWifListLayout.setVisibility(View.GONE);
return;
}
mConnectedWifListLayout.setVisibility(View.VISIBLE);
- mConnectedWifiTitleText.setText(getConnectedWifiTitle());
- mConnectedWifiSummaryText.setText(getConnectedWifiSummary());
+ mConnectedWifiTitleText.setText(mInternetDialogController.getInternetWifiTitle());
+ mConnectedWifiSummaryText.setText(mInternetDialogController.getInternetWifiSummary());
mConnectedWifiIcon.setImageDrawable(
- mInternetDialogController.getConnectedWifiDrawable(mConnectedWifiEntry));
- mConnectedWifiTitleText.setTextColor(
- mContext.getColor(R.color.connected_network_primary_color));
- mConnectedWifiSummaryText.setTextColor(
- mContext.getColor(R.color.connected_network_tertiary_color));
+ mInternetDialogController.getInternetWifiDrawable(mConnectedWifiEntry));
+ if (mInternetDialogController.isNightMode()) {
+ mConnectedWifiTitleText.setTextColor(
+ mContext.getColor(R.color.connected_network_primary_color));
+ mConnectedWifiSummaryText.setTextColor(
+ mContext.getColor(R.color.connected_network_secondary_color));
+ }
mWifiSettingsIcon.setColorFilter(
mContext.getColor(R.color.connected_network_primary_color));
mConnectedWifListLayout.setBackground(mBackgroundOn);
@@ -404,16 +423,9 @@ public class InternetDialog extends SystemUIDialog implements
return mInternetDialogController.getMobileNetworkSummary();
}
- String getConnectedWifiTitle() {
- return mInternetDialogController.getDefaultWifiTitle();
- }
-
- String getConnectedWifiSummary() {
- return mInternetDialogController.getDefaultWifiSummary();
- }
-
protected void showProgressBar() {
- if (mWifiManager == null || !mWifiManager.isWifiEnabled()) {
+ if (mWifiManager == null || !mWifiManager.isWifiEnabled()
+ || mInternetDialogController.isDeviceLocked()) {
setProgressBarVisible(false);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 5c22e855a3d0..ed32730c58b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -23,6 +23,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -66,6 +67,7 @@ import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.util.settings.GlobalSettings;
@@ -96,6 +98,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off;
private static final int SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT =
R.string.tap_a_network_to_connect;
+ private static final int SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS =
+ R.string.unlock_to_view_networks;
private static final int SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS =
R.string.wifi_empty_list_wifi_on;
private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE =
@@ -136,6 +140,9 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
@VisibleForTesting
protected WifiUtils.InternetIconInjector mWifiIconInjector;
+ @VisibleForTesting
+ KeyguardStateController mKeyguardStateController;
+
private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -160,7 +167,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
@Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
@Main Handler handler, @Main Executor mainExecutor,
BroadcastDispatcher broadcastDispatcher, KeyguardUpdateMonitor keyguardUpdateMonitor,
- GlobalSettings globalSettings) {
+ GlobalSettings globalSettings, KeyguardStateController keyguardStateController) {
if (DEBUG) {
Log.d(TAG, "Init InternetDialogController");
}
@@ -174,6 +181,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mSubscriptionManager = subscriptionManager;
mBroadcastDispatcher = broadcastDispatcher;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardStateController = keyguardStateController;
mConnectionStateFilter = new IntentFilter();
mConnectionStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mConnectionStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
@@ -271,6 +279,15 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return mContext.getText(SUBTITLE_TEXT_WIFI_IS_OFF);
}
+ if (isDeviceLocked()) {
+ // When the device is locked.
+ // Sub-Title: Unlock to view networks
+ if (DEBUG) {
+ Log.d(TAG, "The device is locked.");
+ }
+ return mContext.getText(SUBTITLE_TEXT_UNLOCK_TO_VIEW_NETWORKS);
+ }
+
final List<ScanResult> wifiList = mWifiManager.getScanResults();
if (wifiList != null && wifiList.size() != 0) {
return mContext.getText(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT);
@@ -317,17 +334,21 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return mContext.getText(SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE);
}
- Drawable getConnectedWifiDrawable(@NonNull WifiEntry wifiEntry) {
+ Drawable getInternetWifiDrawable(@NonNull WifiEntry wifiEntry) {
final Drawable drawable =
- mWifiIconInjector.getIcon(false /* noInternet*/, wifiEntry.getLevel());
+ mWifiIconInjector.getIcon(wifiEntry.shouldShowXLevelIcon(), wifiEntry.getLevel());
if (drawable == null) {
return null;
}
- drawable.setTint(Utils.getColorAttrDefaultColor(mContext,
- com.android.internal.R.attr.colorControlNormal));
+ drawable.setTint(mContext.getColor(R.color.connected_network_primary_color));
return drawable;
}
+ boolean isNightMode() {
+ return (mContext.getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+ }
+
Drawable getSignalStrengthDrawable() {
Drawable drawable = mContext.getDrawable(
R.drawable.ic_signal_strength_zero_bar_no_internet);
@@ -345,8 +366,9 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
drawable = shared.get();
}
- drawable.setTint(
- Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
+ drawable.setTint(activeNetworkIsCellular() ? mContext.getColor(
+ R.color.connected_network_primary_color) : Utils.getColorAttrDefaultColor(
+ mContext, android.R.attr.textColorTertiary));
} catch (Throwable e) {
e.printStackTrace();
}
@@ -393,7 +415,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
// Set the signal strength icon at the bottom right
icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT);
icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize);
- icons.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
+ icons.setTintList(Utils.getColorAttr(context, android.R.attr.textColorTertiary));
return icons;
}
@@ -527,24 +549,24 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return summary;
}
- String getDefaultWifiTitle() {
- if (getDefaultWifiEntry() == null) {
+ String getInternetWifiTitle() {
+ if (getInternetWifiEntry() == null) {
if (DEBUG) {
Log.d(TAG, "connected entry is null");
}
return "";
}
- return getDefaultWifiEntry().getTitle();
+ return getInternetWifiEntry().getTitle();
}
- String getDefaultWifiSummary() {
- if (getDefaultWifiEntry() == null) {
+ String getInternetWifiSummary() {
+ if (getInternetWifiEntry() == null) {
if (DEBUG) {
Log.d(TAG, "connected entry is null");
}
return "";
}
- return getDefaultWifiEntry().getSummary(false);
+ return getInternetWifiEntry().getSummary(false);
}
void launchNetworkSetting() {
@@ -572,11 +594,12 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return mWifiEntry;
}
- WifiEntry getDefaultWifiEntry() {
- if (mConnectedEntry != null && mConnectedEntry.isDefaultNetwork()) {
- return mConnectedEntry;
+ WifiEntry getInternetWifiEntry() {
+ if (mConnectedEntry == null || !mConnectedEntry.isDefaultNetwork()
+ || !mConnectedEntry.hasInternetAccess()) {
+ return null;
}
- return null;
+ return mConnectedEntry;
}
WifiManager getWifiManager() {
@@ -677,6 +700,10 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
&& serviceState.getState() == serviceState.STATE_IN_SERVICE;
}
+ public boolean isDeviceLocked() {
+ return !mKeyguardStateController.isUnlocked();
+ }
+
boolean activeNetworkIsCellular() {
if (mConnectivityManager == null) {
if (DEBUG) {
@@ -775,7 +802,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mConnectedEntry = null;
}
- mCallback.onAccessPointsChanged(mWifiEntry, getDefaultWifiEntry());
+ mCallback.onAccessPointsChanged(mWifiEntry, getInternetWifiEntry());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index eb72296d5c5b..658be729a34c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -78,6 +78,7 @@ import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBar;
import com.android.systemui.navigationbar.NavigationBarController;
@@ -427,6 +428,19 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
};
+ private final BroadcastReceiver mDebugAnyPackageChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String[] stringArrayExtra = intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ Log.e("b/188806432", intent.toString()
+ + (stringArrayExtra != null
+ ? ", EXTRA_CHANGED_COMPONENT_NAME_LIST: " + String.join(", ",
+ stringArrayExtra)
+ : ""));
+ }
+ };
+
private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -530,6 +544,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher,
ShellTransitions shellTransitions,
+ ScreenLifecycle screenLifecycle,
Optional<StartingSurface> startingSurface,
SmartspaceTransitionController smartspaceTransitionController) {
super(broadcastDispatcher);
@@ -566,6 +581,13 @@ public class OverviewProxyService extends CurrentUserTracker implements
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
mContext.registerReceiver(mLauncherStateChangedReceiver, filter);
+ // b/188806432
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ filter.addDataSchemeSpecificPart("", PatternMatcher.PATTERN_PREFIX);
+ mContext.registerReceiver(mDebugAnyPackageChangedReceiver, filter);
+
// Listen for status bar state changes
statusBarWinController.registerCallback(mStatusBarWindowCallback);
mScreenshotHelper = new ScreenshotHelper(context);
@@ -588,6 +610,13 @@ public class OverviewProxyService extends CurrentUserTracker implements
// Listen for user setup
startTracking();
+ screenLifecycle.addObserver(new ScreenLifecycle.Observer() {
+ @Override
+ public void onScreenTurnedOn() {
+ notifyScreenTurnedOn();
+ }
+ });
+
// Connect to the service
updateEnabledState();
startConnectionToCurrentUser();
@@ -880,6 +909,21 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
+ /**
+ * Notifies the Launcher that screen turned on and ready to use
+ */
+ public void notifyScreenTurnedOn() {
+ try {
+ if (mOverviewProxy != null) {
+ mOverviewProxy.onScreenTurnedOn();
+ } else {
+ Log.e(TAG_OPS, "Failed to get overview proxy for screen turned on event.");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG_OPS, "Failed to call notifyScreenTurnedOn()", e);
+ }
+ }
+
void notifyToggleRecentApps() {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
mConnectionCallbacks.get(i).onToggleRecentApps();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index a9ebcad8304f..acc6ee130539 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -30,7 +30,6 @@ import android.hardware.display.DisplayManager.DisplayListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
-import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -47,15 +46,16 @@ import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.systemui.Dependency;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import java.util.ArrayList;
import javax.inject.Inject;
-public class BrightnessController implements ToggleSlider.Listener {
+public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
private static final String TAG = "StatusBar.BrightnessController";
private static final int SLIDER_ANIMATION_DURATION = 3000;
@@ -109,6 +109,11 @@ public class BrightnessController implements ToggleSlider.Listener {
private ValueAnimator mSliderAnimator;
+ @Override
+ public void setMirror(BrightnessMirrorController controller) {
+ mControl.setMirrorControllerAndMirror(controller);
+ }
+
public interface BrightnessStateChangeCallback {
/** Indicates that some of the brightness settings have changed */
void onBrightnessLevelChanged();
@@ -282,12 +287,15 @@ public class BrightnessController implements ToggleSlider.Listener {
}
};
- public BrightnessController(Context context, ToggleSlider control,
- BroadcastDispatcher broadcastDispatcher) {
+ public BrightnessController(
+ Context context,
+ ToggleSlider control,
+ BroadcastDispatcher broadcastDispatcher,
+ @Background Handler bgHandler) {
mContext = context;
mControl = control;
mControl.setMax(GAMMA_SPACE_MAX);
- mBackgroundHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
+ mBackgroundHandler = bgHandler;
mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
@@ -458,16 +466,25 @@ public class BrightnessController implements ToggleSlider.Listener {
public static class Factory {
private final Context mContext;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final Handler mBackgroundHandler;
@Inject
- public Factory(Context context, BroadcastDispatcher broadcastDispatcher) {
+ public Factory(
+ Context context,
+ BroadcastDispatcher broadcastDispatcher,
+ @Background Handler bgHandler) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
+ mBackgroundHandler = bgHandler;
}
/** Create a {@link BrightnessController} */
public BrightnessController create(ToggleSlider toggleSlider) {
- return new BrightnessController(mContext, toggleSlider, mBroadcastDispatcher);
+ return new BrightnessController(
+ mContext,
+ toggleSlider,
+ mBroadcastDispatcher,
+ mBackgroundHandler);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 0f97e43c466b..8fc831a7ce4d 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -21,6 +21,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.app.Activity;
import android.os.Bundle;
+import android.os.Handler;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
@@ -32,6 +33,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Background;
import javax.inject.Inject;
@@ -41,13 +43,16 @@ public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
private final BrightnessSlider.Factory mToggleSliderFactory;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final Handler mBackgroundHandler;
@Inject
public BrightnessDialog(
BroadcastDispatcher broadcastDispatcher,
- BrightnessSlider.Factory factory) {
+ BrightnessSlider.Factory factory,
+ @Background Handler bgHandler) {
mBroadcastDispatcher = broadcastDispatcher;
mToggleSliderFactory = factory;
+ mBackgroundHandler = bgHandler;
}
@@ -76,7 +81,8 @@ public class BrightnessDialog extends Activity {
controller.init();
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
- mBrightnessController = new BrightnessController(this, controller, mBroadcastDispatcher);
+ mBrightnessController = new BrightnessController(
+ this, controller, mBroadcastDispatcher, mBackgroundHandler);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
new file mode 100644
index 000000000000..51aa339149a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.settings.brightness
+
+import com.android.systemui.statusbar.policy.BrightnessMirrorController
+import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener
+
+class BrightnessMirrorHandler(private val brightnessController: MirroredBrightnessController) {
+
+ private var mirrorController: BrightnessMirrorController? = null
+
+ private val brightnessMirrorListener = BrightnessMirrorListener { updateBrightnessMirror() }
+
+ fun onQsPanelAttached() {
+ mirrorController?.addCallback(brightnessMirrorListener)
+ }
+
+ fun onQsPanelDettached() {
+ mirrorController?.removeCallback(brightnessMirrorListener)
+ }
+
+ fun setController(controller: BrightnessMirrorController) {
+ mirrorController?.removeCallback(brightnessMirrorListener)
+ mirrorController = controller
+ mirrorController?.addCallback(brightnessMirrorListener)
+ updateBrightnessMirror()
+ }
+
+ private fun updateBrightnessMirror() {
+ mirrorController?.let { brightnessController.setMirror(it) }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
index 896106a82fe4..b0e320ad1e2f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
@@ -140,13 +140,7 @@ public class BrightnessSlider extends ViewController<BrightnessSliderView> imple
@Override
public void setMirrorControllerAndMirror(BrightnessMirrorController c) {
mMirrorController = c;
- if (c != null) {
- setMirror(c.getToggleSlider());
- } else {
- // If there's no mirror, we may be the ones dispatching, events but we should not mirror
- // them
- mView.setOnDispatchTouchEventListener(null);
- }
+ setMirror(c.getToggleSlider());
}
@Override
diff --git a/core/java/android/uwb/RangingReport.aidl b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
index c32747ae58da..8d857dec2108 100644
--- a/core/java/android/uwb/RangingReport.aidl
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -11,9 +11,16 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
*/
-package android.uwb;
+package com.android.systemui.settings.brightness
-parcelable RangingReport;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController
+
+/**
+ * Indicates controller that has brightness slider and uses [BrightnessMirrorController]
+ */
+interface MirroredBrightnessController {
+ fun setMirror(controller: BrightnessMirrorController)
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index acfd998ff6e4..8e6cf36f8e74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -17,14 +17,10 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
-import android.view.DisplayCutout;
import android.view.View;
import android.widget.TextView;
@@ -42,22 +38,14 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry.
public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
private static final String HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE =
"heads_up_status_bar_view_super_parcelable";
- private static final String FIRST_LAYOUT = "first_layout";
private static final String VISIBILITY = "visibility";
private static final String ALPHA = "alpha";
- private int mAbsoluteStartPadding;
- private int mEndMargin;
+ private final Rect mLayoutedIconRect = new Rect();
+ private final int[] mTmpPosition = new int[2];
+ private final Rect mIconDrawingRect = new Rect();
private View mIconPlaceholder;
private TextView mTextView;
private NotificationEntry mShowingEntry;
- private Rect mLayoutedIconRect = new Rect();
- private int[] mTmpPosition = new int[2];
- private boolean mFirstLayout = true;
- private int mMaxWidth;
- private int mSysWinInset;
- private int mCutOutInset;
- private Rect mIconDrawingRect = new Rect();
- private Point mDisplaySize;
private Runnable mOnDrawingRectChangedListener;
public HeadsUpStatusBarView(Context context) {
@@ -75,40 +63,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
public HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- Resources res = getResources();
- mAbsoluteStartPadding = res.getDimensionPixelSize(R.dimen.notification_side_paddings)
- + res.getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_start);
- mEndMargin = res.getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
- setPaddingRelative(mAbsoluteStartPadding, 0, mEndMargin, 0);
- updateMaxWidth();
- }
-
- private void updateMaxWidth() {
- int maxWidth = getResources().getDimensionPixelSize(R.dimen.qs_panel_width);
- if (maxWidth != mMaxWidth) {
- // maxWidth doesn't work with fill_parent, let's manually make it at most as big as the
- // notification panel
- mMaxWidth = maxWidth;
- requestLayout();
- }
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mMaxWidth > 0) {
- int newSize = Math.min(MeasureSpec.getSize(widthMeasureSpec), mMaxWidth);
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(newSize,
- MeasureSpec.getMode(widthMeasureSpec));
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateMaxWidth();
}
@Override
@@ -116,7 +70,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
Bundle bundle = new Bundle();
bundle.putParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE,
super.onSaveInstanceState());
- bundle.putBoolean(FIRST_LAYOUT, mFirstLayout);
bundle.putInt(VISIBILITY, getVisibility());
bundle.putFloat(ALPHA, getAlpha());
@@ -125,7 +78,7 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
@Override
public void onRestoreInstanceState(Parcelable state) {
- if (state == null || !(state instanceof Bundle)) {
+ if (!(state instanceof Bundle)) {
super.onRestoreInstanceState(state);
return;
}
@@ -133,7 +86,6 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
Bundle bundle = (Bundle) state;
Parcelable superState = bundle.getParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE);
super.onRestoreInstanceState(superState);
- mFirstLayout = bundle.getBoolean(FIRST_LAYOUT, true);
if (bundle.containsKey(VISIBILITY)) {
setVisibility(bundle.getInt(VISIBILITY));
}
@@ -185,70 +137,22 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mIconPlaceholder.getLocationOnScreen(mTmpPosition);
- int left = (int) (mTmpPosition[0] - getTranslationX());
+ int left = mTmpPosition[0];
int top = mTmpPosition[1];
int right = left + mIconPlaceholder.getWidth();
int bottom = top + mIconPlaceholder.getHeight();
mLayoutedIconRect.set(left, top, right, bottom);
updateDrawingRect();
- int targetPadding = mAbsoluteStartPadding + mSysWinInset + mCutOutInset;
- boolean isRtl = isLayoutRtl();
- int start = isRtl ? (mDisplaySize.x - right) : left;
- if (start != targetPadding) {
- int newPadding = targetPadding - start + getPaddingStart();
- setPaddingRelative(newPadding, 0, mEndMargin, 0);
- }
- if (mFirstLayout) {
- // we need to do the padding calculation in the first frame, so the layout specified
- // our visibility to be INVISIBLE in the beginning. let's correct that and set it
- // to GONE.
- setVisibility(GONE);
- mFirstLayout = false;
- }
- }
-
- /** In order to do UI alignment, this view will be notified by
- * {@link com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout}.
- * After scroller laid out, the scroller will tell this view about scroller's getX()
- * @param translationX how to translate the horizontal position
- */
- public void setPanelTranslation(float translationX) {
- setTranslationX(translationX);
- updateDrawingRect();
}
private void updateDrawingRect() {
float oldLeft = mIconDrawingRect.left;
mIconDrawingRect.set(mLayoutedIconRect);
- mIconDrawingRect.offset((int) getTranslationX(), 0);
if (oldLeft != mIconDrawingRect.left && mOnDrawingRectChangedListener != null) {
mOnDrawingRectChangedListener.run();
}
}
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- boolean isRtl = isLayoutRtl();
- mSysWinInset = isRtl ? insets.right : insets.left;
- DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
- mCutOutInset = (displayCutout != null)
- ? (isRtl ? displayCutout.getSafeInsetRight() : displayCutout.getSafeInsetLeft())
- : 0;
-
- getDisplaySize();
-
- // For Double Cut Out mode, the System window navigation bar is at the right
- // side of the left cut out. In this condition, mSysWinInset include the left cut
- // out width so we set mCutOutInset to be 0. For RTL, the condition is the same.
- // The navigation bar is at the left side of the right cut out and include the
- // right cut out width.
- if (mSysWinInset != 0) {
- mCutOutInset = 0;
- }
-
- return super.fitSystemWindows(insets);
- }
-
public NotificationEntry getShowingEntry() {
return mShowingEntry;
}
@@ -264,17 +168,4 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
public void setOnDrawingRectChangedListener(Runnable onDrawingRectChangedListener) {
mOnDrawingRectChangedListener = onDrawingRectChangedListener;
}
-
- private void getDisplaySize() {
- if (mDisplaySize == null) {
- mDisplaySize = new Point();
- }
- getDisplay().getRealSize(mDisplaySize);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- getDisplaySize();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 3890c1aa4e4f..503b5c0ee4b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -825,7 +825,11 @@ public class KeyguardIndicationController {
if (mKeyguardUpdateMonitor.isUdfpsAvailable()) {
// if udfps available, there will always be a tappable affordance to unlock
// For example, the lock icon
- showTransientIndication(R.string.keyguard_unlock_press);
+ if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) {
+ showTransientIndication(R.string.keyguard_unlock_press);
+ } else {
+ showTransientIndication(R.string.keyguard_face_failed_use_fp);
+ }
} else {
showTransientIndication(R.string.keyguard_try_fingerprint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index db553e4b093b..002c9c7d2544 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -178,7 +178,8 @@ class NotificationShadeDepthController @Inject constructor(
blurUtils.minBlurRadius, blurUtils.maxBlurRadius)
var combinedBlur = (shadeSpring.radius * INTERACTION_BLUR_FRACTION +
normalizedBlurRadius * ANIMATION_BLUR_FRACTION).toInt()
- combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsPanelExpansion))
+ val qsExpandedRatio = qsPanelExpansion * shadeExpansion
+ combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio))
combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius).toFloat()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index f2060b740860..fdbe72879374 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -31,6 +31,8 @@ import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
import android.view.ViewGroup
import com.android.settingslib.Utils
import com.android.systemui.R
@@ -44,14 +46,21 @@ import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.AnimatableProperty
+import com.android.systemui.statusbar.notification.PropertyAnimator
+import com.android.systemui.statusbar.notification.stack.AnimationProperties
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.Execution
import com.android.systemui.util.settings.SecureSettings
-import java.lang.RuntimeException
import java.util.Optional
import java.util.concurrent.Executor
import javax.inject.Inject
+private val ANIMATION_PROPERTIES = AnimationProperties()
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD.toLong())
+
/**
* Controller for managing the smartspace view on the lockscreen
*/
@@ -72,10 +81,15 @@ class LockscreenSmartspaceController @Inject constructor(
@Main private val handler: Handler,
optionalPlugin: Optional<BcSmartspaceDataPlugin>
) {
+
+ var splitShadeContainer: ViewGroup? = null
+ private var singlePaneContainer: ViewGroup? = null
+
private var session: SmartspaceSession? = null
private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
private lateinit var smartspaceView: SmartspaceView
+ // smartspace casted to View
lateinit var view: View
private set
@@ -83,12 +97,60 @@ class LockscreenSmartspaceController @Inject constructor(
private var showSensitiveContentForManagedUser = false
private var managedUserHandle: UserHandle? = null
- fun isEnabled(): Boolean {
+ private var isAod = false
+ private var isSplitShade = false
+
+ fun isSmartspaceEnabled(): Boolean {
execution.assertIsMainThread()
return featureFlags.isSmartspaceEnabled && plugin != null
}
+ fun setKeyguardStatusContainer(container: ViewGroup) {
+ singlePaneContainer = container
+ // reattach smartspace if necessary as this might be a new container
+ updateSmartSpaceContainer()
+ }
+
+ fun onSplitShadeChanged(splitShade: Boolean) {
+ isSplitShade = splitShade
+ updateSmartSpaceContainer()
+ }
+
+ private fun updateSmartSpaceContainer() {
+ if (!isSmartspaceEnabled()) return
+ // in AOD we always want to show smartspace on the left i.e. in singlePaneContainer
+ if (isSplitShade && !isAod) {
+ switchContainerVisibility(
+ newParent = splitShadeContainer,
+ oldParent = singlePaneContainer)
+ } else {
+ switchContainerVisibility(
+ newParent = singlePaneContainer,
+ oldParent = splitShadeContainer)
+ }
+ requestSmartspaceUpdate()
+ }
+
+ private fun switchContainerVisibility(newParent: ViewGroup?, oldParent: ViewGroup?) {
+ // it might be the case that smartspace was already attached and we just needed to update
+ // visibility, e.g. going from lockscreen -> unlocked -> lockscreen
+ if (newParent?.childCount == 0) {
+ oldParent?.removeAllViews()
+ newParent.addView(buildAndConnectView(newParent))
+ }
+ oldParent?.visibility = GONE
+ newParent?.visibility = VISIBLE
+ }
+
+ fun setSplitShadeSmartspaceAlpha(alpha: Float) {
+ // the other container's alpha is modified as a part of keyguard status view, so we don't
+ // have to do that here
+ if (splitShadeContainer?.visibility == VISIBLE) {
+ splitShadeContainer?.alpha = alpha
+ }
+ }
+
/**
* Constructs the smartspace view and connects it to the smartspace service. Subsequent calls
* are idempotent until [disconnect] is called.
@@ -96,7 +158,7 @@ class LockscreenSmartspaceController @Inject constructor(
fun buildAndConnectView(parent: ViewGroup): View {
execution.assertIsMainThread()
- if (!isEnabled()) {
+ if (!isSmartspaceEnabled()) {
throw RuntimeException("Cannot build view when not enabled")
}
@@ -182,7 +244,6 @@ class LockscreenSmartspaceController @Inject constructor(
userTracker.removeCallback(userTrackerCallback)
contentResolver.unregisterContentObserver(settingsObserver)
configurationController.removeCallback(configChangeListener)
- statusBarStateController.removeCallback(statusBarStateListener)
session = null
plugin?.onTargetsAvailable(emptyList())
@@ -198,6 +259,13 @@ class LockscreenSmartspaceController @Inject constructor(
plugin?.unregisterListener(listener)
}
+ fun shiftSplitShadeSmartspace(y: Int, animate: Boolean) {
+ if (splitShadeContainer?.visibility == VISIBLE) {
+ PropertyAnimator.setProperty(splitShadeContainer, AnimatableProperty.Y, y.toFloat(),
+ ANIMATION_PROPERTIES, animate)
+ }
+ }
+
private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
execution.assertIsMainThread()
val filteredTargets = targets.filter(::filterSmartspaceTarget)
@@ -233,6 +301,23 @@ class LockscreenSmartspaceController @Inject constructor(
execution.assertIsMainThread()
smartspaceView.setDozeAmount(eased)
}
+
+ override fun onDozingChanged(isDozing: Boolean) {
+ isAod = isDozing
+ updateSmartSpaceContainer()
+ }
+
+ override fun onStateChanged(newState: Int) {
+ if (newState == StatusBarState.KEYGUARD) {
+ if (isSmartspaceEnabled()) {
+ updateSmartSpaceContainer()
+ }
+ } else {
+ splitShadeContainer?.visibility = GONE
+ singlePaneContainer?.visibility = GONE
+ disconnect()
+ }
+ }
}
private fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
index 2537b19513d2..129fa5a7cc17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
@@ -20,6 +20,7 @@ import android.content.Intent;
import android.service.notification.StatusBarNotification;
import android.view.View;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
@@ -37,6 +38,9 @@ public interface NotificationActivityStarter {
/** Called when the user clicks "Manage" or "History" in the Shade. */
void startHistoryIntent(View view, boolean showHistory);
+ /** Called when the user succeed to drop notification to proper target view. */
+ void onDragSuccess(NotificationEntry entry);
+
default boolean isCollapsingToShowActivityOverLockscreen() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index 0fb1c54bb150..da706215863e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -43,6 +43,14 @@ public final class NotificationClicker implements View.OnClickListener {
private final Optional<Bubbles> mBubblesOptional;
private final NotificationActivityStarter mNotificationActivityStarter;
+ private ExpandableNotificationRow.OnDragSuccessListener mOnDragSuccessListener =
+ new ExpandableNotificationRow.OnDragSuccessListener() {
+ @Override
+ public void onDragSuccess(NotificationEntry entry) {
+ mNotificationActivityStarter.onDragSuccess(entry);
+ }
+ };
+
private NotificationClicker(
NotificationClickerLogger logger,
Optional<StatusBar> statusBarOptional,
@@ -111,8 +119,10 @@ public final class NotificationClicker implements View.OnClickListener {
if (notification.contentIntent != null || notification.fullScreenIntent != null
|| row.getEntry().isBubble()) {
row.setOnClickListener(this);
+ row.setOnDragSuccessListener(mOnDragSuccessListener);
} else {
row.setOnClickListener(null);
+ row.setOnDragSuccessListener(null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 7a71ee1d154e..acb0e82c24f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.MathUtils;
@@ -139,6 +140,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mIsHeadsUpAnimation;
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
+ /* In order to track headsup longpress coorindate. */
+ protected Point mTargetPoint;
private boolean mIsAppearing;
private boolean mDismissed;
private boolean mRefocusOnDismiss;
@@ -568,8 +571,19 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
final int actualHeight = getActualHeight();
float bottom = actualHeight * interpolatedFraction;
- setOutlineRect(0, mAppearAnimationTranslation, getWidth(),
- bottom + mAppearAnimationTranslation);
+ if (mTargetPoint != null) {
+ int width = getWidth();
+ float fraction = 1 - mAppearAnimationFraction;
+
+ setOutlineRect(mTargetPoint.x * fraction,
+ mAnimationTranslationY
+ + (mAnimationTranslationY - mTargetPoint.y) * fraction,
+ width - (width - mTargetPoint.x) * fraction,
+ actualHeight - (actualHeight - mTargetPoint.y) * fraction);
+ } else {
+ setOutlineRect(0, mAppearAnimationTranslation, getWidth(),
+ bottom + mAppearAnimationTranslation);
+ }
}
private float getInterpolatedAppearAnimationFraction() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 73bb6cd9ba1c..0d8e85094646 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -37,6 +37,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Path;
+import android.graphics.Point;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
@@ -260,6 +261,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
// Use #setLongPressPosition to optionally assign positional data with the long press.
private LongPressListener mLongPressListener;
+ private ExpandableNotificationRowDragController mDragController;
+
private boolean mGroupExpansionChanging;
/**
@@ -331,6 +334,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
};
private OnClickListener mOnClickListener;
+ private OnDragSuccessListener mOnDragSuccessListener;
private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
@@ -1083,6 +1087,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mLongPressListener = longPressListener;
}
+ public void setDragController(ExpandableNotificationRowDragController dragController) {
+ mDragController = dragController;
+ }
+
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
super.setOnClickListener(l);
@@ -1329,6 +1337,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void dismiss(boolean refocusOnDismiss) {
super.dismiss(refocusOnDismiss);
setLongPressListener(null);
+ setDragController(null);
mGroupParentWhenDismissed = mNotificationParent;
mChildAfterViewWhenDismissed = null;
mEntry.getIcons().getStatusBarIcon().setDismissed();
@@ -1637,6 +1646,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
onHeightReset();
requestLayout();
+
+ setTargetPoint(null);
}
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
@@ -1727,6 +1738,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mTranslateableViews.remove(mGutsStub);
}
+ /**
+ * Called once when starting drag motion after opening notification guts,
+ * in case of notification that has {@link android.app.Notification#contentIntent}
+ * and it is to start an activity.
+ */
+ public void doDragCallback(float x, float y) {
+ if (mDragController != null) {
+ setTargetPoint(new Point((int) x, (int) y));
+ mDragController.startDragAndDrop(this);
+ }
+ }
+
+ public void setOnDragSuccessListener(OnDragSuccessListener listener) {
+ mOnDragSuccessListener = listener;
+ }
+
+ /**
+ * Called when a notification is dropped on proper target window.
+ */
+ public void dragAndDropSuccess() {
+ mOnDragSuccessListener.onDragSuccess(getEntry());
+ }
+
private void doLongClickCallback() {
doLongClickCallback(getWidth() / 2, getHeight() / 2);
}
@@ -3255,6 +3289,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
/**
+ * Called when notification drag and drop is finished successfully.
+ */
+ public interface OnDragSuccessListener {
+ /**
+ * @param entry NotificationEntry that succeed to drop on proper target window.
+ */
+ void onDragSuccess(NotificationEntry entry);
+ }
+
+ /**
* Equivalent to View.OnClickListener with coordinates
*/
public interface CoordinateOnClickListener {
@@ -3321,4 +3365,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
}
+
+ private void setTargetPoint(Point p) {
+ mTargetPoint = p;
+ }
+ public Point getTargetPoint() {
+ return mTargetPoint;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index c9fcdac8e45f..0662a1eba8b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -25,6 +25,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
+import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -85,6 +86,8 @@ public class ExpandableNotificationRowController implements NodeController {
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
private final Optional<BubblesManager> mBubblesManagerOptional;
+ private final ExpandableNotificationRowDragController mDragController;
+
@Inject
public ExpandableNotificationRowController(
ExpandableNotificationRow view,
@@ -109,7 +112,8 @@ public class ExpandableNotificationRowController implements NodeController {
FalsingManager falsingManager,
FalsingCollector falsingCollector,
PeopleNotificationIdentifier peopleNotificationIdentifier,
- Optional<BubblesManager> bubblesManagerOptional) {
+ Optional<BubblesManager> bubblesManagerOptional,
+ ExpandableNotificationRowDragController dragController) {
mView = view;
mListContainer = listContainer;
mActivatableNotificationViewController = activatableNotificationViewController;
@@ -134,6 +138,7 @@ public class ExpandableNotificationRowController implements NodeController {
mFalsingCollector = falsingCollector;
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
mBubblesManagerOptional = bubblesManagerOptional;
+ mDragController = dragController;
}
/**
@@ -164,6 +169,10 @@ public class ExpandableNotificationRowController implements NodeController {
);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
+ if (mView.getResources().getBoolean(R.bool.config_notificationToContents)) {
+ mView.setDragController(mDragController);
+ }
+
mView.setLongPressListener((v, x, y, item) -> {
if (mView.isSummaryWithChildren()) {
mView.expandNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
new file mode 100644
index 000000000000..06b739b33e77
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import android.view.DragEvent;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for Notification to window.
+ */
+public class ExpandableNotificationRowDragController {
+ private static final String TAG = ExpandableNotificationRowDragController.class.getSimpleName();
+ private int mIconSize;
+
+ private final Context mContext;
+ private final HeadsUpManager mHeadsUpManager;
+
+ @Inject
+ public ExpandableNotificationRowDragController(Context context,
+ HeadsUpManager headsUpManager) {
+ mContext = context;
+ mHeadsUpManager = headsUpManager;
+
+ init();
+ }
+
+ private void init() {
+ mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.drag_and_drop_icon_size);
+ }
+
+ /**
+ * Called when drag event beyond the touchslop,
+ * and start drag and drop.
+ *
+ * @param view notification that was long pressed and started to drag and drop.
+ */
+ @VisibleForTesting
+ public void startDragAndDrop(View view) {
+ ExpandableNotificationRow enr = null;
+ if (view instanceof ExpandableNotificationRow) {
+ enr = (ExpandableNotificationRow) view;
+ }
+
+ StatusBarNotification sn = enr.getEntry().getSbn();
+ Notification notification = sn.getNotification();
+ final PendingIntent contentIntent = notification.contentIntent != null
+ ? notification.contentIntent
+ : notification.fullScreenIntent;
+ Bitmap iconBitmap = getBitmapFromDrawable(
+ getPkgIcon(enr.getEntry().getSbn().getPackageName()));
+
+ final ImageView snapshot = new ImageView(mContext);
+ snapshot.setImageBitmap(iconBitmap);
+ snapshot.layout(0, 0, mIconSize, mIconSize);
+
+ ClipDescription clipDescription = new ClipDescription("Drag And Drop",
+ new String[]{ClipDescription.MIMETYPE_APPLICATION_ACTIVITY});
+ Intent dragIntent = new Intent();
+ dragIntent.putExtra("android.intent.extra.PENDING_INTENT", contentIntent);
+ dragIntent.putExtra(Intent.EXTRA_USER, android.os.Process.myUserHandle());
+ ClipData.Item item = new ClipData.Item(dragIntent);
+ ClipData dragData = new ClipData(clipDescription, item);
+ View.DragShadowBuilder myShadow = new View.DragShadowBuilder(snapshot);
+ view.setOnDragListener(getDraggedViewDragListener());
+ view.startDragAndDrop(dragData, myShadow, null, View.DRAG_FLAG_GLOBAL);
+ }
+
+
+ private Drawable getPkgIcon(String pkgName) {
+ Drawable pkgicon = null;
+ PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo info;
+ try {
+ info = pm.getApplicationInfo(
+ pkgName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (info != null) {
+ pkgicon = pm.getApplicationIcon(info);
+ } else {
+ Log.d(TAG, " application info is null ");
+ pkgicon = pm.getDefaultActivityIcon();
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.d(TAG, "can not find package with : " + pkgName);
+ pkgicon = pm.getDefaultActivityIcon();
+ }
+
+ return pkgicon;
+ }
+
+ private Bitmap getBitmapFromDrawable(@NonNull Drawable drawable) {
+ final Bitmap bmp = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(bmp);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bmp;
+ }
+
+ private View.OnDragListener getDraggedViewDragListener() {
+ return (view, dragEvent) -> {
+ switch (dragEvent.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ if (view instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow enr = (ExpandableNotificationRow) view;
+ if (enr.isPinned()) {
+ mHeadsUpManager.releaseAllImmediately();
+ } else {
+ Dependency.get(ShadeController.class).animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ }
+ }
+ return true;
+ case DragEvent.ACTION_DRAG_ENDED:
+ if (dragEvent.getResult()) {
+ if (view instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow enr = (ExpandableNotificationRow) view;
+ enr.dragAndDropSuccess();
+ }
+ }
+ return true;
+ }
+ return false;
+ };
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index a865c3a5e3f8..04129b52b4ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -183,6 +183,8 @@ public class NotificationStackScrollLayoutController {
private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
+ private View mLongPressedView;
+
private final NotificationListContainerImpl mNotificationListContainer =
new NotificationListContainerImpl();
@@ -492,6 +494,11 @@ public class NotificationStackScrollLayoutController {
}
@Override
+ public void onLongPressSent(View v) {
+ mLongPressedView = v;
+ }
+
+ @Override
public void onBeginDrag(View v) {
mFalsingCollector.onNotificationStartDismissing();
mView.onSwipeBegin(v);
@@ -1435,6 +1442,10 @@ public class NotificationStackScrollLayoutController {
return mDynamicPrivacyController.isInLockedDownShade();
}
+ public boolean isLongPressInProgress() {
+ return mLongPressedView != null;
+ }
+
/**
* Set the dimmed state for all of the notification views.
*/
@@ -1689,17 +1700,23 @@ public class NotificationStackScrollLayoutController {
mView.handleEmptySpaceClick(ev);
NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
+
+ boolean longPressWantsIt = false;
+ if (mLongPressedView != null) {
+ longPressWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
+ }
boolean expandWantsIt = false;
- if (!mSwipeHelper.isSwiping()
+ if (mLongPressedView == null && !mSwipeHelper.isSwiping()
&& !mView.getOnlyScrollingInThisMotion() && guts == null) {
expandWantsIt = mView.getExpandHelper().onInterceptTouchEvent(ev);
}
boolean scrollWantsIt = false;
- if (!mSwipeHelper.isSwiping() && !mView.isExpandingNotification()) {
+ if (mLongPressedView == null && !mSwipeHelper.isSwiping()
+ && !mView.isExpandingNotification()) {
scrollWantsIt = mView.onInterceptTouchEventScroll(ev);
}
boolean swipeWantsIt = false;
- if (!mView.isBeingDragged()
+ if (mLongPressedView == null && !mView.isBeingDragged()
&& !mView.isExpandingNotification()
&& !mView.getExpandedInThisMotion()
&& !mView.getOnlyScrollingInThisMotion()
@@ -1727,7 +1744,7 @@ public class NotificationStackScrollLayoutController {
InteractionJankMonitor.getInstance().begin(mView,
CUJ_NOTIFICATION_SHADE_SCROLL_FLING);
}
- return swipeWantsIt || scrollWantsIt || expandWantsIt;
+ return swipeWantsIt || scrollWantsIt || expandWantsIt || longPressWantsIt;
}
@Override
@@ -1736,11 +1753,15 @@ public class NotificationStackScrollLayoutController {
boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
|| ev.getActionMasked() == MotionEvent.ACTION_UP;
mView.handleEmptySpaceClick(ev);
+ boolean longPressWantsIt = false;
+ if (guts != null && mLongPressedView != null) {
+ longPressWantsIt = mSwipeHelper.onTouchEvent(ev);
+ }
boolean expandWantsIt = false;
boolean onlyScrollingInThisMotion = mView.getOnlyScrollingInThisMotion();
boolean expandingNotification = mView.isExpandingNotification();
- if (mView.getIsExpanded() && !mSwipeHelper.isSwiping() && !onlyScrollingInThisMotion
- && guts == null) {
+ if (mLongPressedView == null && mView.getIsExpanded()
+ && !mSwipeHelper.isSwiping() && !onlyScrollingInThisMotion && guts == null) {
ExpandHelper expandHelper = mView.getExpandHelper();
if (isCancelOrUp) {
expandHelper.onlyObserveMovements(false);
@@ -1754,12 +1775,12 @@ public class NotificationStackScrollLayoutController {
}
}
boolean scrollerWantsIt = false;
- if (mView.isExpanded() && !mSwipeHelper.isSwiping() && !expandingNotification
- && !mView.getDisallowScrollingInThisMotion()) {
+ if (mLongPressedView == null && mView.isExpanded() && !mSwipeHelper.isSwiping()
+ && !expandingNotification && !mView.getDisallowScrollingInThisMotion()) {
scrollerWantsIt = mView.onScrollTouch(ev);
}
boolean horizontalSwipeWantsIt = false;
- if (!mView.isBeingDragged()
+ if (mLongPressedView == null && !mView.isBeingDragged()
&& !expandingNotification
&& !mView.getExpandedInThisMotion()
&& !onlyScrollingInThisMotion
@@ -1785,7 +1806,7 @@ public class NotificationStackScrollLayoutController {
mView.setCheckForLeaveBehind(true);
}
traceJankOnTouchEvent(ev.getActionMasked(), scrollerWantsIt);
- return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt;
+ return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || longPressWantsIt;
}
private void traceJankOnTouchEvent(int action, boolean scrollerWantsIt) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index ee12b4b2d728..2702bf7d31da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -433,6 +433,7 @@ public class StackStateAnimator {
if (row.isDismissed()) {
needsAnimation = false;
}
+
NotificationEntry entry = row.getEntry();
StatusBarIconView icon = entry.getIcons().getStatusBarIcon();
final StatusBarIconView centeredIcon = entry.getIcons().getCenteredIcon();
@@ -442,7 +443,8 @@ public class StackStateAnimator {
if (icon.getParent() != null) {
icon.getLocationOnScreen(mTmpLocation);
float iconPosition = mTmpLocation[0] - icon.getTranslationX()
- + ViewState.getFinalTranslationX(icon) + icon.getWidth() * 0.25f;
+ + ViewState.getFinalTranslationX(icon)
+ + icon.getWidth() * 0.25f;
mHostLayout.getLocationOnScreen(mTmpLocation);
targetLocation = iconPosition - mTmpLocation[0];
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index a0af389302e5..7908d84bcd70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -231,7 +231,9 @@ public class DozeParameters implements TunerService.Tunable,
* possible if AOD isn't even enabled or if the flag is disabled.
*/
public boolean canControlUnlockedScreenOff() {
- return getAlwaysOn() && mFeatureFlags.useNewLockscreenAnimations();
+ return getAlwaysOn()
+ && mFeatureFlags.useNewLockscreenAnimations()
+ && !getDisplayNeedsBlanking();
}
private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index f4830fbb0028..878fbbf39627 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -18,9 +18,7 @@ package com.android.systemui.statusbar.phone;
import android.graphics.Point;
import android.graphics.Rect;
-import android.view.DisplayCutout;
import android.view.View;
-import android.view.WindowInsets;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
@@ -61,7 +59,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
private final NotificationPanelViewController mNotificationPanelViewController;
private final Consumer<ExpandableNotificationRow>
mSetTrackingHeadsUp = this::setTrackingHeadsUp;
- private final Runnable mUpdatePanelTranslation = this::updatePanelTranslation;
private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction;
private final KeyguardBypassController mBypassController;
private final StatusBarStateController mStatusBarStateController;
@@ -75,9 +72,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
float mAppearFraction;
private ExpandableNotificationRow mTrackedChild;
private boolean mShown;
- private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
- -> updatePanelTranslation();
private final ViewClippingUtil.ClippingParameters mParentClippingParams =
new ViewClippingUtil.ClippingParameters() {
@Override
@@ -134,10 +128,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mStackScrollerController = stackScrollerController;
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
- notificationPanelViewController.setVerticalTranslationListener(mUpdatePanelTranslation);
notificationPanelViewController.setHeadsUpAppearanceController(this);
mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
- mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mStackScrollerController.setHeadsUpAppearanceController(this);
mClockView = clockView;
mOperatorNameView = operatorNameView;
@@ -174,7 +166,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mNotificationPanelViewController.setVerticalTranslationListener(null);
mNotificationPanelViewController.setHeadsUpAppearanceController(null);
mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
- mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mDarkIconDispatcher.removeDarkReceiver(this);
}
@@ -189,63 +180,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
updateHeader(entry);
}
- /** To count the distance from the window right boundary to scroller right boundary. The
- * distance formula is the following:
- * Y = screenSize - (SystemWindow's width + Scroller.getRight())
- * There are four modes MUST to be considered in Cut Out of RTL.
- * No Cut Out:
- * Scroller + NB
- * NB + Scroller
- * => SystemWindow = NavigationBar's width
- * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
- * Corner Cut Out or Tall Cut Out:
- * cut out + Scroller + NB
- * NB + Scroller + cut out
- * => SystemWindow = NavigationBar's width
- * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
- * Double Cut Out:
- * cut out left + Scroller + (NB + cut out right)
- * SystemWindow = NavigationBar's width + cut out right width
- * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
- * (cut out left + NB) + Scroller + cut out right
- * SystemWindow = NavigationBar's width + cut out left width
- * => Y = screenSize - (SystemWindow's width + Scroller.getRight())
- * @return the translation X value for RTL. In theory, it should be negative. i.e. -Y
- */
- private int getRtlTranslation() {
- if (mPoint == null) {
- mPoint = new Point();
- }
-
- int realDisplaySize = 0;
- if (mStackScrollerController.getDisplay() != null) {
- mStackScrollerController.getDisplay().getRealSize(mPoint);
- realDisplaySize = mPoint.x;
- }
-
- WindowInsets windowInset = mStackScrollerController.getRootWindowInsets();
- DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null;
- int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0;
- int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0;
- int cutoutLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0;
- int cutoutRight = (cutout != null) ? cutout.getSafeInsetRight() : 0;
- int leftInset = Math.max(sysWinLeft, cutoutLeft);
- int rightInset = Math.max(sysWinRight, cutoutRight);
-
- return leftInset + mStackScrollerController.getRight() + rightInset - realDisplaySize;
- }
-
- public void updatePanelTranslation() {
- float newTranslation;
- if (mStackScrollerController.isLayoutRtl()) {
- newTranslation = getRtlTranslation();
- } else {
- newTranslation = mStackScrollerController.getLeft();
- }
- newTranslation += mStackScrollerController.getTranslationX();
- mHeadsUpStatusBarView.setPanelTranslation(newTranslation);
- }
-
private void updateTopEntry() {
NotificationEntry newEntry = null;
if (shouldBeVisible()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index f77c0520cdb1..19c258558a7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -33,23 +33,11 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
*/
public class KeyguardClockPositionAlgorithm {
/**
- * How much the clock height influences the shade position.
- * 0 means nothing, 1 means move the shade up by the height of the clock
- * 0.5f means move the shade up by half of the size of the clock.
- */
- private static float CLOCK_HEIGHT_WEIGHT = 0.7f;
-
- /**
* Margin between the bottom of the status view and the notification shade.
*/
private int mStatusViewBottomMargin;
/**
- * Height of the parent view - display size in px.
- */
- private int mHeight;
-
- /**
* Height of {@link KeyguardStatusView}.
*/
private int mKeyguardStatusHeight;
@@ -68,21 +56,6 @@ public class KeyguardClockPositionAlgorithm {
private int mUserSwitchPreferredY;
/**
- * Whether or not there is a custom clock face on keyguard.
- */
- private boolean mHasCustomClock;
-
- /**
- * Whether or not the NSSL contains any visible notifications.
- */
- private boolean mHasVisibleNotifs;
-
- /**
- * Height of notification stack: Sum of height of each notification.
- */
- private int mNotificationStackHeight;
-
- /**
* Minimum top margin to avoid overlap with status bar, lock icon, or multi-user switcher
* avatar.
*/
@@ -148,6 +121,7 @@ public class KeyguardClockPositionAlgorithm {
private int mUnlockedStackScrollerPadding;
private boolean mIsSplitShade;
+ private int mSplitShadeSmartspaceHeight;
/**
* Refreshes the dimension values.
@@ -170,28 +144,25 @@ public class KeyguardClockPositionAlgorithm {
* Sets up algorithm values.
*/
public void setup(int keyguardStatusBarHeaderHeight, int maxShadeBottom,
- int notificationStackHeight, float panelExpansion, int parentHeight,
- int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY,
- boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
+ float panelExpansion,
+ int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY, float dark,
float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
- float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
+ float qsExpansion, int cutoutTopInset, int splitShadeSmartspaceHeight,
+ boolean isSplitShade) {
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
userSwitchHeight);
mMaxShadeBottom = maxShadeBottom;
- mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
- mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight + mStatusViewBottomMargin;
mUserSwitchHeight = userSwitchHeight;
mUserSwitchPreferredY = userSwitchPreferredY;
- mHasCustomClock = hasCustomClock;
- mHasVisibleNotifs = hasVisibleNotifs;
mDarkAmount = dark;
mOverStretchAmount = overStrechAmount;
mBypassEnabled = bypassEnabled;
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
mQsExpansion = qsExpansion;
mCutoutTopInset = cutoutTopInset;
+ mSplitShadeSmartspaceHeight = splitShadeSmartspaceHeight;
mIsSplitShade = isSplitShade;
}
@@ -213,7 +184,7 @@ public class KeyguardClockPositionAlgorithm {
if (mBypassEnabled) {
return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
} else if (mIsSplitShade) {
- return clockYPosition;
+ return clockYPosition + mSplitShadeSmartspaceHeight;
} else {
return clockYPosition + mKeyguardStatusHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index bfadc3f7582a..8770e86df735 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -159,10 +159,16 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
@Override
protected void onViewDetached() {
+ destroy();
+ }
+
+ @Override
+ public void destroy() {
// Don't receive future #onViewAttached calls so that we don't accidentally have two
// controllers registered for the same view.
// TODO(b/194181195): This shouldn't be necessary.
- destroy();
+ super.destroy();
+ mBatteryMeterViewController.destroy();
mConfigurationController.removeCallback(mConfigurationListener);
mAnimationScheduler.removeCallback(mAnimationCallback);
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 3e39b46ffeae..50db24000157 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -147,6 +147,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.ConversationNotificationManager;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -239,6 +240,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final HeightListener mHeightListener = new HeightListener();
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
private final SettingsChangeObserver mSettingsChangeObserver;
+ private final LockscreenSmartspaceController mLockscreenSmartspaceController;
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
new StatusBarStateListener();
@@ -372,6 +374,8 @@ public class NotificationPanelViewController extends PanelViewController {
private IdleHostViewController mIdleHostViewController;
private LockIconViewController mLockIconViewController;
private NotificationsQuickSettingsContainer mNotificationContainerParent;
+ private FrameLayout mSplitShadeSmartspaceContainer;
+
private boolean mAnimateNextPositionUpdate;
private float mQuickQsOffsetHeight;
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -776,6 +780,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Main Executor uiExecutor,
SecureSettings secureSettings,
SplitShadeHeaderController splitShadeHeaderController,
+ LockscreenSmartspaceController lockscreenSmartspaceController,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
NotificationRemoteInputManager remoteInputManager,
ControlsComponent controlsComponent) {
@@ -809,6 +814,7 @@ public class NotificationPanelViewController extends PanelViewController {
mQSDetailDisplayer = qsDetailDisplayer;
mFragmentService = fragmentService;
mSettingsChangeObserver = new SettingsChangeObserver(handler);
+ mLockscreenSmartspaceController = lockscreenSmartspaceController;
mShouldUseSplitNotificationShade =
Utils.shouldUseSplitNotificationShade(mResources);
mView.setWillNotDraw(!DEBUG);
@@ -905,6 +911,9 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
mBigClockContainer = mView.findViewById(R.id.big_clock_container);
mCommunalView = mView.findViewById(R.id.communal_host);
+ mSplitShadeSmartspaceContainer = mView.findViewById(R.id.split_shade_smartspace_container);
+ mLockscreenSmartspaceController.setSplitShadeContainer(mSplitShadeSmartspaceContainer);
+ mLockscreenSmartspaceController.onSplitShadeChanged(mShouldUseSplitNotificationShade);
UserAvatarView userAvatarView = null;
KeyguardUserSwitcherView keyguardUserSwitcherView = null;
@@ -1034,7 +1043,7 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardStatusBarViewComponentFactory.build(keyguardStatusBarView);
if (mKeyguardStatusBarViewController != null) {
// TODO(b/194181195): This shouldn't be necessary.
- mKeyguardStatusBarViewController.onViewDetached();
+ mKeyguardStatusBarViewController.destroy();
}
mKeyguardStatusBarViewController =
statusBarViewComponent.getKeyguardStatusBarViewController();
@@ -1134,7 +1143,7 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationContainerParent.setSplitShadeEnabled(mShouldUseSplitNotificationShade);
updateKeyguardStatusViewAlignment(false /* animate */);
-
+ mLockscreenSmartspaceController.onSplitShadeChanged(mShouldUseSplitNotificationShade);
mKeyguardMediaController.refreshMediaPosition();
}
@@ -1398,16 +1407,15 @@ public class NotificationPanelViewController extends PanelViewController {
? 1.0f : mInterpolatedDarkAmount;
mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
totalHeight - bottomPadding,
- mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
expandedFraction,
- totalHeight,
mKeyguardStatusViewController.getLockscreenHeight(),
userIconHeight,
- userSwitcherPreferredY, hasCustomClock(),
- hasVisibleNotifications, darkamount, mOverStretchAmount,
+ userSwitcherPreferredY,
+ darkamount, mOverStretchAmount,
bypassEnabled, getUnlockedStackScrollerPadding(),
computeQsExpansionFraction(),
mDisplayTopInset,
+ mSplitShadeSmartspaceContainer.getHeight(),
mShouldUseSplitNotificationShade);
mClockPositionAlgorithm.run(mClockPositionResult);
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
@@ -1427,6 +1435,9 @@ public class NotificationPanelViewController extends PanelViewController {
mClockPositionResult.userSwitchY,
animateClock);
}
+ // no need to translate in X axis - horizontal position is determined by constraints
+ mLockscreenSmartspaceController
+ .shiftSplitShadeSmartspace(mClockPositionResult.clockY, animateClock);
updateNotificationTranslucency();
updateClock();
}
@@ -1602,6 +1613,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (mKeyguardUserSwitcherController != null) {
mKeyguardUserSwitcherController.setAlpha(alpha);
}
+ mLockscreenSmartspaceController.setSplitShadeSmartspaceAlpha(alpha);
}
public void animateToFullShade(long delay) {
@@ -3783,6 +3795,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void dozeTimeTick() {
mKeyguardBottomArea.dozeTimeTick();
mKeyguardStatusViewController.dozeTimeTick();
+ mLockscreenSmartspaceController.requestSmartspaceUpdate();
if (mInterpolatedDarkAmount > 0) {
positionClockAndNotifications();
}
@@ -4005,7 +4018,9 @@ public class NotificationPanelViewController extends PanelViewController {
if (mStatusBar.isBouncerShowing()) {
return true;
}
- if (mBar.panelEnabled() && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
+ if (mBar.panelEnabled()
+ && !mNotificationStackScrollLayoutController.isLongPressInProgress()
+ && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1);
return true;
@@ -4057,6 +4072,7 @@ public class NotificationPanelViewController extends PanelViewController {
return true;
}
if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
+ && !mNotificationStackScrollLayoutController.isLongPressInProgress()
&& mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index d2a4a00c03bf..c52a094d4b57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -84,8 +84,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private final WindowManager mWindowManager;
private final IActivityManager mActivityManager;
private final DozeParameters mDozeParameters;
+ private final KeyguardStateController mKeyguardStateController;
private final LayoutParams mLpChanged;
- private final boolean mKeyguardScreenRotation;
private final long mLockScreenDisplayTimeout;
private final float mKeyguardPreferredRefreshRate; // takes precedence over max
private final float mKeyguardMaxRefreshRate;
@@ -123,8 +123,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
- mKeyguardScreenRotation = keyguardStateController.isKeyguardScreenRotationAllowed();
mDozeParameters = dozeParameters;
+ mKeyguardStateController = keyguardStateController;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new LayoutParams();
mKeyguardViewMediator = keyguardViewMediator;
@@ -323,7 +323,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private void adjustScreenOrientation(State state) {
if (state.isKeyguardShowingAndNotOccluded() || state.mDozing) {
- if (mKeyguardScreenRotation) {
+ if (mKeyguardStateController.isKeyguardScreenRotationAllowed()) {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
} else {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index c300b11b9a34..70a46b25c1eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -27,6 +27,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.EventLog;
+import android.util.Log;
import android.util.Pair;
import android.view.DisplayCutout;
import android.view.Gravity;
@@ -42,7 +43,6 @@ import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.leak.RotationUtils;
import java.util.List;
@@ -52,7 +52,6 @@ public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
private static final boolean DEBUG = StatusBar.DEBUG;
private static final boolean DEBUG_GESTURES = false;
- private final CommandQueue mCommandQueue;
private final StatusBarContentInsetsProvider mContentInsetsProvider;
StatusBar mBar;
@@ -81,6 +80,8 @@ public class PhoneStatusBarView extends PanelBar {
@Nullable
private List<StatusBar.ExpansionChangedListener> mExpansionChangedListeners;
+ private PanelEnabledProvider mPanelEnabledProvider;
+
/**
* Draw this many pixels into the left/right side of the cutout to optimally use the space
*/
@@ -89,7 +90,6 @@ public class PhoneStatusBarView extends PanelBar {
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
- mCommandQueue = Dependency.get(CommandQueue.class);
mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
}
@@ -177,7 +177,11 @@ public class PhoneStatusBarView extends PanelBar {
@Override
public boolean panelEnabled() {
- return mCommandQueue.panelsEnabled();
+ if (mPanelEnabledProvider == null) {
+ Log.e(TAG, "panelEnabledProvider is null; defaulting to super class.");
+ return super.panelEnabled();
+ }
+ return mPanelEnabledProvider.panelEnabled();
}
@Override
@@ -294,6 +298,11 @@ public class PhoneStatusBarView extends PanelBar {
}
}
+ /** Set the {@link PanelEnabledProvider} to use. */
+ public void setPanelEnabledProvider(PanelEnabledProvider panelEnabledProvider) {
+ mPanelEnabledProvider = panelEnabledProvider;
+ }
+
private void updateScrimFraction() {
float scrimFraction = mPanelFraction;
if (mMinFraction < 1.0f) {
@@ -391,4 +400,10 @@ public class PhoneStatusBarView extends PanelBar {
protected boolean shouldPanelBeVisible() {
return mHeadsUpVisible || super.shouldPanelBeVisible();
}
+
+ /** An interface that will provide whether panel is enabled. */
+ interface PanelEnabledProvider {
+ /** Returns true if the panel is enabled and false otherwise. */
+ boolean panelEnabled();
+ }
}
diff --git a/services/uwb/java/com/android/server/uwb/UwbService.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java
index 4bb280f75ed1..b36b67dc02c0 100644
--- a/services/uwb/java/com/android/server/uwb/UwbService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java
@@ -14,29 +14,26 @@
* limitations under the License.
*/
-package com.android.server.uwb;
+package com.android.systemui.statusbar.phone;
-import android.content.Context;
-import android.util.Log;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.util.ViewController;
-import com.android.server.SystemService;
+/** Controller for {@link PhoneStatusBarView}. */
+public class PhoneStatusBarViewController extends ViewController<PhoneStatusBarView> {
-/**
- * Uwb System service.
- */
-public class UwbService extends SystemService {
- private static final String TAG = "UwbService";
-
- private final UwbServiceImpl mImpl;
+ protected PhoneStatusBarViewController(
+ PhoneStatusBarView view,
+ CommandQueue commandQueue) {
+ super(view);
+ mView.setPanelEnabledProvider(commandQueue::panelsEnabled);
+ }
- public UwbService(Context context) {
- super(context);
- mImpl = new UwbServiceImpl(context, new UwbInjector(context));
+ @Override
+ protected void onViewAttached() {
}
@Override
- public void onStart() {
- Log.i(TAG, "Registering " + Context.UWB_SERVICE);
- publishBinderService(Context.UWB_SERVICE, mImpl);
+ protected void onViewDetached() {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index 0a5fa1eb8236..4b7fe4e7ea29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -20,8 +20,8 @@ import android.view.View
import com.android.systemui.R
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.qs.carrier.QSCarrierGroupController
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.qs.carrier.QSCarrierGroupController
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER
import javax.inject.Inject
@@ -54,11 +54,12 @@ class SplitShadeHeaderController @Inject constructor(
}
init {
+ batteryMeterViewController.init()
val batteryIcon: BatteryMeterView = statusBar.findViewById(R.id.batteryRemainingIcon)
+
// battery settings same as in QS icons
- batteryIcon.setIgnoreTunerUpdates(true)
+ batteryMeterViewController.ignoreTunerUpdates()
batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
- batteryMeterViewController.init()
val iconContainer: StatusIconContainer = statusBar.findViewById(R.id.statusIcons)
iconManager = StatusBarIconController.IconManager(iconContainer, featureFlags)
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 5218dfec4c80..82358a6ca2fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -224,6 +224,7 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.unfold.config.UnfoldTransitionConfig;
@@ -462,6 +463,7 @@ public class StatusBar extends SystemUI implements
protected NotificationShadeWindowView mNotificationShadeWindowView;
protected StatusBarWindowView mPhoneStatusBarWindow;
protected PhoneStatusBarView mStatusBarView;
+ private PhoneStatusBarViewController mPhoneStatusBarViewController;
private AuthRippleController mAuthRippleController;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected NotificationShadeWindowController mNotificationShadeWindowController;
@@ -539,6 +541,7 @@ public class StatusBar extends SystemUI implements
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final WallpaperManager mWallpaperManager;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ private final TunerService mTunerService;
private final List<ExpansionChangedListener> mExpansionChangedListeners;
@@ -872,7 +875,8 @@ public class StatusBar extends SystemUI implements
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
WallpaperManager wallpaperManager,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
- Optional<StartingSurface> startingSurfaceOptional) {
+ Optional<StartingSurface> startingSurfaceOptional,
+ TunerService tunerService) {
super(context);
mNotificationsController = notificationsController;
mLightBarController = lightBarController;
@@ -955,6 +959,7 @@ public class StatusBar extends SystemUI implements
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mWallpaperManager = wallpaperManager;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mTunerService = tunerService;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
@@ -1206,9 +1211,17 @@ public class StatusBar extends SystemUI implements
mStatusBarView.setPanel(mNotificationPanelViewController);
mStatusBarView.setScrimController(mScrimController);
mStatusBarView.setExpansionChangedListeners(mExpansionChangedListeners);
+ mPhoneStatusBarViewController =
+ new PhoneStatusBarViewController(mStatusBarView, mCommandQueue);
+ mPhoneStatusBarViewController.init();
mBatteryMeterViewController = new BatteryMeterViewController(
- mStatusBarView.findViewById(R.id.battery)
+ mStatusBarView.findViewById(R.id.battery),
+ mConfigurationController,
+ mTunerService,
+ mBroadcastDispatcher,
+ mMainThreadHandler,
+ mContext.getContentResolver()
);
mBatteryMeterViewController.init();
@@ -1365,7 +1378,7 @@ public class StatusBar extends SystemUI implements
QS qs = (QS) f;
if (qs instanceof QSFragment) {
mQSPanelController = ((QSFragment) qs).getQSPanelController();
- mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
+ ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 8873fbf111ba..dba3b2418790 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -71,6 +71,7 @@ import com.android.systemui.statusbar.notification.collection.render.GroupMember
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowDragController;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -402,6 +403,53 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mIsCollapsingToShowActivityOverLockscreen = false;
}
+ /**
+ * Called when a notification is dropped on proper target window.
+ * Intent that is included in this entry notification,
+ * will be sent by {@link ExpandableNotificationRowDragController}
+ *
+ * @param entry notification entry that is dropped.
+ */
+ @Override
+ public void onDragSuccess(NotificationEntry entry) {
+ // this method is not responsible for intent sending.
+ // will focus follow operation only after drag-and-drop that notification.
+ NotificationVisibility.NotificationLocation location =
+ NotificationLogger.getNotificationLocation(entry);
+ final NotificationVisibility nv = NotificationVisibility.obtain(entry.getKey(),
+ entry.getRanking().getRank(), getVisibleNotificationsCount(), true, location);
+
+ // retrieve the group summary to remove with this entry before we tell NMS the
+ // notification was clicked to avoid a race condition
+ final boolean shouldAutoCancel = shouldAutoCancel(entry.getSbn());
+ final NotificationEntry summaryToRemove = shouldAutoCancel
+ ? mOnUserInteractionCallback.getGroupSummaryToDismiss(entry) : null;
+
+ String notificationKey = entry.getKey();
+ // inform NMS that the notification was clicked
+ mClickNotifier.onNotificationClick(notificationKey, nv);
+
+ if (shouldAutoCancel || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
+ notificationKey)) {
+ // Immediately remove notification from visually showing.
+ // We have to post the removal to the UI thread for synchronization.
+ mMainThreadHandler.post(() -> {
+ final Runnable removeNotification = () ->
+ mOnUserInteractionCallback.onDismiss(
+ entry, REASON_CLICK, summaryToRemove);
+ if (mPresenter.isCollapsing()) {
+ // To avoid lags we're only performing the remove
+ // after the shade is collapsed
+ mShadeController.addPostCollapseAction(removeNotification);
+ } else {
+ removeNotification.run();
+ }
+ });
+ }
+
+ mIsCollapsingToShowActivityOverLockscreen = false;
+ }
+
private void expandBubbleStackOnMainThread(NotificationEntry entry) {
if (!mBubblesManagerOptional.isPresent()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index a5b868b6f8a3..6b52dca42eda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -149,14 +149,18 @@ class UnlockedScreenOffAnimationController @Inject constructor(
lightRevealAnimationPlaying = false
aodUiAnimationPlaying = false
- // Make sure the status bar is in the correct keyguard state, forcing it if necessary. This
- // is required if the screen off animation is cancelled, since it might be incorrectly left
- // in the KEYGUARD or SHADE states depending on when it was cancelled and whether 'lock
- // instantly' is enabled. We need to force it so that the state is set even if we're going
- // from SHADE to SHADE or KEYGUARD to KEYGUARD, since we might have changed parts of the UI
- // (such as showing AOD in the shade) without actually changing the StatusBarState. This
- // ensures that the UI definitely reflects the desired state.
- statusBar.updateIsKeyguard(true /* force */)
+ // If we can't control the screen off animation, we shouldn't mess with the StatusBar's
+ // keyguard state unnecessarily.
+ if (dozeParameters.get().canControlUnlockedScreenOff()) {
+ // Make sure the status bar is in the correct keyguard state, forcing it if necessary.
+ // This is required if the screen off animation is cancelled, since it might be
+ // incorrectly left in the KEYGUARD or SHADE states depending on when it was cancelled
+ // and whether 'lock instantly' is enabled. We need to force it so that the state is set
+ // even if we're going from SHADE to SHADE or KEYGUARD to KEYGUARD, since we might have
+ // changed parts of the UI (such as showing AOD in the shade) without actually changing
+ // the StatusBarState. This ensures that the UI definitely reflects the desired state.
+ statusBar.updateIsKeyguard(true /* force */)
+ }
}
override fun onStartedGoingToSleep() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 7ad0e7f7d05a..eabb2ab696ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -99,6 +99,7 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.unfold.config.UnfoldTransitionConfig;
@@ -212,7 +213,8 @@ public interface StatusBarPhoneModule {
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
WallpaperManager wallpaperManager,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
- Optional<StartingSurface> startingSurfaceOptional) {
+ Optional<StartingSurface> startingSurfaceOptional,
+ TunerService tunerService) {
return new StatusBar(
context,
notificationsController,
@@ -298,6 +300,7 @@ public interface StatusBarPhoneModule {
keyguardUnlockAnimationController,
wallpaperManager,
unlockedScreenOffAnimationController,
- startingSurfaceOptional);
+ startingSurfaceOptional,
+ tunerService);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 1db6ce4ea2a8..62ba56ab2077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -216,6 +216,10 @@ class OngoingCallController @Inject constructor(
isCallAppVisible = isProcessVisibleToUser(
iActivityManager.getUidProcessState(currentCallNotificationInfo.uid, null))
+ if (uidObserver != null) {
+ iActivityManager.unregisterUidObserver(uidObserver)
+ }
+
uidObserver = object : IUidObserver.Stub() {
override fun onUidStateChanged(
uid: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index d80fa12f5122..f54bb6882ed0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -68,6 +68,7 @@ public class AccessPointControllerImpl
private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
private final UserManager mUserManager;
+ private final UserTracker mUserTracker;
private final Executor mMainExecutor;
private @Nullable WifiPickerTracker mWifiPickerTracker;
@@ -84,6 +85,7 @@ public class AccessPointControllerImpl
WifiPickerTrackerFactory wifiPickerTrackerFactory
) {
mUserManager = userManager;
+ mUserTracker = userTracker;
mCurrentUser = userTracker.getUserId();
mMainExecutor = mainExecutor;
mWifiPickerTrackerFactory = wifiPickerTrackerFactory;
@@ -120,7 +122,7 @@ public class AccessPointControllerImpl
public boolean canConfigMobileData() {
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
- UserHandle.of(mCurrentUser));
+ UserHandle.of(mCurrentUser)) && mUserTracker.getUserInfo().isAdmin();
}
public void onUserSwitched(int newUserId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 8f1a5782e779..251ecc626387 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -26,6 +26,7 @@ import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.IActivityTaskManager;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -114,6 +115,8 @@ public class UserSwitcherController implements Dumpable {
@VisibleForTesting
final GuestResumeSessionReceiver mGuestResumeSessionReceiver;
private final KeyguardStateController mKeyguardStateController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+ private final DevicePolicyManager mDevicePolicyManager;
protected final Handler mHandler;
private final ActivityStarter mActivityStarter;
private final BroadcastDispatcher mBroadcastDispatcher;
@@ -149,6 +152,8 @@ public class UserSwitcherController implements Dumpable {
UserManager userManager,
UserTracker userTracker,
KeyguardStateController keyguardStateController,
+ DeviceProvisionedController deviceProvisionedController,
+ DevicePolicyManager devicePolicyManager,
@Main Handler handler,
ActivityStarter activityStarter,
BroadcastDispatcher broadcastDispatcher,
@@ -178,6 +183,8 @@ public class UserSwitcherController implements Dumpable {
mGuestIsResetting = new AtomicBoolean();
mGuestCreationScheduled = new AtomicBoolean();
mKeyguardStateController = keyguardStateController;
+ mDeviceProvisionedController = deviceProvisionedController;
+ mDevicePolicyManager = devicePolicyManager;
mHandler = handler;
mActivityStarter = activityStarter;
mUserManager = userManager;
@@ -336,8 +343,7 @@ public class UserSwitcherController implements Dumpable {
true /* isGuest */, false /* isCurrent */,
false /* isAddUser */, false /* isRestricted */,
isSwitchToGuestEnabled);
- // Don't call checkIfAddUserDisallowedByAdminOnly if
- // config_guestUserAutoCreated=true.
+ checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
} else if (canCreateGuest) {
guestRecord = new UserRecord(null /* info */, null /* picture */,
@@ -733,10 +739,27 @@ public class UserSwitcherController implements Dumpable {
}
/**
+ * Guarantee guest is present only if the device is provisioned. Otherwise, create a content
+ * observer to wait until the device is provisioned, then schedule the guest creation.
+ */
+ public void schedulePostBootGuestCreation() {
+ if (isDeviceAllowedToAddGuest()) {
+ guaranteeGuestPresent();
+ } else {
+ mDeviceProvisionedController.addCallback(mGuaranteeGuestPresentAfterProvisioned);
+ }
+ }
+
+ private boolean isDeviceAllowedToAddGuest() {
+ return mDeviceProvisionedController.isDeviceProvisioned()
+ && !mDevicePolicyManager.isDeviceManaged();
+ }
+
+ /**
* If there is no guest on the device, schedule creation of a new guest user in the background.
*/
- public void guaranteeGuestPresent() {
- if (mUserManager.findCurrentGuestUser() == null) {
+ private void guaranteeGuestPresent() {
+ if (isDeviceAllowedToAddGuest() && mUserManager.findCurrentGuestUser() == null) {
scheduleGuestCreation();
}
}
@@ -1056,6 +1079,21 @@ public class UserSwitcherController implements Dumpable {
}
};
+ private final DeviceProvisionedController.DeviceProvisionedListener
+ mGuaranteeGuestPresentAfterProvisioned =
+ new DeviceProvisionedController.DeviceProvisionedListener() {
+ @Override
+ public void onDeviceProvisionedChanged() {
+ if (isDeviceAllowedToAddGuest()) {
+ mBgExecutor.execute(
+ () -> mDeviceProvisionedController.removeCallback(
+ mGuaranteeGuestPresentAfterProvisioned));
+ guaranteeGuestPresent();
+ }
+ }
+ };
+
+
private final class ExitGuestDialog extends SystemUIDialog implements
DialogInterface.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index b38fc77fd131..90e022a52d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -290,15 +290,18 @@ public class ProximitySensor implements ThresholdSensor {
return;
}
- if (!mSecondaryThresholdSensor.isLoaded()) {
+
+ if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary
logDebug("Primary sensor event: " + event.getBelow() + ". No secondary.");
onSensorEvent(event);
- } else if (event.getBelow()) {
+ } else if (event.getBelow()) { // Covered? Check secondary.
logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary.");
if (mCancelSecondaryRunnable != null) {
mCancelSecondaryRunnable.run();
}
mSecondaryThresholdSensor.resume();
+ } else { // Uncovered. Report immediately.
+ onSensorEvent(event);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 56f1c092efd9..f2e031cfa1df 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -26,7 +26,6 @@ import android.os.Bundle;
import android.view.WindowManager.LayoutParams;
import com.android.settingslib.applications.InterestingConfigChanges;
-import com.android.systemui.Dependency;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
@@ -67,6 +66,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
| ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
private final KeyguardViewMediator mKeyguardViewMediator;
+ private final ActivityStarter mActivityStarter;
private VolumeDialog mDialog;
private VolumePolicy mVolumePolicy = new VolumePolicy(
DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT, // volumeDownToEnterSilent
@@ -79,16 +79,20 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
public VolumeDialogComponent(
Context context,
KeyguardViewMediator keyguardViewMediator,
+ ActivityStarter activityStarter,
VolumeDialogControllerImpl volumeDialogController,
- DemoModeController demoModeController) {
+ DemoModeController demoModeController,
+ PluginDependencyProvider pluginDependencyProvider,
+ ExtensionController extensionController,
+ TunerService tunerService) {
mContext = context;
mKeyguardViewMediator = keyguardViewMediator;
+ mActivityStarter = activityStarter;
mController = volumeDialogController;
mController.setUserActivityListener(this);
// Allow plugins to reference the VolumeDialogController.
- Dependency.get(PluginDependencyProvider.class)
- .allowPluginDependency(VolumeDialogController.class);
- Dependency.get(ExtensionController.class).newExtension(VolumeDialog.class)
+ pluginDependencyProvider.allowPluginDependency(VolumeDialogController.class);
+ extensionController.newExtension(VolumeDialog.class)
.withPlugin(VolumeDialog.class)
.withDefault(this::createDefault)
.withCallback(dialog -> {
@@ -99,7 +103,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
mDialog.init(LayoutParams.TYPE_VOLUME_OVERLAY, mVolumeDialogCallback);
}).build();
applyConfiguration();
- Dependency.get(TunerService.class).addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
+ tunerService.addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
VOLUME_SILENT_DO_NOT_DISTURB);
demoModeController.addCallback(this);
}
@@ -189,8 +193,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
}
private void startSettings(Intent intent) {
- Dependency.get(ActivityStarter.class).startActivity(intent,
- true /* onlyProvisioned */, true /* dismissShade */);
+ mActivityStarter.startActivity(intent, true /* onlyProvisioned */, true /* dismissShade */);
}
private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index f31762819d00..dbf115b62a58 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -2255,6 +2255,11 @@ public class VolumeDialogImpl implements VolumeDialog,
@Override
public void onClick(View view) {
+ // If the ringer drawer isn't open, don't let anything in it be clicked.
+ if (!mIsRingerDrawerOpen) {
+ return;
+ }
+
setRingerMode(mClickedRingerMode);
mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 39a8bd94bf37..dbdc460b7d83 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -25,6 +25,7 @@ import com.android.systemui.dagger.WMSingleton;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
@@ -58,10 +59,10 @@ public class TvWMShellModule {
@WMSingleton
@Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
- DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor,
- TransactionPool transactionPool) {
- return new DisplayImeController(wmService, displayController, mainExecutor,
- transactionPool);
+ DisplayController displayController, DisplayInsetsController displayInsetsController,
+ @ShellMainThread ShellExecutor mainExecutor, TransactionPool transactionPool) {
+ return new DisplayImeController(wmService, displayController, displayInsetsController,
+ mainExecutor, transactionPool);
}
//
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 7e733a9721ef..7937dfd0dbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -44,6 +44,7 @@ import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
@@ -55,6 +56,7 @@ import com.android.wm.shell.common.annotations.ShellAnimationThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
@@ -109,6 +111,14 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
+ static DisplayInsetsController provideDisplayInsetsController( IWindowManager wmService,
+ DisplayController displayController,
+ @ShellMainThread ShellExecutor mainExecutor) {
+ return new DisplayInsetsController(wmService, displayController, mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
static DisplayLayout provideDisplayLayout() {
return new DisplayLayout();
}
@@ -213,6 +223,13 @@ public abstract class WMShellBaseModule {
}
//
+ // Freeform (optional feature)
+ //
+
+ @BindsOptionalOf
+ abstract Optional<FreeformTaskListener> optionalFreeformTaskListener();
+
+ //
// Hide display cutout
//
@@ -328,9 +345,11 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
- Context context, @ShellMainThread ShellExecutor mainExecutor,
+ DisplayController displayController, Context context,
+ @ShellMainThread ShellExecutor mainExecutor,
@ShellAnimationThread ShellExecutor animExecutor) {
- return new Transitions(organizer, pool, context, mainExecutor, animExecutor);
+ return new Transitions(organizer, pool, displayController, context, mainExecutor,
+ animExecutor);
}
//
@@ -442,7 +461,9 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
- static ShellInitImpl provideShellInitImpl(DisplayImeController displayImeController,
+ static ShellInitImpl provideShellInitImpl(DisplayController displayController,
+ DisplayImeController displayImeController,
+ DisplayInsetsController displayInsetsController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<BubbleController> bubblesOptional,
@@ -451,10 +472,13 @@ public abstract class WMShellBaseModule {
Optional<AppPairsController> appPairsOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
+ Optional<Optional<FreeformTaskListener>> freeformTaskListener,
Transitions transitions,
StartingWindowController startingWindow,
@ShellMainThread ShellExecutor mainExecutor) {
- return new ShellInitImpl(displayImeController,
+ return new ShellInitImpl(displayController,
+ displayImeController,
+ displayInsetsController,
dragAndDropController,
shellTaskOrganizer,
bubblesOptional,
@@ -463,6 +487,7 @@ public abstract class WMShellBaseModule {
appPairsOptional,
pipTouchHandlerOptional,
fullscreenTaskListener,
+ freeformTaskListener,
transitions,
startingWindow,
mainExecutor);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index be7813e19b11..83c2a9b1be33 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -28,6 +28,7 @@ import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.apppairs.AppPairsController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -36,6 +37,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
@@ -82,10 +84,23 @@ public class WMShellModule {
@WMSingleton
@Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
- DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor,
+ DisplayController displayController, DisplayInsetsController displayInsetsController,
+ @ShellMainThread ShellExecutor mainExecutor,
TransactionPool transactionPool) {
- return new DisplayImeController(wmService, displayController, mainExecutor,
- transactionPool);
+ return new DisplayImeController(wmService, displayController, displayInsetsController,
+ mainExecutor, transactionPool);
+ }
+
+ //
+ // Freeform
+ //
+
+ @WMSingleton
+ @Provides
+ static Optional<FreeformTaskListener> provideFreeformTaskListener(
+ Context context,
+ SyncTransactionQueue syncQueue) {
+ return Optional.ofNullable(FreeformTaskListener.create(context, syncQueue));
}
//
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 06b0bb25e01c..ce65733ad5e5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -19,7 +19,6 @@ package com.android.keyguard;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -29,6 +28,7 @@ import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
@@ -104,6 +104,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
private AnimatableClockView mLargeClockView;
@Mock
private FrameLayout mLargeClockFrame;
+ @Mock
+ private ViewGroup mSmartspaceContainer;
private final View mFakeSmartspaceView = new View(mContext);
@@ -123,6 +125,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
when(mView.findViewById(R.id.animatable_clock_view)).thenReturn(mClockView);
when(mView.findViewById(R.id.animatable_clock_view_large)).thenReturn(mLargeClockView);
when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame);
+ when(mView.findViewById(R.id.keyguard_smartspace_container))
+ .thenReturn(mSmartspaceContainer);
when(mClockView.getContext()).thenReturn(getContext());
when(mLargeClockView.getContext()).thenReturn(getContext());
@@ -210,7 +214,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
@Test
public void testSmartspaceEnabledRemovesKeyguardStatusArea() {
- when(mSmartspaceController.isEnabled()).thenReturn(true);
+ when(mSmartspaceController.isSmartspaceEnabled()).thenReturn(true);
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
mController.init();
@@ -219,7 +223,7 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
@Test
public void testSmartspaceDisabledShowsKeyguardStatusArea() {
- when(mSmartspaceController.isEnabled()).thenReturn(false);
+ when(mSmartspaceController.isSmartspaceEnabled()).thenReturn(false);
mController.init();
assertEquals(View.VISIBLE, mStatusArea.getVisibility());
@@ -227,17 +231,16 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
@Test
public void testDetachRemovesSmartspaceView() {
- when(mSmartspaceController.isEnabled()).thenReturn(true);
+ when(mSmartspaceController.isSmartspaceEnabled()).thenReturn(true);
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
mController.init();
- verify(mView).addView(eq(mFakeSmartspaceView), anyInt(), any());
ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mView).removeView(mFakeSmartspaceView);
+ verify(mSmartspaceContainer).removeAllViews();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
new file mode 100644
index 000000000000..db87c5df16e1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class KeyguardListenQueueTest : SysuiTestCase() {
+
+ @Test
+ fun testQueueIsBounded() {
+ val size = 5
+ val queue = KeyguardListenQueue(sizePerModality = size)
+
+ val fingerprints = List(100) { fingerprintModel(it) }
+ fingerprints.forEach { queue.add(it) }
+
+ assertThat(queue.models).containsExactlyElementsIn(fingerprints.takeLast(size))
+
+ val faces = List(100) { faceModel(it) }
+ faces.forEach { queue.add(it) }
+
+ assertThat(queue.models).containsExactlyElementsIn(
+ faces.takeLast(size) + fingerprints.takeLast(5)
+ )
+
+ repeat(100) {
+ queue.add(faceModel(-1))
+ queue.add(fingerprintModel(-1))
+ }
+ assertThat(queue.models).hasSize(2 * size)
+ assertThat(queue.models.count { it.userId == -1 }).isEqualTo(2 * size)
+ }
+}
+
+private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel(
+ timeMillis = System.currentTimeMillis(),
+ userId = user,
+ listening = false,
+ biometricEnabledForUser = false,
+ bouncer = false,
+ canSkipBouncer = false,
+ credentialAttempted = false,
+ deviceInteractive = false,
+ dreaming = false,
+ encryptedOrLockdown = false,
+ fingerprintDisabled = false,
+ fingerprintLockedOut = false,
+ goingToSleep = false,
+ keyguardGoingAway = false,
+ keyguardIsVisible = false,
+ keyguardOccluded = false,
+ occludingAppRequestingFp = false,
+ primaryUser = false,
+ shouldListenForFingerprintAssistant = false,
+ switchingUser = false,
+ udfps = false,
+ userDoesNotHaveTrust = false,
+ userNeedsStrongAuth = false
+)
+
+private fun faceModel(user: Int) = KeyguardFaceListenModel(
+ timeMillis = System.currentTimeMillis(),
+ userId = user,
+ listening = false,
+ authInterruptActive = false,
+ becauseCannotSkipBouncer = false,
+ biometricSettingEnabledForUser = false,
+ bouncer = false,
+ faceAuthenticated = false,
+ faceDisabled = false,
+ keyguardAwake = false,
+ keyguardGoingAway = false,
+ listeningForFaceAssistant = false,
+ lockIconPressed = false,
+ occludingAppRequestingFaceAuth = false,
+ primaryUser = false,
+ scanningAllowedByStrongAuth = false,
+ secureCameraLaunched = false,
+ switchingUser = false
+)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index bb71bed84f43..8e1e42a9c9a2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
+import com.android.systemui.statusbar.policy.DevicePostureController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,6 +63,8 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() {
private lateinit var mKeyguardMessageAreaController: KeyguardMessageAreaController
@Mock
private lateinit var mLockPatternView: LockPatternView
+ @Mock
+ private lateinit var mPostureController: DevicePostureController
private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController
@@ -78,7 +81,7 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() {
mKeyguardPatternViewController = KeyguardPatternViewController(mKeyguardPatternView,
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
mLatencyTracker, mFalsingCollector, mEmergencyButtonController,
- mKeyguardMessageAreaControllerFactory)
+ mKeyguardMessageAreaControllerFactory, mPostureController)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java
index 06e27b5dbf48..f09d7b78ea6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.accessibility.floatingmenu;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.View.OVER_SCROLL_ALWAYS;
import static android.view.View.OVER_SCROLL_NEVER;
import static android.view.WindowInsets.Type.ime;
@@ -134,7 +135,10 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase {
mMenuHalfHeight = menuHeight / 2;
mScreenHalfWidth = screenWidth / 2;
mScreenHalfHeight = mScreenHeight / 2;
- mMaxWindowX = screenWidth - margin - menuWidth;
+ int marginStartEnd =
+ mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT
+ ? margin : 0;
+ mMaxWindowX = screenWidth - marginStartEnd - menuWidth;
mMenuWindowHeight = menuHeight + margin * 2;
mMaxWindowY = mScreenHeight - mMenuWindowHeight;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
new file mode 100644
index 000000000000..903cbb522e4f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2021 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.battery;
+
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+
+import static com.android.systemui.util.mockito.KotlinMockitoHelpersKt.eq;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.os.Handler;
+import android.provider.Settings;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+public class BatteryMeterViewControllerTest extends SysuiTestCase {
+ @Mock
+ private BatteryMeterView mBatteryMeterView;
+
+ @Mock
+ private ConfigurationController mConfigurationController;
+ @Mock
+ private TunerService mTunerService;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private Handler mHandler;
+ @Mock
+ private ContentResolver mContentResolver;
+
+ private BatteryMeterViewController mController;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mBatteryMeterView.getContext()).thenReturn(mContext);
+ when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
+
+ mController = new BatteryMeterViewController(
+ mBatteryMeterView,
+ mConfigurationController,
+ mTunerService,
+ mBroadcastDispatcher,
+ mHandler,
+ mContentResolver
+ );
+ }
+
+ @Test
+ public void onViewAttached_callbacksRegistered() {
+ mController.onViewAttached();
+
+ verify(mConfigurationController).addCallback(any());
+ verify(mTunerService).addTunable(any(), any());
+ verify(mContentResolver).registerContentObserver(
+ eq(Settings.System.getUriFor(SHOW_BATTERY_PERCENT)), anyBoolean(), any(), anyInt()
+ );
+ verify(mContentResolver).registerContentObserver(
+ eq(Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME)),
+ anyBoolean(),
+ any()
+ );
+ }
+
+ @Test
+ public void onViewDetached_callbacksUnregistered() {
+ // Set everything up first.
+ mController.onViewAttached();
+
+ mController.onViewDetached();
+
+ verify(mConfigurationController).removeCallback(any());
+ verify(mTunerService).removeTunable(any());
+ verify(mContentResolver).unregisterContentObserver(any());
+ }
+
+ @Test
+ public void ignoreTunerUpdates_afterOnViewAttached_callbackUnregistered() {
+ // Start out receiving tuner updates
+ mController.onViewAttached();
+
+ mController.ignoreTunerUpdates();
+
+ verify(mTunerService).removeTunable(any());
+ }
+
+ @Test
+ public void ignoreTunerUpdates_beforeOnViewAttached_callbackNeverRegistered() {
+ mController.ignoreTunerUpdates();
+
+ mController.onViewAttached();
+
+ verify(mTunerService, never()).addTunable(any(), any());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
index e478b1afa65c..b6d1e42a4763 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java
@@ -102,7 +102,7 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
mFaceToFpView.onDialogAnimatedIn();
verify(mFaceToFpView.mFaceIconController)
.updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
- verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());
+ verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt());
}
@Test
@@ -110,13 +110,13 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
mFaceToFpView.onDialogAnimatedIn();
verify(mFaceToFpView.mFaceIconController)
.updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
- verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());
+ verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt());
mFaceToFpView.updateState(AuthBiometricFaceView.STATE_AUTHENTICATED);
verify(mFaceToFpView.mFaceIconController).updateState(
eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING),
eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED));
- verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());
+ verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt());
assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED, mFaceToFpView.mState);
}
@@ -131,14 +131,12 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
verify(mFaceToFpView.mFaceIconController).deactivate();
verify(mFaceToFpView.mUdfpsIconController).updateState(
- eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING),
- eq(AuthBiometricFaceToFingerprintView.STATE_ERROR));
+ eq(AuthBiometricFaceToFingerprintView.STATE_IDLE));
verify(mConfirmButton).setVisibility(eq(View.GONE));
mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);
verify(mFaceToFpView.mUdfpsIconController).updateState(
- eq(AuthBiometricFaceToFingerprintView.STATE_ERROR),
eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
index 223714cfda30..7bc5f86510a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagReaderTest.java
@@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.wrapper.BuildInfo;
import org.junit.Before;
@@ -43,6 +44,7 @@ import org.mockito.MockitoAnnotations;
public class FeatureFlagReaderTest extends SysuiTestCase {
@Mock private Resources mResources;
@Mock private BuildInfo mBuildInfo;
+ @Mock private PluginManager mPluginManager;
@Mock private SystemPropertiesHelper mSystemPropertiesHelper;
private FeatureFlagReader mReader;
@@ -63,7 +65,8 @@ public class FeatureFlagReaderTest extends SysuiTestCase {
private void initialize(boolean isDebuggable, boolean isOverrideable) {
when(mBuildInfo.isDebuggable()).thenReturn(isDebuggable);
when(mResources.getBoolean(R.bool.are_flags_overrideable)).thenReturn(isOverrideable);
- mReader = new FeatureFlagReader(mResources, mBuildInfo, mSystemPropertiesHelper);
+ mReader = new FeatureFlagReader(
+ mResources, mBuildInfo, mPluginManager, mSystemPropertiesHelper);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsTest.java
new file mode 100644
index 000000000000..1a961787ee79
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 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.flags;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.FlagReaderPlugin;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+public class FeatureFlagsTest extends SysuiTestCase {
+
+ @Mock FeatureFlagReader mFeatureFlagReader;
+
+ private FeatureFlags mFeatureFlags;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mFeatureFlags = new FeatureFlags(mFeatureFlagReader, getContext());
+ }
+
+ @Test
+ public void testAddListener() {
+ Flag<?> flag = new BooleanFlag(1);
+ mFeatureFlags.addFlag(flag);
+
+ // Assert and capture that a plugin listener was added.
+ ArgumentCaptor<FlagReaderPlugin.Listener> pluginListenerCaptor =
+ ArgumentCaptor.forClass(FlagReaderPlugin.Listener.class);
+
+ verify(mFeatureFlagReader).addListener(pluginListenerCaptor.capture());
+ FlagReaderPlugin.Listener pluginListener = pluginListenerCaptor.getValue();
+
+ // Signal a change. No listeners, so no real effect.
+ pluginListener.onFlagChanged(flag.getId());
+
+ // Add a listener for the flag
+ final Flag<?>[] changedFlag = {null};
+ FeatureFlags.Listener listener = f -> changedFlag[0] = f;
+ mFeatureFlags.addFlagListener(flag, listener);
+
+ // No changes seen yet.
+ assertThat(changedFlag[0]).isNull();
+
+ // Signal a change.
+ pluginListener.onFlagChanged(flag.getId());
+
+ // Assert that the change was for the correct flag.
+ assertThat(changedFlag[0]).isEqualTo(flag);
+ }
+
+ @Test
+ public void testRemoveListener() {
+ Flag<?> flag = new BooleanFlag(1);
+ mFeatureFlags.addFlag(flag);
+
+ // Assert and capture that a plugin listener was added.
+ ArgumentCaptor<FlagReaderPlugin.Listener> pluginListenerCaptor =
+ ArgumentCaptor.forClass(FlagReaderPlugin.Listener.class);
+
+ verify(mFeatureFlagReader).addListener(pluginListenerCaptor.capture());
+ FlagReaderPlugin.Listener pluginListener = pluginListenerCaptor.getValue();
+
+ // Add a listener for the flag
+ final Flag<?>[] changedFlag = {null};
+ FeatureFlags.Listener listener = f -> changedFlag[0] = f;
+ mFeatureFlags.addFlagListener(flag, listener);
+
+ // Signal a change.
+ pluginListener.onFlagChanged(flag.getId());
+
+ // Assert that the change was for the correct flag.
+ assertThat(changedFlag[0]).isEqualTo(flag);
+
+ changedFlag[0] = null;
+
+ // Now remove the listener.
+ mFeatureFlags.removeFlagListener(flag, listener);
+ // Signal a change.
+ pluginListener.onFlagChanged(flag.getId());
+ // Assert that the change was not triggered
+ assertThat(changedFlag[0]).isNull();
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
new file mode 100644
index 000000000000..25c302885e07
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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.flags;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SmallTest
+public class FlagsTest extends SysuiTestCase {
+
+ @Test
+ public void testDuplicateFlagIdCheckWorks() {
+ List<Pair<String, Flag<?>>> flags = collectFlags(DuplicateFlagContainer.class);
+ Map<Integer, List<String>> duplicates = groupDuplicateFlags(flags);
+
+ assertWithMessage(generateAssertionMessage(duplicates))
+ .that(duplicates.size()).isEqualTo(2);
+ }
+
+ @Test
+ public void testNoDuplicateFlagIds() {
+ List<Pair<String, Flag<?>>> flags = collectFlags(Flags.class);
+ Map<Integer, List<String>> duplicates = groupDuplicateFlags(flags);
+
+ assertWithMessage(generateAssertionMessage(duplicates))
+ .that(duplicates.size()).isEqualTo(0);
+ }
+
+ private String generateAssertionMessage(Map<Integer, List<String>> duplicates) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("Duplicate flag keys found: {");
+ for (int id : duplicates.keySet()) {
+ stringBuilder
+ .append(" ")
+ .append(id)
+ .append(": [")
+ .append(String.join(", ", duplicates.get(id)))
+ .append("]");
+ }
+ stringBuilder.append(" }");
+
+ return stringBuilder.toString();
+ }
+
+ private List<Pair<String, Flag<?>>> collectFlags(Class<?> clz) {
+ List<Pair<String, Flag<?>>> flags = new ArrayList<>();
+
+ Field[] fields = clz.getFields();
+
+ for (Field field : fields) {
+ Class<?> t = field.getType();
+ if (Flag.class.isAssignableFrom(t)) {
+ try {
+ flags.add(Pair.create(field.getName(), (Flag<?>) field.get(null)));
+ } catch (IllegalAccessException e) {
+ // no-op
+ }
+ }
+ }
+
+ return flags;
+ }
+
+ private Map<Integer, List<String>> groupDuplicateFlags(List<Pair<String, Flag<?>>> flags) {
+ Map<Integer, List<String>> grouping = new HashMap<>();
+
+ for (Pair<String, Flag<?>> flag : flags) {
+ grouping.putIfAbsent(flag.second.getId(), new ArrayList<>());
+ grouping.get(flag.second.getId()).add(flag.first);
+ }
+
+ Map<Integer, List<String>> result = new HashMap<>();
+ for (Integer id : grouping.keySet()) {
+ if (grouping.get(id).size() > 1) {
+ result.put(id, grouping.get(id));
+ }
+ }
+
+ return result;
+ }
+
+ private static class DuplicateFlagContainer {
+ public static final BooleanFlag A_FLAG = new BooleanFlag(0);
+ public static final BooleanFlag B_FLAG = new BooleanFlag(0);
+ public static final StringFlag C_FLAG = new StringFlag(0);
+
+ public static final BooleanFlag D_FLAG = new BooleanFlag(1);
+
+ public static final DoubleFlag E_FLAG = new DoubleFlag(3);
+ public static final DoubleFlag F_FLAG = new DoubleFlag(3);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 8c0d21e911da..4483f3770a97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -169,14 +169,14 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
public void testShouldLogShow() {
mGlobalActionsDialogLite.onShow(null);
mTestableLooper.processAllMessages();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_OPEN);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_POWER_MENU_OPEN);
}
@Test
public void testShouldLogDismiss() {
mGlobalActionsDialogLite.onDismiss(mGlobalActionsDialogLite.mDialog);
mTestableLooper.processAllMessages();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_CLOSE);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_POWER_MENU_CLOSE);
}
@Test
@@ -186,16 +186,16 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
dialog.onBackPressed();
mTestableLooper.processAllMessages();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_BACK);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_BACK);
}
@Test
@@ -205,17 +205,17 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener);
gestureListener.onSingleTapConfirmed(null);
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
}
@Test
@@ -226,10 +226,10 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
doReturn(true).when(mStatusBar).isKeyguardShowing();
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
@@ -238,7 +238,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
MotionEvent start = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0);
gestureListener.onFling(start, end, 0, 1000);
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
verify(mStatusBar).animateExpandSettingsPanel(null);
}
@@ -250,10 +250,10 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
doReturn(false).when(mStatusBar).isKeyguardShowing();
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
@@ -262,40 +262,40 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
MotionEvent start = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
MotionEvent end = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 500, 0);
gestureListener.onFling(start, end, 0, 1000);
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
verify(mStatusBar).animateExpandNotificationsPanel();
}
@Test
public void testShouldLogBugreportPress() throws InterruptedException {
- GlobalActionsDialog.BugReportAction bugReportAction =
+ GlobalActionsDialogLite.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
bugReportAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_BUGREPORT_PRESS);
}
@Test
public void testShouldLogBugreportLongPress() {
- GlobalActionsDialog.BugReportAction bugReportAction =
+ GlobalActionsDialogLite.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
bugReportAction.onLongPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
}
@Test
public void testShouldLogEmergencyDialerPress() {
- GlobalActionsDialog.EmergencyDialerAction emergencyDialerAction =
+ GlobalActionsDialogLite.EmergencyDialerAction emergencyDialerAction =
mGlobalActionsDialogLite.makeEmergencyDialerActionForTesting();
emergencyDialerAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
}
@Test
public void testShouldLogScreenshotPress() {
- GlobalActionsDialog.ScreenshotAction screenshotAction =
+ GlobalActionsDialogLite.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
screenshotAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_SCREENSHOT_PRESS);
}
@Test
@@ -304,7 +304,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
com.android.internal.R.integer.config_navBarInteractionMode,
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON);
- GlobalActionsDialog.ScreenshotAction screenshotAction =
+ GlobalActionsDialogLite.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
assertThat(screenshotAction.shouldShow()).isTrue();
}
@@ -315,12 +315,12 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
com.android.internal.R.integer.config_navBarInteractionMode,
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
- GlobalActionsDialog.ScreenshotAction screenshotAction =
+ GlobalActionsDialogLite.ScreenshotAction screenshotAction =
mGlobalActionsDialogLite.makeScreenshotActionForTesting();
assertThat(screenshotAction.shouldShow()).isFalse();
}
- private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) {
+ private void verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent event) {
mTestableLooper.processAllMessages();
verify(mUiEventLogger, times(1))
.log(event);
@@ -341,19 +341,19 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
mGlobalActionsDialogLite.createActionItems();
assertItemsOfType(mGlobalActionsDialogLite.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.LockDownAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
+ GlobalActionsDialogLite.EmergencyAction.class,
+ GlobalActionsDialogLite.LockDownAction.class,
+ GlobalActionsDialogLite.ShutDownAction.class,
+ GlobalActionsDialogLite.RestartAction.class);
assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
}
@@ -365,19 +365,19 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
// make sure lockdown action will NOT be shown
doReturn(false).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
// lockdown action not allowed
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
};
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
mGlobalActionsDialogLite.createActionItems();
assertItemsOfType(mGlobalActionsDialogLite.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
+ GlobalActionsDialogLite.EmergencyAction.class,
+ GlobalActionsDialogLite.ShutDownAction.class,
+ GlobalActionsDialogLite.RestartAction.class);
assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
}
@@ -387,7 +387,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
GlobalActionsDialogLite.LockDownAction lockDownAction =
mGlobalActionsDialogLite.new LockDownAction();
lockDownAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_LOCKDOWN_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_LOCKDOWN_PRESS);
}
@Test
@@ -395,7 +395,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
GlobalActionsDialogLite.ShutDownAction shutDownAction =
mGlobalActionsDialogLite.new ShutDownAction();
shutDownAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SHUTDOWN_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_SHUTDOWN_PRESS);
}
@Test
@@ -403,7 +403,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
GlobalActionsDialogLite.ShutDownAction shutDownAction =
mGlobalActionsDialogLite.new ShutDownAction();
shutDownAction.onLongPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
}
@Test
@@ -411,7 +411,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
GlobalActionsDialogLite.RestartAction restartAction =
mGlobalActionsDialogLite.new RestartAction();
restartAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_REBOOT_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_REBOOT_PRESS);
}
@Test
@@ -419,6 +419,6 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
GlobalActionsDialogLite.RestartAction restartAction =
mGlobalActionsDialogLite.new RestartAction();
restartAction.onLongPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_REBOOT_LONG_PRESS);
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_REBOOT_LONG_PRESS);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
deleted file mode 100644
index 6d1db378bf2a..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.globalactions;
-
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.IActivityManager;
-import android.app.admin.DevicePolicyManager;
-import android.app.trust.TrustManager;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.media.AudioManager;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserManager;
-import android.service.dreams.IDreamManager;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.IWindowManager;
-import android.view.View;
-import android.view.WindowManagerPolicyConstants;
-import android.widget.FrameLayout;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.GlobalActions;
-import com.android.systemui.plugins.GlobalActionsPanelPlugin;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.telephony.TelephonyListenerManager;
-import com.android.systemui.util.RingerModeLiveData;
-import com.android.systemui.util.RingerModeTracker;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SecureSettings;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.Executor;
-import java.util.regex.Pattern;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class GlobalActionsDialogTest extends SysuiTestCase {
- private static final long UI_TIMEOUT_MILLIS = 5000; // 5 sec
- private static final Pattern CANCEL_BUTTON =
- Pattern.compile("cancel", Pattern.CASE_INSENSITIVE);
-
- private GlobalActionsDialog mGlobalActionsDialog;
-
- @Mock private GlobalActions.GlobalActionsManager mWindowManagerFuncs;
- @Mock private AudioManager mAudioManager;
- @Mock private IDreamManager mDreamManager;
- @Mock private DevicePolicyManager mDevicePolicyManager;
- @Mock private LockPatternUtils mLockPatternUtils;
- @Mock private BroadcastDispatcher mBroadcastDispatcher;
- @Mock private TelephonyListenerManager mTelephonyListenerManager;
- @Mock private GlobalSettings mGlobalSettings;
- @Mock private Resources mResources;
- @Mock private ConfigurationController mConfigurationController;
- @Mock private ActivityStarter mActivityStarter;
- @Mock private KeyguardStateController mKeyguardStateController;
- @Mock private UserManager mUserManager;
- @Mock private TrustManager mTrustManager;
- @Mock private IActivityManager mActivityManager;
- @Mock private MetricsLogger mMetricsLogger;
- @Mock private SysuiColorExtractor mColorExtractor;
- @Mock private IStatusBarService mStatusBarService;
- @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
- @Mock private IWindowManager mWindowManager;
- @Mock private Executor mBackgroundExecutor;
- @Mock private UiEventLogger mUiEventLogger;
- @Mock private RingerModeTracker mRingerModeTracker;
- @Mock private RingerModeLiveData mRingerModeLiveData;
- @Mock private SysUiState mSysUiState;
- @Mock GlobalActionsPanelPlugin mWalletPlugin;
- @Mock GlobalActionsPanelPlugin.PanelViewController mWalletController;
- @Mock private Handler mHandler;
- @Mock private UserTracker mUserTracker;
- @Mock private PackageManager mPackageManager;
- @Mock private SecureSettings mSecureSettings;
- @Mock private StatusBar mStatusBar;
-
- private TestableLooper mTestableLooper;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mTestableLooper = TestableLooper.get(this);
- allowTestableLooperAsMainThread();
-
- when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);
- when(mResources.getConfiguration()).thenReturn(
- getContext().getResources().getConfiguration());
-
- mGlobalActionsDialog = new GlobalActionsDialog(mContext,
- mWindowManagerFuncs,
- mAudioManager,
- mDreamManager,
- mDevicePolicyManager,
- mLockPatternUtils,
- mBroadcastDispatcher,
- mTelephonyListenerManager,
- mGlobalSettings,
- mSecureSettings,
- null,
- mResources,
- mConfigurationController,
- mActivityStarter,
- mKeyguardStateController,
- mUserManager,
- mTrustManager,
- mActivityManager,
- null,
- mMetricsLogger,
- mColorExtractor,
- mStatusBarService,
- mNotificationShadeWindowController,
- mWindowManager,
- mBackgroundExecutor,
- mUiEventLogger,
- mRingerModeTracker,
- mSysUiState,
- mHandler,
- mPackageManager,
- Optional.of(mStatusBar)
- );
- mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
-
- ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors();
- backdropColors.setMainColor(Color.BLACK);
- when(mColorExtractor.getNeutralColors()).thenReturn(backdropColors);
- when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
- }
-
- @Test
- public void testShouldLogShow() {
- mGlobalActionsDialog.onShow(null);
- mTestableLooper.processAllMessages();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_OPEN);
- }
-
- @Test
- public void testShouldLogDismiss() {
- mGlobalActionsDialog.onDismiss(mGlobalActionsDialog.mDialog);
- mTestableLooper.processAllMessages();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_CLOSE);
- }
-
- @Test
- public void testShouldLogBugreportPress() throws InterruptedException {
- GlobalActionsDialog.BugReportAction bugReportAction =
- mGlobalActionsDialog.makeBugReportActionForTesting();
- bugReportAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_PRESS);
- }
-
- @Test
- public void testShouldLogBugreportLongPress() {
- GlobalActionsDialog.BugReportAction bugReportAction =
- mGlobalActionsDialog.makeBugReportActionForTesting();
- bugReportAction.onLongPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
- }
-
- @Test
- public void testShouldLogEmergencyDialerPress() {
- GlobalActionsDialog.EmergencyDialerAction emergencyDialerAction =
- mGlobalActionsDialog.makeEmergencyDialerActionForTesting();
- emergencyDialerAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_EMERGENCY_DIALER_PRESS);
- }
-
- @Test
- public void testShouldLogScreenshotPress() {
- GlobalActionsDialog.ScreenshotAction screenshotAction =
- mGlobalActionsDialog.makeScreenshotActionForTesting();
- screenshotAction.onPress();
- verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_PRESS);
- }
-
- @Test
- public void testShouldShowScreenshot() {
- mContext.getOrCreateTestableResources().addOverride(
- com.android.internal.R.integer.config_navBarInteractionMode,
- WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON);
-
- GlobalActionsDialog.ScreenshotAction screenshotAction =
- mGlobalActionsDialog.makeScreenshotActionForTesting();
- assertThat(screenshotAction.shouldShow()).isTrue();
- }
-
- @Test
- public void testShouldNotShowScreenshot() {
- mContext.getOrCreateTestableResources().addOverride(
- com.android.internal.R.integer.config_navBarInteractionMode,
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
-
- GlobalActionsDialog.ScreenshotAction screenshotAction =
- mGlobalActionsDialog.makeScreenshotActionForTesting();
- assertThat(screenshotAction.shouldShow()).isFalse();
- }
-
- private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) {
- mTestableLooper.processAllMessages();
- verify(mUiEventLogger, times(1))
- .log(event);
- }
-
- @SafeVarargs
- private static <T> void assertItemsOfType(List<T> stuff, Class<? extends T>... classes) {
- assertThat(stuff).hasSize(classes.length);
- for (int i = 0; i < stuff.size(); i++) {
- assertThat(stuff.get(i)).isInstanceOf(classes[i]);
- }
- }
-
- @Test
- public void testCreateActionItems_maxThree_noOverflow() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertThat(mGlobalActionsDialog.mPowerItems).isEmpty();
- }
-
- @Test
- public void testCreateActionItems_maxThree_condensePower() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- // make sure lockdown action will be shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.LockDownAction.class,
- GlobalActionsDialog.PowerOptionsAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertItemsOfType(mGlobalActionsDialog.mPowerItems,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- }
-
- @Test
- public void testCreateActionItems_maxThree_condensePower_splitPower() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // make sure lockdown action will be shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- // make sure bugreport also shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayBugReport(any());
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_BUGREPORT,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.LockDownAction.class,
- GlobalActionsDialog.PowerOptionsAction.class);
- assertItemsOfType(mGlobalActionsDialog.mOverflowItems,
- GlobalActionsDialog.BugReportAction.class);
- assertItemsOfType(mGlobalActionsDialog.mPowerItems,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- }
-
- @Test
- public void testCreateActionItems_maxFour_condensePower() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow 3 items to be shown
- doReturn(4).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // make sure lockdown action will be shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_SCREENSHOT
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.LockDownAction.class,
- GlobalActionsDialog.PowerOptionsAction.class,
- GlobalActionsDialog.ScreenshotAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertItemsOfType(mGlobalActionsDialog.mPowerItems,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- }
-
- @Test
- public void testCreateActionItems_maxThree_doNotCondensePower() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // make sure lockdown action will be shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- // make sure bugreport is also shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayBugReport(any());
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_BUGREPORT,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.BugReportAction.class);
- assertItemsOfType(mGlobalActionsDialog.mOverflowItems,
- GlobalActionsDialog.LockDownAction.class);
- assertThat(mGlobalActionsDialog.mPowerItems).isEmpty();
- }
-
- @Test
- public void testCreateActionItems_maxAny() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow any number of power menu items to be shown
- doReturn(Integer.MAX_VALUE).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // ensure items are not blocked by keyguard or device provisioning
- doReturn(true).when(mGlobalActionsDialog).shouldShowAction(any());
- // make sure lockdown action will be shown
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class,
- GlobalActionsDialog.LockDownAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertThat(mGlobalActionsDialog.mPowerItems).isEmpty();
- }
-
- @Test
- public void testCreateActionItems_maxThree_lockdownDisabled_doesNotShowLockdown() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow only 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- // make sure lockdown action will NOT be shown
- doReturn(false).when(mGlobalActionsDialog).shouldDisplayLockdown(any());
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- // lockdown action not allowed
- GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertThat(mGlobalActionsDialog.mPowerItems).isEmpty();
- }
-
- @Test
- public void testCreateActionItems_shouldShowAction_excludeBugReport() {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- // allow only 3 items to be shown
- doReturn(3).when(mGlobalActionsDialog).getMaxShownPowerItems();
- doReturn(true).when(mGlobalActionsDialog).shouldDisplayBugReport(any());
- // exclude bugreport in shouldShowAction to demonstrate how any button can be removed
- doAnswer(
- invocation -> !(invocation.getArgument(0)
- instanceof GlobalActionsDialog.BugReportAction))
- .when(mGlobalActionsDialog).shouldShowAction(any());
-
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- // bugreport action not allowed
- GlobalActionsDialog.GLOBAL_ACTION_KEY_BUGREPORT,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- mGlobalActionsDialog.createActionItems();
-
- assertItemsOfType(mGlobalActionsDialog.mItems,
- GlobalActionsDialog.EmergencyAction.class,
- GlobalActionsDialog.ShutDownAction.class,
- GlobalActionsDialog.RestartAction.class);
- assertThat(mGlobalActionsDialog.mOverflowItems).isEmpty();
- assertThat(mGlobalActionsDialog.mPowerItems).isEmpty();
- }
-
- @Test
- public void testShouldShowLockScreenMessage() throws RemoteException {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- mGlobalActionsDialog.mDialog = null;
- when(mKeyguardStateController.isUnlocked()).thenReturn(false);
- when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
- when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
- mGlobalActionsDialog.mShowLockScreenCards = false;
- setupDefaultActions();
- when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
- when(mWalletController.getPanelContent()).thenReturn(new FrameLayout(mContext));
-
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
-
- GlobalActionsDialog.ActionsDialog dialog =
- (GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
- assertThat(dialog).isNotNull();
- assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.VISIBLE);
-
- // Dismiss the dialog so that it does not pollute other tests
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
- }
-
- @Test
- public void testShouldNotShowLockScreenMessage_whenWalletShownOnLockScreen()
- throws RemoteException {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- mGlobalActionsDialog.mDialog = null;
- when(mKeyguardStateController.isUnlocked()).thenReturn(false);
- when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
- when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
- mGlobalActionsDialog.mShowLockScreenCards = true;
- setupDefaultActions();
- when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
- when(mWalletController.getPanelContent()).thenReturn(new FrameLayout(mContext));
-
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
-
- GlobalActionsDialog.ActionsDialog dialog =
- (GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
- assertThat(dialog).isNotNull();
- assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);
-
- // Dismiss the dialog so that it does not pollute other tests
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
- }
-
- @Test
- public void testShouldNotShowLockScreenMessage_whenWalletBothDisabled()
- throws RemoteException {
- mGlobalActionsDialog = spy(mGlobalActionsDialog);
- mGlobalActionsDialog.mDialog = null;
- when(mKeyguardStateController.isUnlocked()).thenReturn(false);
-
- when(mActivityManager.getCurrentUser()).thenReturn(newUserInfo());
- when(mLockPatternUtils.getStrongAuthForUser(anyInt())).thenReturn(STRONG_AUTH_NOT_REQUIRED);
- mGlobalActionsDialog.mShowLockScreenCards = true;
- setupDefaultActions();
- when(mWalletPlugin.onPanelShown(any(), anyBoolean())).thenReturn(mWalletController);
- when(mWalletController.getPanelContent()).thenReturn(null);
-
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
-
- GlobalActionsDialog.ActionsDialog dialog =
- (GlobalActionsDialog.ActionsDialog) mGlobalActionsDialog.mDialog;
- assertThat(dialog).isNotNull();
- assertThat(dialog.mLockMessageContainer.getVisibility()).isEqualTo(View.GONE);
-
- // Dismiss the dialog so that it does not pollute other tests
- mGlobalActionsDialog.showOrHideDialog(false, true, mWalletPlugin);
- }
-
- private UserInfo newUserInfo() {
- return new UserInfo(0, null, null, UserInfo.FLAG_PRIMARY, null);
- }
-
- private void setupDefaultActions() {
- String[] actions = {
- GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER,
- GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART,
- };
- doReturn(actions).when(mGlobalActionsDialog).getDefaultActions();
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
index 79b0dd0eda71..8cc2776bc16b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -69,7 +69,7 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(true)
whenever(mediaHost.hostView).thenReturn(hostView)
-
+ hostView.layoutParams = FrameLayout.LayoutParams(100, 100)
keyguardMediaController = KeyguardMediaController(
mediaHost,
bypassController,
@@ -79,6 +79,7 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
configurationController
)
keyguardMediaController.attachSinglePaneContainer(mediaHeaderView)
+ keyguardMediaController.useSplitShade = false
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 8fd2a329a33e..3ea57be98be0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -142,6 +142,8 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testCreateNavigationBarsIncludeDefaultTrue() {
+ // Tablets may be using taskbar and the logic is different
+ mNavigationBarController.mIsTablet = false;
doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
mNavigationBarController.createNavigationBars(true, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
new file mode 100644
index 000000000000..e54a6ec46b9c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
@@ -0,0 +1,93 @@
+package com.android.systemui.qs
+
+import com.android.systemui.R
+import android.os.UserManager
+import android.view.LayoutInflater
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.testing.FakeMetricsLogger
+import com.android.systemui.Dependency
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.globalactions.GlobalActionsDialogLite
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.qs.FooterActionsController.ExpansionState
+import com.android.systemui.statusbar.phone.MultiUserSwitchController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.tuner.TunerService
+import com.android.systemui.utils.leaks.FakeTunerService
+import com.android.systemui.utils.leaks.LeakCheckedTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+class FooterActionsControllerTest : LeakCheckedTest() {
+ @Mock
+ private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var activityStarter: ActivityStarter
+ @Mock
+ private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock
+ private lateinit var userInfoController: UserInfoController
+ @Mock
+ private lateinit var qsPanelController: QSPanelController
+ @Mock
+ private lateinit var multiUserSwitchController: MultiUserSwitchController
+ @Mock
+ private lateinit var globalActionsDialog: GlobalActionsDialogLite
+ @Mock
+ private lateinit var uiEventLogger: UiEventLogger
+ @Mock
+ private lateinit var controller: FooterActionsController
+
+ private val metricsLogger: MetricsLogger = FakeMetricsLogger()
+ private lateinit var view: FooterActionsView
+ private val falsingManager: FalsingManagerFake = FalsingManagerFake()
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
+ val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
+
+ view = LayoutInflater.from(context)
+ .inflate(R.layout.footer_actions, null) as FooterActionsView
+
+ controller = FooterActionsController(view, qsPanelController, activityStarter,
+ userManager, userInfoController, multiUserSwitchController,
+ deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
+ globalActionsDialog, uiEventLogger, showPMLiteButton = true,
+ buttonsVisibleState = ExpansionState.EXPANDED)
+ controller.init()
+ controller.onViewAttached()
+ }
+
+ @Test
+ fun testLogPowerMenuClick() {
+ controller.expanded = true
+ falsingManager.setFalseTap(false)
+
+ view.findViewById<View>(R.id.pm_lite).performClick()
+ // Verify clicks are logged
+ verify(uiEventLogger, Mockito.times(1))
+ .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
+ }
+
+ @Test
+ fun testSettings_UserNotSetup() {
+ whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
+ view.findViewById<View>(R.id.settings_button).performClick()
+ // Verify Settings wasn't launched.
+ verify<ActivityStarter>(activityStarter, Mockito.never()).startActivity(any(), anyBoolean())
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 6f7bf3b09daa..8b19c50f915e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -18,16 +18,11 @@ package com.android.systemui.qs;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ClipData;
import android.content.ClipboardManager;
-import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -35,21 +30,8 @@ import android.widget.TextView;
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.FakeMetricsLogger;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.globalactions.GlobalActionsDialogLite;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.MultiUserSwitchController;
-import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.utils.leaks.FakeTunerService;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
@@ -67,14 +49,6 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
@Mock
private QSFooterView mView;
@Mock
- private UserManager mUserManager;
- @Mock
- private ActivityStarter mActivityStarter;
- @Mock
- private DeviceProvisionedController mDeviceProvisionedController;
- @Mock
- private UserInfoController mUserInfoController;
- @Mock
private UserTracker mUserTracker;
@Mock
private QSPanelController mQSPanelController;
@@ -82,36 +56,19 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
private ClipboardManager mClipboardManager;
@Mock
private QuickQSPanelController mQuickQSPanelController;
- private FakeTunerService mFakeTunerService;
- private MetricsLogger mMetricsLogger = new FakeMetricsLogger();
- private FalsingManagerFake mFalsingManager;
-
- @Mock
- private SettingsButton mSettingsButton;
@Mock
private TextView mBuildText;
@Mock
- private View mEdit;
- @Mock
- private MultiUserSwitchController mMultiUserSwitchController;
- @Mock
- private View mPowerMenuLiteView;
- @Mock
- private GlobalActionsDialogLite mGlobalActionsDialog;
- @Mock
- private UiEventLogger mUiEventLogger;
+ private FooterActionsController mFooterActionsController;
private QSFooterViewController mController;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- mFalsingManager = new FalsingManagerFake();
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- mFakeTunerService = (FakeTunerService) Dependency.get(TunerService.class);
-
mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
when(mView.getContext()).thenReturn(mContext);
@@ -119,16 +76,10 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
when(mUserTracker.getUserContext()).thenReturn(mContext);
when(mView.isAttachedToWindow()).thenReturn(true);
- when(mView.findViewById(R.id.settings_button)).thenReturn(mSettingsButton);
when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
- when(mView.findViewById(android.R.id.edit)).thenReturn(mEdit);
- when(mView.findViewById(R.id.pm_lite)).thenReturn(mPowerMenuLiteView);
- mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
- mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
- mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
- mMetricsLogger, mFalsingManager, false, mGlobalActionsDialog,
- mUiEventLogger);
+ mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController,
+ mQuickQSPanelController, mFooterActionsController);
mController.init();
}
@@ -148,40 +99,4 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
verify(mClipboardManager).setPrimaryClip(captor.capture());
assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(text);
}
-
- @Test
- public void testSettings_UserNotSetup() {
- ArgumentCaptor<View.OnClickListener> onClickCaptor =
- ArgumentCaptor.forClass(View.OnClickListener.class);
- verify(mSettingsButton).setOnClickListener(onClickCaptor.capture());
-
- when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
-
- onClickCaptor.getValue().onClick(mSettingsButton);
- // Verify Settings wasn't launched.
- verify(mActivityStarter, never()).startActivity(any(), anyBoolean());
- }
-
- @Test
- public void testLogPowerMenuClick() {
- // Enable power menu button
- mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
- mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
- mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService,
- mMetricsLogger, new FalsingManagerFake(), true, mGlobalActionsDialog,
- mUiEventLogger);
- mController.init();
- mController.setExpanded(true);
- mFalsingManager.setFalseTap(false);
-
- ArgumentCaptor<View.OnClickListener> onClickCaptor =
- ArgumentCaptor.forClass(View.OnClickListener.class);
- verify(mPowerMenuLiteView).setOnClickListener(onClickCaptor.capture());
-
- onClickCaptor.getValue().onClick(mPowerMenuLiteView);
-
- // Verify clicks are logged
- verify(mUiEventLogger, times(1))
- .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 3b78632a7ca3..9e97f801be3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -44,7 +44,6 @@ import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.CollectionUtils;
@@ -53,7 +52,6 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -71,15 +69,12 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -133,16 +128,9 @@ public class QSTileHostTest extends SysuiTestCase {
private Handler mHandler;
private TestableLooper mLooper;
private QSTileHost mQSTileHost;
- MockitoSession mMockingSession = null;
@Before
public void setUp() {
- // TODO(b/174753536): Remove the mMockingSession when
- // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
- mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
- .mockStatic(FeatureFlags.class).startMocking();
- ExtendedMockito.doReturn(false)
- .when(() -> FeatureFlags.isProviderModelSettingEnabled(mContext));
MockitoAnnotations.initMocks(this);
mLooper = TestableLooper.get(this);
mHandler = new Handler(mLooper.getLooper());
@@ -156,13 +144,6 @@ public class QSTileHostTest extends SysuiTestCase {
.thenReturn("");
}
- @After
- public void tearDown() throws Exception {
- if (mMockingSession != null) {
- mMockingSession.finishMocking();
- }
- }
-
private void setUpTileFactory() {
when(mMockState.toString()).thenReturn(MOCK_STATE_STRING);
// Only create this kind of tiles
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
index f8373ffca955..de1d86b08785 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
@@ -19,13 +19,15 @@ package com.android.systemui.qs
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.brightness.BrightnessController
+import com.android.systemui.statusbar.policy.BrightnessMirrorController
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mock
-import org.mockito.Mockito.verify
import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
import org.mockito.Mockito.never
+import org.mockito.Mockito.mock
import org.mockito.junit.MockitoJUnit
@SmallTest
@@ -104,4 +106,13 @@ class QuickQSBrightnessControllerTest : SysuiTestCase() {
verify(brightnessController, never()).registerCallbacks()
}
+
+ @Test
+ fun testMirrorIsSetWhenSliderIsShown() {
+ val mirrorController = mock(BrightnessMirrorController::class.java)
+ quickQSBrightnessController.setMirror(mirrorController)
+ quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
+
+ verify(brightnessController).setMirror(mirrorController)
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 66a006fd4fba..912bea2f4c97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -68,6 +68,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
private lateinit var featureFlags: FeatureFlags
@Mock
private lateinit var quickQsBrightnessController: QuickQSBrightnessController
+ @Mock
+ private lateinit var footerActionsController: FooterActionsController
private lateinit var controller: QuickQSPanelController
@@ -90,7 +92,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
uiEventLogger,
qsLogger,
dumpManager,
- quickQsBrightnessController
+ quickQsBrightnessController,
+ footerActionsController
)
controller.init()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index a6d044a51ac2..4efcc5c3fc73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -45,17 +45,14 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.FeatureFlagUtils;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.InstanceId;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
@@ -64,7 +61,6 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -74,8 +70,6 @@ import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -114,7 +108,6 @@ public class TileQueryHelperTest extends SysuiTestCase {
private PackageManager mPackageManager;
@Mock
private UserTracker mUserTracker;
- @Mock private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
@@ -122,18 +115,10 @@ public class TileQueryHelperTest extends SysuiTestCase {
private TileQueryHelper mTileQueryHelper;
private FakeExecutor mMainExecutor;
private FakeExecutor mBgExecutor;
- MockitoSession mMockingSession = null;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- // TODO(b/174753536): Remove the mMockingSession when
- // FeatureFlagUtils.SETTINGS_PROVIDER_MODEL is removed.
- mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
- .mockStatic(FeatureFlagUtils.class).startMocking();
- ExtendedMockito.doReturn(false).when(() -> FeatureFlagUtils.isEnabled(mContext,
- FeatureFlagUtils.SETTINGS_PROVIDER_MODEL));
-
mContext.setMockPackageManager(mPackageManager);
mState = new QSTile.State();
@@ -153,17 +138,10 @@ public class TileQueryHelperTest extends SysuiTestCase {
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
mTileQueryHelper = new TileQueryHelper(
- mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
+ mContext, mUserTracker, mMainExecutor, mBgExecutor);
mTileQueryHelper.setListener(mListener);
}
- @After
- public void tearDown() throws Exception {
- if (mMockingSession != null) {
- mMockingSession.finishMocking();
- }
- }
-
@Test
public void testIsFinished_falseBeforeQuerying() {
assertFalse(mTileQueryHelper.isFinished());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index 9c3301ef3dc4..2b9082d7e303 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -33,6 +33,8 @@ public class InternetAdapterTest extends SysuiTestCase {
private static final String WIFI_SUMMARY = "Wi-Fi Summary";
@Mock
+ private WifiEntry mInternetWifiEntry;
+ @Mock
private WifiEntry mWifiEntry;
@Mock
private InternetDialogController mInternetDialogController;
@@ -45,41 +47,49 @@ public class InternetAdapterTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mInternetAdapter = new InternetAdapter(mInternetDialogController);
- mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0);
+ when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+ when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+ when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
+ when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true);
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+
+ mInternetAdapter = new InternetAdapter(mInternetDialogController);
+ mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0);
+ when(mInternetDialogController.getInternetWifiEntry()).thenReturn(mInternetWifiEntry);
when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
mViewHolder.mWifiIconInjector = mWifiIconInjector;
}
@Test
- public void getItemCount_withApmOnWifiOnNoDefaultWifi_returnFour() {
+ public void getItemCount_withApmOnWifiOnNoInternetWifi_returnFour() {
+ // The preconditions WiFi ON is already in setUp()
+ when(mInternetDialogController.getInternetWifiEntry()).thenReturn(null);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
assertThat(mInternetAdapter.getItemCount()).isEqualTo(4);
}
@Test
- public void getItemCount_withApmOnWifiOnHasDefaultWifi_returnThree() {
- when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
- when(mInternetDialogController.getDefaultWifiEntry()).thenReturn(mWifiEntry);
+ public void getItemCount_withApmOnWifiOnHasInternetWifi_returnThree() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
assertThat(mInternetAdapter.getItemCount()).isEqualTo(3);
}
@Test
- public void getItemCount_withApmOffWifiOnNoDefaultWifi_returnThree() {
+ public void getItemCount_withApmOffWifiOnNoInternetWifi_returnThree() {
+ // The preconditions WiFi ON is already in setUp()
+ when(mInternetDialogController.getInternetWifiEntry()).thenReturn(null);
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
assertThat(mInternetAdapter.getItemCount()).isEqualTo(3);
}
@Test
- public void getItemCount_withApmOffWifiOnHasDefaultWifi_returnTwo() {
- when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
- when(mInternetDialogController.getDefaultWifiEntry()).thenReturn(mWifiEntry);
+ public void getItemCount_withApmOffWifiOnHasInternetWifi_returnTwo() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
assertThat(mInternetAdapter.getItemCount()).isEqualTo(2);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index cdd6d66c45d2..830fe5af69b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -18,7 +18,6 @@ import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.telephony.ServiceState;
@@ -33,12 +32,13 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.settingslib.Utils;
import com.android.settingslib.wifi.WifiUtils;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -78,14 +78,12 @@ public class InternetDialogControllerTest extends SysuiTestCase {
@Mock
private GlobalSettings mGlobalSettings;
@Mock
- private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private KeyguardStateController mKeyguardStateController;
@Mock
private NetworkController.AccessPointController mAccessPointController;
@Mock
private WifiEntry mConnectedEntry;
@Mock
- private WifiInfo mWifiInfo;
- @Mock
private ServiceState mServiceState;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
@@ -98,15 +96,16 @@ public class InternetDialogControllerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
- when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
when(mConnectedEntry.isDefaultNetwork()).thenReturn(true);
+ when(mConnectedEntry.hasInternetAccess()).thenReturn(true);
mInternetDialogController = new MockInternetDialogController(mContext,
mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController,
mSubscriptionManager, mTelephonyManager, mWifiManager,
mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
- mKeyguardUpdateMonitor, mGlobalSettings);
+ mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController);
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mInternetDialogController.mOnSubscriptionsChangedListener);
mInternetDialogController.onStart(
@@ -173,6 +172,16 @@ public class InternetDialogControllerTest extends SysuiTestCase {
}
@Test
+ public void getSubtitleText_deviceLockedWithWifiOn_returnUnlockToViewNetworks() {
+ mInternetDialogController.setAirplaneModeEnabled(false);
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
+ getResourcesString("unlock_to_view_networks")));
+ }
+
+ @Test
public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
mInternetDialogController.setAirplaneModeEnabled(false);
when(mWifiManager.isWifiEnabled()).thenReturn(true);
@@ -210,53 +219,62 @@ public class InternetDialogControllerTest extends SysuiTestCase {
}
@Test
- public void getDefaultWifiEntry_connectedEntryIsNull_returnNull() {
+ public void getInternetWifiEntry_connectedEntryIsNull_returnNull() {
mInternetDialogController.mConnectedEntry = null;
- assertThat(mInternetDialogController.getDefaultWifiEntry()).isNull();
+ assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
}
@Test
- public void getDefaultWifiEntry_connectedEntryIsNotDefault_returnNull() {
+ public void getInternetWifiEntry_connectedWifiIsNotDefaultNetwork_returnNull() {
when(mConnectedEntry.isDefaultNetwork()).thenReturn(false);
- assertThat(mInternetDialogController.getDefaultWifiEntry()).isNull();
+ assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
+ }
+
+ @Test
+ public void getInternetWifiEntry_connectedWifiHasNotInternetAccess_returnNull() {
+ when(mConnectedEntry.hasInternetAccess()).thenReturn(false);
+
+ assertThat(mInternetDialogController.getInternetWifiEntry()).isNull();
}
@Test
- public void getDefaultWifiEntry_connectedEntryIsDefault_returnConnectedEntry() {
- // The default conditions have been set in setUp().
- // - The connected Wi-Fi entry with the default network condition.
+ public void getInternetWifiEntry_connectedEntryIsInternetWifi_returnConnectedEntry() {
+ // The preconditions have been set in setUp().
+ // - The connected Wi-Fi entry have both default network and internet access conditions.
- assertThat(mInternetDialogController.getDefaultWifiEntry()).isEqualTo(mConnectedEntry);
+ assertThat(mInternetDialogController.getInternetWifiEntry()).isEqualTo(mConnectedEntry);
}
@Test
- public void getDefaultWifiTitle_withNoDefaultEntry_returnEmpty() {
+ public void getInternetWifiTitle_withNoConnectedWifiEntry_returnEmpty() {
mInternetDialogController.mConnectedEntry = null;
- assertThat(mInternetDialogController.getDefaultWifiTitle()).isEmpty();
+ assertThat(mInternetDialogController.getInternetWifiTitle()).isEmpty();
}
@Test
- public void getDefaultWifiTitle_withDefaultEntry_returnTitle() {
+ public void getInternetWifiTitle_withInternetWifi_returnTitle() {
+ // The preconditions have been set in setUp().
+ // - The connected Wi-Fi entry have both default network and internet access conditions.
when(mConnectedEntry.getTitle()).thenReturn(CONNECTED_TITLE);
- assertThat(mInternetDialogController.getDefaultWifiTitle()).isEqualTo(CONNECTED_TITLE);
+ assertThat(mInternetDialogController.getInternetWifiTitle()).isEqualTo(CONNECTED_TITLE);
}
@Test
- public void getDefaultWifiSummary_withNoDefaultEntry_returnEmpty() {
+ public void getInternetWifiSummary_withNoConnectedWifiEntry_returnEmpty() {
mInternetDialogController.mConnectedEntry = null;
- assertThat(mInternetDialogController.getDefaultWifiSummary()).isEmpty();
+ assertThat(mInternetDialogController.getInternetWifiSummary()).isEmpty();
}
@Test
- public void getDefaultWifiSummary_withDefaultEntry_returnSummary() {
+ public void getInternetWifiSummary_withInternetWifi_returnSummary() {
when(mConnectedEntry.getSummary(false)).thenReturn(CONNECTED_SUMMARY);
- assertThat(mInternetDialogController.getDefaultWifiSummary()).isEqualTo(CONNECTED_SUMMARY);
+ assertThat(mInternetDialogController.getInternetWifiSummary()).isEqualTo(CONNECTED_SUMMARY);
}
@Test
@@ -281,15 +299,14 @@ public class InternetDialogControllerTest extends SysuiTestCase {
}
@Test
- public void getWifiConnectedDrawable_withConnectedEntry_returnIntentIconWithColorAccent() {
+ public void getWifiDrawable_withConnectedEntry_returnIntentIconWithCorrectColor() {
final Drawable drawable = mock(Drawable.class);
when(mWifiIconInjector.getIcon(anyBoolean(), anyInt())).thenReturn(drawable);
- mInternetDialogController.getConnectedWifiDrawable(mConnectedEntry);
+ mInternetDialogController.getInternetWifiDrawable(mConnectedEntry);
verify(mWifiIconInjector).getIcon(eq(false), anyInt());
- verify(drawable).setTint(Utils.getColorAttrDefaultColor(mContext,
- com.android.internal.R.attr.colorControlNormal));
+ verify(drawable).setTint(mContext.getColor(R.color.connected_network_primary_color));
}
@Test
@@ -311,6 +328,20 @@ public class InternetDialogControllerTest extends SysuiTestCase {
verify(mActivityStarter).postStartActivityDismissingKeyguard(any(Intent.class), anyInt());
}
+ @Test
+ public void isDeviceLocked_keyguardIsUnlocked_returnFalse() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isDeviceLocked()).isFalse();
+ }
+
+ @Test
+ public void isDeviceLocked_keyguardIsLocked_returnTrue() {
+ when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isDeviceLocked()).isTrue();
+ }
+
private String getResourcesString(String name) {
return mContext.getResources().getString(getResourcesId(name));
}
@@ -331,10 +362,12 @@ public class InternetDialogControllerTest extends SysuiTestCase {
@Nullable WifiManager wifiManager, ConnectivityManager connectivityManager,
@Main Handler handler, @Main Executor mainExecutor,
BroadcastDispatcher broadcastDispatcher,
- KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
+ KeyguardStateController keyguardStateController) {
super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
- broadcastDispatcher, keyguardUpdateMonitor, globalSettings);
+ broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
+ keyguardStateController);
mGlobalSettings = globalSettings;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 856e3a128193..5a018f409a0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -3,6 +3,7 @@ package com.android.systemui.qs.tiles.dialog;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -11,12 +12,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.telephony.TelephonyManager;
@@ -32,7 +28,6 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.wifitrackerlib.WifiEntry;
import org.junit.After;
@@ -53,52 +48,61 @@ import java.util.List;
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class InternetDialogTest extends SysuiTestCase {
- private static final int SUB_ID = 1;
private static final String MOBILE_NETWORK_TITLE = "Mobile Title";
private static final String MOBILE_NETWORK_SUMMARY = "Mobile Summary";
private static final String WIFI_TITLE = "Connected Wi-Fi Title";
private static final String WIFI_SUMMARY = "Connected Wi-Fi Summary";
- private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
-
- private InternetDialogFactory mInternetDialogFactory = mock(InternetDialogFactory.class);
- private InternetAdapter mInternetAdapter = mock(InternetAdapter.class);
- private InternetDialogController mInternetDialogController = mock(
- InternetDialogController.class);
- private InternetDialogController.InternetDialogCallback mCallback =
- mock(InternetDialogController.InternetDialogCallback.class);
- private MockInternetDialog mInternetDialog;
- private WifiReceiver mWifiReceiver = null;
- private WifiManager mMockWifiManager = mock(WifiManager.class);
- private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
@Mock
- private WifiEntry mWifiEntry = mock(WifiEntry.class);
+ private Handler mHandler;
@Mock
- private WifiInfo mWifiInfo;
+ private TelephonyManager mTelephonyManager;
@Mock
- private Handler mHandler;
+ private WifiManager mWifiManager;
+ @Mock
+ private WifiEntry mInternetWifiEntry;
+ @Mock
+ private WifiEntry mWifiEntry;
+ @Mock
+ private InternetAdapter mInternetAdapter;
+ @Mock
+ private InternetDialogController mInternetDialogController;
+
+ private InternetDialog mInternetDialog;
+ private LinearLayout mWifiToggle;
+ private LinearLayout mConnectedWifi;
+ private RecyclerView mWifiList;
+ private LinearLayout mSeeAll;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mInternetDialog = new MockInternetDialog(mContext, mInternetDialogFactory,
- mInternetDialogController, true, true, mUiEventLogger, mHandler);
- mInternetDialog.show();
- doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- when(mMockWifiManager.getConnectionInfo()).thenReturn(mWifiInfo);
- mInternetDialog.setMobileNetworkTitle(MOBILE_NETWORK_TITLE);
- mInternetDialog.setMobileNetworkSummary(MOBILE_NETWORK_SUMMARY);
- mInternetDialog.setConnectedWifiTitle(WIFI_TITLE);
- mInternetDialog.setConnectedWifiSummary(WIFI_SUMMARY);
- mWifiReceiver = new WifiReceiver();
- IntentFilter mIntentFilter = new IntentFilter();
- mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mContext.registerReceiver(mWifiReceiver, mIntentFilter);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
+ when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
+ when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+ when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
+ when(mInternetWifiEntry.hasInternetAccess()).thenReturn(true);
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
+
+ when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE);
+ when(mInternetDialogController.getMobileNetworkSummary())
+ .thenReturn(MOBILE_NETWORK_SUMMARY);
+ when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
+ when(mInternetDialogController.getInternetWifiEntry()).thenReturn(mInternetWifiEntry);
when(mInternetDialogController.getWifiEntryList()).thenReturn(Arrays.asList(mWifiEntry));
+
+ mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
+ mInternetDialogController, true, true, mock(UiEventLogger.class), mHandler);
+ mInternetDialog.mAdapter = mInternetAdapter;
+ mInternetDialog.mConnectedWifiEntry = mInternetWifiEntry;
+ mInternetDialog.show();
+
+ mWifiToggle = mInternetDialog.mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+ mConnectedWifi = mInternetDialog.mDialogView.requireViewById(R.id.wifi_connected_layout);
+ mWifiList = mInternetDialog.mDialogView.requireViewById(R.id.wifi_list_layout);
+ mSeeAll = mInternetDialog.mDialogView.requireViewById(R.id.see_all_layout);
}
@After
@@ -137,46 +141,80 @@ public class InternetDialogTest extends SysuiTestCase {
}
@Test
- public void updateDialog_withWifiOnAndHasConnectedWifi_connectedWifiLayoutVisible() {
+ public void updateDialog_wifiOnAndHasInternetWifi_showConnectedWifi() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
- when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
- when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
- when(mWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
- when(mWifiEntry.isDefaultNetwork()).thenReturn(true);
- mInternetDialog.mConnectedWifiEntry = mWifiEntry;
mInternetDialog.updateDialog();
- final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_connected_layout);
- assertThat(linearLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void updateDialog_withWifiOnAndNoConnectedWifi_connectedWifiLayoutGone() {
+ public void updateDialog_wifiOnAndNoConnectedWifi_hideConnectedWifi() {
+ mInternetDialog.mConnectedWifiEntry = null;
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
+
mInternetDialog.updateDialog();
- final LinearLayout linearLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_connected_layout);
- assertThat(linearLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
}
@Test
- public void updateDialog_withWifiOff_WifiRecycleViewGone() {
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false);
+ public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
+ when(mInternetDialogController.getWifiEntryList()).thenReturn(null);
+
mInternetDialog.updateDialog();
- final RecyclerView view = mInternetDialog.mDialogView.requireViewById(
- R.id.wifi_list_layout);
- assertThat(view.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+ // The preconditions WiFi ON and WiFi entries are already in setUp()
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasInternetWifi_showHighlightWifiToggle() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNotNull();
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasInternetWifi_hideConnectedWifi() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() {
+ // The preconditions WiFi entries are already in setUp()
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
}
@Test
- public void onClickSeeMoreButton_clickSeeMore_verifyLaunchNetworkSetting() {
- final LinearLayout seeAllLayout = mInternetDialog.mDialogView.requireViewById(
- R.id.see_all_layout);
- seeAllLayout.performClick();
+ public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
+ mSeeAll.performClick();
verify(mInternetDialogController).launchNetworkSetting();
}
@@ -184,7 +222,18 @@ public class InternetDialogTest extends SysuiTestCase {
@Test
public void showProgressBar_wifiDisabled_hideProgressBar() {
Mockito.reset(mHandler);
- when(mMockWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+
+ mInternetDialog.showProgressBar();
+
+ assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
+ verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong());
+ }
+
+ @Test
+ public void showProgressBar_deviceLocked_hideProgressBar() {
+ Mockito.reset(mHandler);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
mInternetDialog.showProgressBar();
@@ -195,10 +244,10 @@ public class InternetDialogTest extends SysuiTestCase {
@Test
public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
Mockito.reset(mHandler);
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
List<ScanResult> wifiScanResults = mock(ArrayList.class);
when(wifiScanResults.size()).thenReturn(1);
- when(mMockWifiManager.getScanResults()).thenReturn(wifiScanResults);
+ when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
mInternetDialog.showProgressBar();
@@ -217,10 +266,10 @@ public class InternetDialogTest extends SysuiTestCase {
@Test
public void showProgressBar_wifiEnabledWithoutWifiScanResults_showProgressBarThenHideSearch() {
Mockito.reset(mHandler);
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
+ when(mWifiManager.isWifiEnabled()).thenReturn(true);
List<ScanResult> wifiScanResults = mock(ArrayList.class);
when(wifiScanResults.size()).thenReturn(0);
- when(mMockWifiManager.getScanResults()).thenReturn(wifiScanResults);
+ when(mWifiManager.getScanResults()).thenReturn(wifiScanResults);
mInternetDialog.showProgressBar();
@@ -236,78 +285,4 @@ public class InternetDialogTest extends SysuiTestCase {
assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
assertThat(mInternetDialog.mIsSearchingHidden).isTrue();
}
-
- private class MockInternetDialog extends InternetDialog {
-
- private String mMobileNetworkTitle;
- private String mMobileNetworkSummary;
- private String mConnectedWifiTitle;
- private String mConnectedWifiSummary;
-
- MockInternetDialog(Context context, InternetDialogFactory internetDialogFactory,
- InternetDialogController internetDialogController, boolean canConfigMobileData,
- boolean aboveStatusBar, UiEventLogger uiEventLogger, @Main Handler handler) {
- super(context, internetDialogFactory, internetDialogController, canConfigMobileData,
- aboveStatusBar, uiEventLogger, handler);
- mAdapter = mInternetAdapter;
- mWifiManager = mMockWifiManager;
- }
-
- @Override
- String getMobileNetworkTitle() {
- return mMobileNetworkTitle;
- }
-
- @Override
- String getMobileNetworkSummary() {
- return mMobileNetworkSummary;
- }
-
- void setMobileNetworkTitle(String title) {
- mMobileNetworkTitle = title;
- }
-
- void setMobileNetworkSummary(String summary) {
- mMobileNetworkSummary = summary;
- }
-
- @Override
- String getConnectedWifiTitle() {
- return mConnectedWifiTitle;
- }
-
- @Override
- String getConnectedWifiSummary() {
- return mConnectedWifiSummary;
- }
-
- void setConnectedWifiTitle(String title) {
- mConnectedWifiTitle = title;
- }
-
- void setConnectedWifiSummary(String summary) {
- mConnectedWifiSummary = summary;
- }
-
- @Override
- public void onWifiStateReceived(Context context, Intent intent) {
- setMobileNetworkTitle(MOBILE_NETWORK_TITLE);
- setMobileNetworkSummary(MOBILE_NETWORK_SUMMARY);
- }
- }
-
- private class WifiReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- return;
- }
-
- if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- mInternetDialog.updateDialog();
- }
- }
- }
-
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
index e0187bdf6ada..bceb92894609 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
@@ -108,15 +108,6 @@ class BrightnessSliderTest : SysuiTestCase() {
}
@Test
- fun testNullMirrorControllerNotTrackingTouch() {
- mController.setMirrorControllerAndMirror(null)
-
- verify(brightnessSliderView, never()).max
- verify(brightnessSliderView, never()).value
- verify(brightnessSliderView).setOnDispatchTouchEventListener(isNull())
- }
-
- @Test
fun testNullMirrorNotTrackingTouch() {
whenever(mirrorController.toggleSlider).thenReturn(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
new file mode 100644
index 000000000000..a9c6a5353350
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 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.shared.animation
+
+import android.graphics.Point
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.view.Display
+import android.view.Surface.ROTATION_0
+import android.view.Surface.ROTATION_90
+import android.view.View
+import android.view.WindowManager
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var windowManager: WindowManager
+
+ @get:Rule
+ val mockito = MockitoJUnit.rule()
+
+ private lateinit var animator: UnfoldMoveFromCenterAnimator
+
+ @Before
+ fun before() {
+ animator = UnfoldMoveFromCenterAnimator(windowManager)
+ }
+
+ @Test
+ fun testRegisterViewOnTheLeftOfVerticalFold_halfProgress_viewTranslatedToTheRight() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+
+ animator.onTransitionProgress(0.5f)
+
+ // Positive translationX -> translated to the right
+ assertThat(view.translationX).isWithin(0.1f).of(3.75f)
+ }
+
+ @Test
+ fun testRegisterViewOnTheLeftOfVerticalFold_zeroProgress_viewTranslatedToTheRight() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+
+ animator.onTransitionProgress(0f)
+
+ // Positive translationX -> translated to the right
+ assertThat(view.translationX).isWithin(0.1f).of(7.5f)
+ }
+
+ @Test
+ fun testRegisterViewOnTheLeftOfVerticalFold_fullProgress_viewTranslatedToTheOriginalPosition() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+
+ animator.onTransitionProgress(1f)
+
+ assertThat(view.translationX).isEqualTo(0f)
+ }
+
+ @Test
+ fun testRegisterViewAndUnregister_halfProgress_viewIsNotUpdated() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+ animator.clearRegisteredViews()
+
+ animator.onTransitionProgress(0.5f)
+
+ assertThat(view.translationX).isEqualTo(0f)
+ }
+
+ @Test
+ fun testRegisterViewUpdateProgressAndUnregister_halfProgress_viewIsNotUpdated() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+ animator.onTransitionProgress(0.2f)
+ animator.clearRegisteredViews()
+
+ animator.onTransitionProgress(0.5f)
+
+ assertThat(view.translationX).isEqualTo(0f)
+ }
+
+ @Test
+ fun testRegisterViewOnTheTopOfHorizontalFold_halfProgress_viewTranslatedToTheBottom() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_90)
+ val view = createView(y = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+
+ animator.onTransitionProgress(0.5f)
+
+ // Positive translationY -> translated to the bottom
+ assertThat(view.translationY).isWithin(0.1f).of(3.75f)
+ }
+
+ private fun createView(
+ x: Int = 0,
+ y: Int = 0,
+ width: Int = 10,
+ height: Int = 10,
+ translationX: Float = 0f,
+ translationY: Float = 0f
+ ): View {
+ val view = spy(View(context))
+ doAnswer {
+ val location = (it.arguments[0] as IntArray)
+ location[0] = x
+ location[1] = y
+ Unit
+ }.`when`(view).getLocationOnScreen(any())
+
+ whenever(view.width).thenReturn(width)
+ whenever(view.height).thenReturn(height)
+
+ return view.apply {
+ setTranslationX(translationX)
+ setTranslationY(translationY)
+ }
+ }
+
+ private fun givenScreen(width: Int = 100,
+ height: Int = 100,
+ rotation: Int = ROTATION_0) {
+ val display = mock(Display::class.java)
+ whenever(display.getSize(any())).thenAnswer {
+ val size = (it.arguments[0] as Point)
+ size.set(width, height)
+ Unit
+ }
+ whenever(display.rotation).thenReturn(rotation)
+ whenever(windowManager.defaultDisplay).thenReturn(display)
+
+ animator.updateDisplayProperties()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index d23a9ce26def..7c045c1f2894 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -184,8 +184,9 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() {
@Test
fun setQsPanelExpansion_appliesBlur() {
notificationShadeDepthController.qsPanelExpansion = 1f
+ notificationShadeDepthController.onPanelExpansionChanged(0.5f, tracking = false)
notificationShadeDepthController.updateBlurCallback.doFrame(0)
- verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
+ verify(blurUtils).applyBlur(any(), eq(maxBlur / 2), eq(false))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index a2bb0aff48e3..756e9844e6c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -389,7 +389,6 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
verify(userTracker).removeCallback(userListener)
verify(contentResolver).unregisterContentObserver(settingsObserver)
verify(configurationController).removeCallback(configChangeListener)
- verify(statusBarStateController).removeCallback(statusBarStateListener)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
new file mode 100644
index 000000000000..24a0ad3de196
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static android.view.DragEvent.ACTION_DRAG_STARTED;
+
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.DragEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class ExpandableNotificationRowDragControllerTest extends SysuiTestCase {
+
+ private ExpandableNotificationRow mRow;
+ private ExpandableNotificationRow mGroupRow;
+ private ExpandableNotificationRowDragController mController;
+ private NotificationTestHelper mNotificationTestHelper;
+
+ private NotificationGutsManager mGutsManager = mock(NotificationGutsManager.class);
+ private HeadsUpManager mHeadsUpManager = mock(HeadsUpManager.class);
+ private NotificationMenuRow mMenuRow = mock(NotificationMenuRow.class);
+ private NotificationMenuRowPlugin.MenuItem mMenuItem =
+ mock(NotificationMenuRowPlugin.MenuItem.class);
+
+ @Before
+ public void setUp() throws Exception {
+ allowTestableLooperAsMainThread();
+
+ mDependency.injectMockDependency(ShadeController.class);
+
+ mNotificationTestHelper = new NotificationTestHelper(
+ mContext,
+ mDependency,
+ TestableLooper.get(this));
+ mRow = mNotificationTestHelper.createRow();
+ mGroupRow = mNotificationTestHelper.createGroup(4);
+ when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
+
+ mController = new ExpandableNotificationRowDragController(mContext, mHeadsUpManager);
+ }
+
+ @Test
+ public void testDoStartDragHeadsUpNotif_startDragAndDrop() throws Exception {
+ ExpandableNotificationRowDragController controller = createSpyController();
+ mRow.setDragController(controller);
+ mRow.setHeadsUp(true);
+ mRow.setPinned(true);
+
+ mRow.doLongClickCallback(0, 0);
+ mRow.doDragCallback(0, 0);
+ verify(controller).startDragAndDrop(mRow);
+
+ // Simulate the drag start
+ mRow.dispatchDragEvent(DragEvent.obtain(ACTION_DRAG_STARTED, 0, 0, 0, 0, null, null, null,
+ null, null, false));
+ verify(mHeadsUpManager, times(1)).releaseAllImmediately();
+ }
+
+ @Test
+ public void testDoStartDragNotif() throws Exception {
+ ExpandableNotificationRowDragController controller = createSpyController();
+ mRow.setDragController(controller);
+
+ mDependency.get(ShadeController.class).instantExpandNotificationsPanel();
+ mRow.doDragCallback(0, 0);
+ verify(controller).startDragAndDrop(mRow);
+
+ // Simulate the drag start
+ mRow.dispatchDragEvent(DragEvent.obtain(ACTION_DRAG_STARTED, 0, 0, 0, 0, null, null, null,
+ null, null, false));
+ verify(mDependency.get(ShadeController.class)).animateCollapsePanels(0, true);
+ }
+
+ private ExpandableNotificationRowDragController createSpyController() {
+ return spy(mController);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 0854b9377eba..4562e4f5954d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -265,7 +265,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
new FalsingManagerFake(),
new FalsingCollectorFake(),
mPeopleNotificationIdentifier,
- Optional.of(mock(BubblesManager.class))
+ Optional.of(mock(BubblesManager.class)),
+ mock(ExpandableNotificationRowDragController.class)
));
when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 6e0cbd9ecfa3..bca1227b7d35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -202,6 +202,5 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
verify(mPanelView).removeTrackingHeadsUpListener(any());
verify(mPanelView).setHeadsUpAppearanceController(isNull());
verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
- verify(mStackScrollerController).removeOnLayoutChangeListener(any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 690b8415762d..2e76bd76e823 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -38,35 +38,27 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
private static final float ZERO_DRAG = 0.f;
private static final float OPAQUE = 1.f;
private static final float TRANSPARENT = 0.f;
- private static final boolean HAS_CUSTOM_CLOCK = false;
- private static final boolean HAS_VISIBLE_NOTIFS = false;
private KeyguardClockPositionAlgorithm mClockPositionAlgorithm;
private KeyguardClockPositionAlgorithm.Result mClockPosition;
- private int mNotificationStackHeight;
private float mPanelExpansion;
private int mKeyguardStatusHeight;
private float mDark;
- private boolean mHasCustomClock;
- private boolean mHasVisibleNotifs;
private float mQsExpansion;
- private int mCutoutTopInset = 0; // in pixels
+ private int mCutoutTopInsetPx = 0;
+ private int mSplitShadeSmartspaceHeightPx = 0;
private boolean mIsSplitShade = false;
@Before
public void setUp() {
mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
mClockPosition = new KeyguardClockPositionAlgorithm.Result();
-
- mHasCustomClock = HAS_CUSTOM_CLOCK;
- mHasVisibleNotifs = HAS_VISIBLE_NOTIFS;
}
@Test
public void clockPositionTopOfScreenOnAOD() {
- // GIVEN on AOD and both stack scroll and clock have 0 height
+ // GIVEN on AOD and clock has 0 height
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
@@ -79,11 +71,10 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
@Test
public void clockPositionBelowCutout() {
- // GIVEN on AOD and both stack scroll and clock have 0 height
+ // GIVEN on AOD and clock has 0 height
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
- mCutoutTopInset = 300;
+ mCutoutTopInsetPx = 300;
// WHEN the clock position algorithm is run
positionClock();
// THEN the clock Y position is below the cutout
@@ -97,7 +88,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void clockPositionAdjustsForKeyguardStatusOnAOD() {
// GIVEN on AOD with a clock of height 100
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = 100;
// WHEN the clock position algorithm is run
positionClock();
@@ -112,7 +102,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void clockPositionLargeClockOnAOD() {
// GIVEN on AOD with a full screen clock
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = SCREEN_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
@@ -125,9 +114,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
@Test
public void clockPositionTopOfScreenOnLockScreen() {
- // GIVEN on lock screen with stack scroll and clock of 0 height
+ // GIVEN on lock screen with clock of 0 height
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
@@ -138,24 +126,9 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
}
@Test
- public void clockPositionWithStackScrollExpandOnLockScreen() {
- // GIVEN on lock screen with stack scroll of height 500
- givenLockScreen();
- mNotificationStackHeight = 500;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the clock position algorithm is run
- positionClock();
- // THEN the clock Y position stays to the top
- assertThat(mClockPosition.clockY).isEqualTo(0);
- // AND the clock is positioned on the left.
- assertThat(mClockPosition.clockX).isEqualTo(0);
- }
-
- @Test
public void clockPositionWithPartialDragOnLockScreen() {
// GIVEN dragging up on lock screen
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
mPanelExpansion = 0.5f;
// WHEN the clock position algorithm is run
@@ -171,7 +144,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void clockPositionWithFullDragOnLockScreen() {
// GIVEN the lock screen is dragged up
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
mPanelExpansion = 0.f;
// WHEN the clock position algorithm is run
@@ -184,7 +156,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void largeClockOnLockScreenIsTransparent() {
// GIVEN on lock screen with a full screen clock
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = SCREEN_HEIGHT;
// WHEN the clock position algorithm is run
positionClock();
@@ -194,9 +165,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
@Test
public void notifPositionTopOfScreenOnAOD() {
- // GIVEN on AOD and both stack scroll and clock have 0 height
+ // GIVEN on AOD and clock has 0 height
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the position algorithm is run
positionClock();
@@ -208,7 +178,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void notifPositionIndependentOfKeyguardStatusHeightOnAOD() {
// GIVEN on AOD and clock has a nonzero height
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = 100;
// WHEN the position algorithm is run
positionClock();
@@ -220,7 +189,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void notifPositionWithLargeClockOnAOD() {
// GIVEN on AOD and clock has a nonzero height
givenAOD();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = SCREEN_HEIGHT;
// WHEN the position algorithm is run
positionClock();
@@ -230,9 +198,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
@Test
public void notifPositionMiddleOfScreenOnLockScreen() {
- // GIVEN on lock screen and both stack scroll and clock have 0 height
+ // GIVEN on lock screen and clock has 0 height
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
// WHEN the position algorithm is run
positionClock();
@@ -241,58 +208,42 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
}
@Test
- public void notifPositionAdjustsForStackHeightOnLockScreen() {
- // GIVEN on lock screen and stack scroller has a nonzero height
- givenLockScreen();
- mNotificationStackHeight = 500;
- mKeyguardStatusHeight = EMPTY_HEIGHT;
- // WHEN the position algorithm is run
- positionClock();
- // THEN the notif padding adjusts for keyguard status height
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
- }
-
- @Test
public void notifPositionAdjustsForClockHeightOnLockScreen() {
// GIVEN on lock screen and stack scroller has a nonzero height
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = 200;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding adjusts for both clock and notif stack.
+
assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
}
@Test
- public void notifPositionAdjustsForStackHeightAndClockHeightOnLockScreen() {
- // GIVEN on lock screen and stack scroller has a nonzero height
+ public void notifPositionAlignedWithClockInSplitShadeMode() {
givenLockScreen();
- mNotificationStackHeight = 500;
+ mIsSplitShade = true;
mKeyguardStatusHeight = 200;
// WHEN the position algorithm is run
positionClock();
- // THEN the notifs are placed below the statusview
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
+ // THEN the notif padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
@Test
- public void notifPositionAlignedWithClockInSplitShadeMode() {
- // GIVEN on lock screen and split shade mode
+ public void notifPositionAdjustedBySmartspaceHeightInSplitShadeMode() {
givenLockScreen();
+ mSplitShadeSmartspaceHeightPx = 200;
mIsSplitShade = true;
- mHasCustomClock = true;
// WHEN the position algorithm is run
positionClock();
- // THEN the notif padding DOESN'T adjust for keyguard status height.
- assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
+
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
}
@Test
public void notifPositionWithLargeClockOnLockScreen() {
// GIVEN on lock screen and clock has a nonzero height
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = SCREEN_HEIGHT;
// WHEN the position algorithm is run
positionClock();
@@ -304,7 +255,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void notifPositionWithFullDragOnLockScreen() {
// GIVEN the lock screen is dragged up
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = EMPTY_HEIGHT;
mPanelExpansion = 0.f;
// WHEN the clock position algorithm is run
@@ -317,19 +267,18 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
public void notifPositionWithLargeClockFullDragOnLockScreen() {
// GIVEN the lock screen is dragged up and a full screen clock
givenLockScreen();
- mNotificationStackHeight = EMPTY_HEIGHT;
mKeyguardStatusHeight = SCREEN_HEIGHT;
mPanelExpansion = 0.f;
// WHEN the clock position algorithm is run
positionClock();
- // THEN the notif padding is zero.
+
assertThat(mClockPosition.stackScrollerPadding).isEqualTo(
(int) (mKeyguardStatusHeight * .667f));
}
@Test
public void clockHiddenWhenQsIsExpanded() {
- // GIVEN on the lock screen with a custom clock and visible notifications
+ // GIVEN on the lock screen with visible notifications
givenLockScreen();
mQsExpansion = 1;
// WHEN the clock position algorithm is run
@@ -349,12 +298,12 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
}
private void positionClock() {
- mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
- mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight,
+ mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT,
+ mPanelExpansion, mKeyguardStatusHeight,
0 /* userSwitchHeight */, 0 /* userSwitchPreferredY */,
- mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
+ mDark, ZERO_DRAG, false /* bypassEnabled */,
0 /* unlockedStackScrollerPadding */, mQsExpansion,
- mCutoutTopInset, mIsSplitShade);
+ mCutoutTopInsetPx, mSplitShadeSmartspaceHeightPx, mIsSplitShade);
mClockPositionAlgorithm.run(mClockPosition);
}
}
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 8f6a2974eeb5..11a822ccb61f 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,6 +63,7 @@ import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
@@ -119,6 +120,7 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.notification.ConversationNotificationManager;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -326,6 +328,10 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private RecordingController mRecordingController;
@Mock
private ControlsComponent mControlsComponent;
+ @Mock
+ private LockscreenSmartspaceController mLockscreenSmartspaceController;
+ @Mock
+ private FrameLayout mSplitShadeSmartspaceContainer;
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -376,6 +382,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
when(mView.findViewById(R.id.keyguard_status_view))
.thenReturn(mock(KeyguardStatusView.class));
+ when(mView.findViewById(R.id.split_shade_smartspace_container))
+ .thenReturn(mSplitShadeSmartspaceContainer);
mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
@@ -479,6 +487,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
new FakeExecutor(new FakeSystemClock()),
mSecureSettings,
mSplitShadeHeaderController,
+ mLockscreenSmartspaceController,
mUnlockedScreenOffAnimationController,
mNotificationRemoteInputManager,
mControlsComponent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
new file mode 100644
index 000000000000..50cea073c701
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.phone
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.CommandQueue
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class PhoneStatusBarViewControllerTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var commandQueue: CommandQueue
+
+ private lateinit var view: PhoneStatusBarView
+ private lateinit var controller: PhoneStatusBarViewController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ view = PhoneStatusBarView(mContext, null)
+ controller = PhoneStatusBarViewController(view, commandQueue)
+ }
+
+ @Test
+ fun constructor_setsPanelEnabledProviderOnView() {
+ var providerUsed = false
+ `when`(commandQueue.panelsEnabled()).then {
+ providerUsed = true
+ true
+ }
+
+ // If the constructor correctly set a [PanelEnabledProvider], then it should be used
+ // when [PhoneStatusBarView.panelEnabled] is called.
+ view.panelEnabled()
+
+ assertThat(providerUsed).isTrue()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
new file mode 100644
index 000000000000..49ab6ebbde93
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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.phone
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+
+@SmallTest
+class PhoneStatusBarViewTest : SysuiTestCase() {
+
+ private lateinit var view: PhoneStatusBarView
+
+ @Before
+ fun setUp() {
+ view = PhoneStatusBarView(mContext, null)
+ }
+
+ @Test
+ fun panelEnabled_providerReturnsTrue_returnsTrue() {
+ view.setPanelEnabledProvider { true }
+
+ assertThat(view.panelEnabled()).isTrue()
+ }
+
+ @Test
+ fun panelEnabled_providerReturnsFalse_returnsFalse() {
+ view.setPanelEnabledProvider { false }
+
+ assertThat(view.panelEnabled()).isFalse()
+ }
+
+ @Test
+ fun panelEnabled_noProvider_noCrash() {
+ view.panelEnabled()
+ // No assert needed, just testing no crash
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index c06a9ae92140..e4f6e13db607 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -138,6 +138,7 @@ import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
@@ -262,6 +263,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private IWallpaperManager mIWallpaperManager;
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ @Mock private TunerService mTunerService;
@Mock private StartingSurface mStartingSurface;
private ShadeController mShadeController;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -425,7 +427,8 @@ public class StatusBarTest extends SysuiTestCase {
mKeyguardUnlockAnimationController,
mWallpaperManager,
mUnlockedScreenOffAnimationController,
- Optional.of(mStartingSurface));
+ Optional.of(mStartingSurface),
+ mTunerService);
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
any(NotificationPanelViewController.class), any(BiometricUnlockController.class),
any(ViewGroup.class), any(KeyguardBypassController.class)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 31fa04d63d13..4476fd879e24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -184,6 +184,21 @@ class OngoingCallControllerTest : SysuiTestCase() {
.isGreaterThan(0)
}
+ /** Regression test for b/194731244. */
+ @Test
+ fun onEntryUpdated_calledManyTimes_uidObserverUnregisteredManyTimes() {
+ val numCalls = 4
+
+ for (i in 0 until numCalls) {
+ // Re-create the notification each time so that it's considered a different object and
+ // observers will get re-registered (and hopefully unregistered).
+ notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
+ }
+
+ // There should be 1 observer still registered, so we should unregister n-1 times.
+ verify(mockIActivityManager, times(numCalls - 1)).unregisterUidObserver(any())
+ }
+
/**
* If a call notification is never added before #onEntryRemoved is called, then the listener
* should never be notified.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index c365ef2002ac..b1b9ff457286 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy
import android.app.IActivityTaskManager
+import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
@@ -63,6 +64,8 @@ import org.mockito.MockitoAnnotations
@SmallTest
class UserSwitcherControllerTest : SysuiTestCase() {
@Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var handler: Handler
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var userManager: UserManager
@@ -107,6 +110,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
userManager,
userTracker,
keyguardStateController,
+ deviceProvisionedController,
+ devicePolicyManager,
handler,
activityStarter,
broadcastDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java
index cc2afe2f7b8a..a34c5986f36c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.util.sensors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -60,7 +61,8 @@ public class ProximitySensorDualTest extends SysuiTestCase {
}
@Test
- public void testPrimaryBelowDoesNotInvokeSecondary() {
+ public void testInitiallyAbovePrimary() {
+
TestableListener listener = new TestableListener();
mProximitySensor.register(listener);
@@ -70,12 +72,71 @@ public class ProximitySensorDualTest extends SysuiTestCase {
assertNull(listener.mLastEvent);
assertEquals(0, listener.mCallCount);
- // Trigger primary sensor. Our secondary sensor is not registered.
mThresholdSensorPrimary.triggerEvent(false, 0);
+ assertNotNull(listener.mLastEvent);
+ assertFalse(listener.mLastEvent.getBelow());
+ assertEquals(1, listener.mCallCount);
+ }
+
+ @Test
+ public void testInitiallyBelowPrimaryAboveSecondary() {
+
+ TestableListener listener = new TestableListener();
+
+ mProximitySensor.register(listener);
+ assertTrue(mProximitySensor.isRegistered());
assertFalse(mThresholdSensorPrimary.isPaused());
assertTrue(mThresholdSensorSecondary.isPaused());
assertNull(listener.mLastEvent);
assertEquals(0, listener.mCallCount);
+
+ mThresholdSensorPrimary.triggerEvent(true, 0);
+ assertNull(listener.mLastEvent);
+ assertEquals(0, listener.mCallCount);
+
+ mThresholdSensorSecondary.triggerEvent(false, 1);
+ assertNotNull(listener.mLastEvent);
+ assertFalse(listener.mLastEvent.getBelow());
+ assertEquals(1, listener.mCallCount);
+ }
+
+ @Test
+ public void testInitiallyBelowPrimaryAndSecondary() {
+
+ TestableListener listener = new TestableListener();
+
+ mProximitySensor.register(listener);
+ assertTrue(mProximitySensor.isRegistered());
+ assertFalse(mThresholdSensorPrimary.isPaused());
+ assertTrue(mThresholdSensorSecondary.isPaused());
+ assertNull(listener.mLastEvent);
+ assertEquals(0, listener.mCallCount);
+
+ mThresholdSensorPrimary.triggerEvent(true, 0);
+ assertNull(listener.mLastEvent);
+ assertEquals(0, listener.mCallCount);
+
+ mThresholdSensorSecondary.triggerEvent(true, 1);
+ assertNotNull(listener.mLastEvent);
+ assertTrue(listener.mLastEvent.getBelow());
+ assertEquals(1, listener.mCallCount);
+ }
+
+ @Test
+ public void testPrimaryBelowDoesNotInvokeSecondary() {
+ TestableListener listener = new TestableListener();
+
+ mProximitySensor.register(listener);
+ assertTrue(mProximitySensor.isRegistered());
+ assertFalse(mThresholdSensorPrimary.isPaused());
+ assertTrue(mThresholdSensorSecondary.isPaused());
+ assertNull(listener.mLastEvent);
+ assertEquals(0, listener.mCallCount);
+
+ // Trigger primary sensor. Our secondary sensor is not registered.
+ mThresholdSensorPrimary.triggerEvent(false, 0);
+ assertFalse(mThresholdSensorPrimary.isPaused());
+ assertTrue(mThresholdSensorSecondary.isPaused());
}
@Test
diff --git a/packages/VpnDialogs/res/values-eu/strings.xml b/packages/VpnDialogs/res/values-eu/strings.xml
index 9fc16e27ca7f..a27a66a86c9d 100644
--- a/packages/VpnDialogs/res/values-eu/strings.xml
+++ b/packages/VpnDialogs/res/values-eu/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"Konektatzeko eskaera"</string>
- <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. &lt;br /&gt; &lt;br /&gt; VPN konexioa aktibo dagoenean, &lt;img src=vpn_icon /&gt; agertuko da pantailaren goialdean."</string>
+ <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. &lt;br /&gt; &lt;br /&gt; VPN bidezko konexioa aktibo dagoenean, &lt;img src=vpn_icon /&gt; agertuko da pantailaren goialdean."</string>
<string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexio bat konfiguratu nahi du sareko trafikoa gainbegiratzeko. Onartu soilik iturburuaz fidatzen bazara. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; agertzen da pantailan, VPNa aktibo dagoenean."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN sarera konektatuta dago"</string>
<string name="session" msgid="6470628549473641030">"Saioa:"</string>
diff --git a/services/Android.bp b/services/Android.bp
index a2d6beb41d29..82d9b3e51c2d 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -68,7 +68,6 @@ filegroup {
":services.texttospeech-sources",
":services.usage-sources",
":services.usb-sources",
- ":services.uwb-sources",
":services.voiceinteraction-sources",
":services.wifi-sources",
],
@@ -122,7 +121,6 @@ java_library {
"services.texttospeech",
"services.usage",
"services.usb",
- "services.uwb",
"services.voiceinteraction",
"services.wifi",
"service-blobstore",
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index cd332a68fa88..4946ad442b0a 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -125,7 +125,7 @@ public class AppPredictionPerUserService extends
// connect with remote AppPredictionService instead for dark launch
usesPeopleService = false;
}
- final boolean serviceExists = resolveService(sessionId, false,
+ final boolean serviceExists = resolveService(sessionId, true,
usesPeopleService, s -> s.onCreatePredictionSession(context, sessionId));
if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
final AppPredictionSessionInfo sessionInfo = new AppPredictionSessionInfo(
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 282b868a4ecb..689890f3ce77 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -92,6 +92,7 @@ java_library_static {
name: "services.core.unboosted",
defaults: ["platform_service_defaults"],
srcs: [
+ ":android.hardware.biometrics.face-V1-java-source",
":statslog-art-java-gen",
":services.core-sources",
":services.core.protologsrc",
@@ -116,6 +117,7 @@ java_library_static {
libs: [
"services.net",
+ "android.hardware.common-V2-java",
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V1-java",
"android.hardware.power-V1-java",
@@ -145,7 +147,6 @@ java_library_static {
"android.hardware.light-V1-java",
"android.hardware.tv.cec-V1.1-java",
"android.hardware.weaver-V1.0-java",
- "android.hardware.biometrics.face-V1-java",
"android.hardware.biometrics.face-V1.0-java",
"android.hardware.biometrics.fingerprint-V2.3-java",
"android.hardware.biometrics.fingerprint-V1-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 0621d0f385f5..e390ae28a092 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -353,6 +353,12 @@ public abstract class PackageManagerInternal implements PackageSettingsSnapshotP
/**
+ * Retrieve all receivers that can handle a broadcast of the given intent.
+ */
+ public abstract List<ResolveInfo> queryIntentReceivers(Intent intent,
+ String resolvedType, int flags, int filterCallingUid, int userId);
+
+ /**
* Retrieve all services that can be performed for the given intent.
* @see PackageManager#queryIntentServices(Intent, int)
*/
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 047aae772f44..aae1cc024ede 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -147,6 +147,47 @@ public abstract class IntentResolver<F, R extends Object> {
return true;
}
+ /**
+ * Returns whether an intent matches the IntentFilter with a pre-resolved type.
+ */
+ public static boolean intentMatchesFilter(
+ IntentFilter filter, Intent intent, String resolvedType) {
+ final boolean debug = localLOGV
+ || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
+
+ final Printer logPrinter = debug
+ ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM) : null;
+
+ if (debug) {
+ Slog.v(TAG, "Intent: " + intent);
+ Slog.v(TAG, "Matching against filter: " + filter);
+ filter.dump(logPrinter, " ");
+ }
+
+ final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
+ intent.getData(), intent.getCategories(), TAG);
+
+ if (match >= 0) {
+ if (debug) {
+ Slog.v(TAG, "Filter matched! match=0x" + Integer.toHexString(match));
+ }
+ return true;
+ } else {
+ if (debug) {
+ final String reason;
+ switch (match) {
+ case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
+ case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
+ case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
+ case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
+ default: reason = "unknown reason"; break;
+ }
+ Slog.v(TAG, "Filter did not match: " + reason);
+ }
+ return false;
+ }
+ }
+
private ArrayList<F> collectFilters(F[] array, IntentFilter matching) {
ArrayList<F> res = null;
if (array != null) {
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 7d7a41068bb1..d5ea5bf0ba88 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -413,6 +413,12 @@ public final class SensorPrivacyService extends SystemService {
return;
}
+ if (uid == Process.SYSTEM_UID) {
+ // If the system uid is being blamed for sensor access, the ui must be shown
+ // explicitly using SensorPrivacyManager#showSensorUseDialog
+ return;
+ }
+
synchronized (mLock) {
if (mSuppressReminders.containsKey(new Pair<>(sensor, user))) {
Log.d(TAG,
@@ -421,11 +427,6 @@ public final class SensorPrivacyService extends SystemService {
}
}
- if (uid == Process.SYSTEM_UID) {
- enqueueSensorUseReminderDialogAsync(-1, user, packageName, sensor);
- return;
- }
-
// TODO: Handle reminders with multiple sensors
// - If we have a likely activity that triggered the sensor use overlay a dialog over
@@ -1241,6 +1242,18 @@ public final class SensorPrivacyService extends SystemService {
}
}
+ @Override
+ public void showSensorUseDialog(int sensor) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Can only be called by the system uid");
+ }
+ if (!isIndividualSensorPrivacyEnabled(mCurrentUser, sensor)) {
+ return;
+ }
+ enqueueSensorUseReminderDialogAsync(
+ -1, UserHandle.of(mCurrentUser), "android", sensor);
+ }
+
private void userSwitching(int from, int to) {
boolean micState;
boolean camState;
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 85eadf5a5137..10071309bc0d 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -1168,8 +1168,8 @@ final class UiModeManagerService extends SystemService {
private boolean doesPackageHaveCallingUid(@NonNull String packageName) {
try {
- return getContext().getPackageManager().getPackageUid(packageName, 0)
- == mInjector.getCallingUid();
+ return getContext().getPackageManager().getPackageUidAsUser(packageName,
+ UserHandle.getCallingUserId()) == mInjector.getCallingUid();
} catch (PackageManager.NameNotFoundException e) {
return false;
}
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index d483f1863258..a03425c0bb75 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -26,6 +26,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.IVpnManager;
@@ -312,6 +314,26 @@ public class VpnManagerService extends IVpnManager.Stub {
}
}
+ // TODO : Move to a static lib to factorize with Vpn.java
+ private int getAppUid(final String app, final int userId) {
+ final PackageManager pm = mContext.getPackageManager();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return pm.getPackageUidAsUser(app, userId);
+ } catch (NameNotFoundException e) {
+ return -1;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private void verifyCallingUidAndPackage(String packageName, int callingUid) {
+ final int userId = UserHandle.getUserId(callingUid);
+ if (getAppUid(packageName, userId) != callingUid) {
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
+ }
+ }
+
/**
* Starts the VPN based on the stored profile for the given package
*
@@ -323,7 +345,9 @@ public class VpnManagerService extends IVpnManager.Stub {
*/
@Override
public void startVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(mDeps.getCallingUid());
+ final int callingUid = Binder.getCallingUid();
+ verifyCallingUidAndPackage(packageName, callingUid);
+ final int user = UserHandle.getUserId(callingUid);
synchronized (mVpns) {
throwIfLockdownEnabled();
mVpns.get(user).startVpnProfile(packageName);
@@ -340,7 +364,9 @@ public class VpnManagerService extends IVpnManager.Stub {
*/
@Override
public void stopVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(mDeps.getCallingUid());
+ final int callingUid = Binder.getCallingUid();
+ verifyCallingUidAndPackage(packageName, callingUid);
+ final int user = UserHandle.getUserId(callingUid);
synchronized (mVpns) {
mVpns.get(user).stopVpnProfile(packageName);
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 1f35b88c8cbd..f591b26f1770 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -1361,7 +1361,10 @@ public class AdbDebuggingManager {
if (args.length > 1) {
hostname = args[1];
}
- PairDevice device = new PairDevice(fingerprints, hostname, false);
+ PairDevice device = new PairDevice();
+ device.name = fingerprints;
+ device.guid = hostname;
+ device.connected = false;
intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// Add the key into the keystore
@@ -1843,8 +1846,11 @@ public class AdbDebuggingManager {
if (args.length > 1) {
hostname = args[1];
}
- pairedDevices.put(keyEntry.getKey(), new PairDevice(
- hostname, fingerprints, mWifiConnectedKeys.contains(keyEntry.getKey())));
+ PairDevice pairDevice = new PairDevice();
+ pairDevice.name = hostname;
+ pairDevice.guid = fingerprints;
+ pairDevice.connected = mWifiConnectedKeys.contains(keyEntry.getKey());
+ pairedDevices.put(keyEntry.getKey(), pairDevice);
}
return pairedDevices;
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 29bb5428dd84..7a4d2ce50cd3 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -27,6 +27,8 @@ import android.database.ContentObserver;
import android.debug.AdbManager;
import android.debug.AdbManagerInternal;
import android.debug.AdbTransportType;
+import android.debug.FingerprintAndPairDevice;
+import android.debug.IAdbCallback;
import android.debug.IAdbManager;
import android.debug.IAdbTransport;
import android.debug.PairDevice;
@@ -35,6 +37,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -87,6 +90,7 @@ public class AdbService extends IAdbManager.Stub {
private final AdbConnectionPortListener mPortListener = new AdbConnectionPortListener();
private AdbDebuggingManager.AdbConnectionPortPoller mConnectionPortPoller;
+ private final RemoteCallbackList<IAdbCallback> mCallbacks = new RemoteCallbackList<>();
/**
* Manages the service lifecycle for {@code AdbService} in {@code SystemServer}.
*/
@@ -348,12 +352,21 @@ public class AdbService extends IAdbManager.Stub {
}
@Override
- public Map<String, PairDevice> getPairedDevices() {
+ public FingerprintAndPairDevice[] getPairedDevices() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- if (mDebuggingManager != null) {
- return mDebuggingManager.getPairedDevices();
- }
- return null;
+ if (mDebuggingManager == null) {
+ return null;
+ }
+ Map<String, PairDevice> map = mDebuggingManager.getPairedDevices();
+ FingerprintAndPairDevice[] ret = new FingerprintAndPairDevice[map.size()];
+ int i = 0;
+ for (Map.Entry<String, PairDevice> entry : map.entrySet()) {
+ ret[i] = new FingerprintAndPairDevice();
+ ret[i].keyFingerprint = entry.getKey();
+ ret[i].device = entry.getValue();
+ i++;
+ }
+ return ret;
}
@Override
@@ -401,6 +414,21 @@ public class AdbService extends IAdbManager.Stub {
return mConnectionPort.get();
}
+ @Override
+ public void registerCallback(IAdbCallback callback) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "Registering callback " + callback);
+ }
+ mCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterCallback(IAdbCallback callback) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "Unregistering callback " + callback);
+ }
+ mCallbacks.unregister(callback);
+ }
/**
* This listener is only used when ro.adb.secure=0. Otherwise, AdbDebuggingManager will
* do this.
@@ -507,6 +535,23 @@ public class AdbService extends IAdbManager.Stub {
if (mDebuggingManager != null) {
mDebuggingManager.setAdbEnabled(enable, transportType);
}
+
+ if (DEBUG) {
+ Slog.d(TAG, "Broadcasting enable = " + enable + ", type = " + transportType);
+ }
+ mCallbacks.broadcast((callback) -> {
+ if (DEBUG) {
+ Slog.d(TAG, "Sending enable = " + enable + ", type = " + transportType
+ + " to " + callback);
+ }
+ try {
+ callback.onDebuggingChanged(enable, transportType);
+ } catch (RemoteException ex) {
+ if (DEBUG) {
+ Slog.d(TAG, "Unable to send onDebuggingChanged:", ex);
+ }
+ }
+ });
}
@Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 07847f1df053..2483fb895f1d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -102,6 +102,7 @@ import android.app.usage.UsageEvents;
import android.appwidget.AppWidgetManagerInternal;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Overridable;
import android.content.ComponentName;
import android.content.ComponentName.WithComponentName;
import android.content.Context;
@@ -152,7 +153,6 @@ import android.webkit.WebViewZygote;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ServiceState;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.notification.SystemNotificationChannels;
@@ -164,6 +164,7 @@ import com.android.server.AppStateTracker;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.am.ActivityManagerService.ItemMatcher;
+import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityServiceConnectionsHolder;
@@ -173,6 +174,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@@ -307,6 +309,7 @@ public final class ActiveServices {
*/
@ChangeId
@EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
+ @Overridable
static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L;
/**
@@ -333,7 +336,9 @@ public final class ActiveServices {
@Override
public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
synchronized (mAm) {
- stopAllForegroundServicesLocked(uid, packageName);
+ if (!isForegroundServiceAllowedInBackgroundRestricted(uid, packageName)) {
+ stopAllForegroundServicesLocked(uid, packageName);
+ }
}
}
}
@@ -607,6 +612,17 @@ public final class ActiveServices {
return (mode != AppOpsManager.MODE_ALLOWED);
}
+ void updateAppRestrictedAnyInBackgroundLocked(final int uid, final String packageName) {
+ final boolean restricted = appRestrictedAnyInBackground(uid, packageName);
+ final UidRecord uidRec = mAm.mProcessList.getUidRecordLOSP(uid);
+ if (uidRec != null) {
+ final ProcessRecord app = uidRec.getProcessInPackage(packageName);
+ if (app != null) {
+ app.mState.setBackgroundRestricted(restricted);
+ }
+ }
+ }
+
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId)
@@ -805,10 +821,12 @@ public final class ActiveServices {
if (fgRequired) {
// We are now effectively running a foreground service.
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(true, mAm.mProcessStats.getMemFactorLocked(),
- r.lastActivity);
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(true, mAm.mProcessStats.getMemFactorLocked(),
+ r.lastActivity);
+ }
}
mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
@@ -1080,9 +1098,11 @@ public final class ActiveServices {
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+ }
}
r.callStart = false;
@@ -1142,8 +1162,10 @@ public final class ActiveServices {
mAm.mBatteryStatsService.noteServiceStopRunning(uid, packageName, serviceName);
service.startRequested = false;
if (service.tracker != null) {
- service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
service.callStart = false;
@@ -1318,8 +1340,10 @@ public final class ActiveServices {
mAm.mBatteryStatsService.noteServiceStopRunning(uid, packageName, serviceName);
r.startRequested = false;
if (r.tracker != null) {
- r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
r.callStart = false;
final long origId = Binder.clearCallingIdentity();
@@ -1438,7 +1462,8 @@ public final class ActiveServices {
if (!aa.mAppOnTop) {
// Transitioning a fg-service host app out of top: if it's bg restricted,
// it loses the fg service state now.
- if (!appRestrictedAnyInBackground(aa.mUid, aa.mPackageName)) {
+ if (isForegroundServiceAllowedInBackgroundRestricted(
+ aa.mUid, aa.mPackageName)) {
if (active == null) {
active = new ArrayList<>();
}
@@ -1656,8 +1681,38 @@ public final class ActiveServices {
}
}
- private boolean appIsTopLocked(int uid) {
- return mAm.getUidStateLocked(uid) <= PROCESS_STATE_TOP;
+ /**
+ * Check if the given app is allowed to have FGS running even if it's background restricted.
+ *
+ * <p>
+ * Currently it needs to be in Top/Bound Top/FGS state. An uid could be in the FGS state if:
+ * a) Bound by another process in the FGS state;
+ * b) There is an active FGS running (ServiceRecord.isForeground is true);
+ * c) The startForegroundService() has been called but the startForeground() hasn't - in this
+ * case, it must have passed the background FGS start check so we're safe here.
+ * </p>
+ */
+ private boolean isForegroundServiceAllowedInBackgroundRestricted(ProcessRecord app) {
+ final ProcessStateRecord state = app.mState;
+ if (!state.isBackgroundRestricted()
+ || state.getSetProcState() <= ActivityManager.PROCESS_STATE_BOUND_TOP) {
+ return true;
+ }
+ if (state.getSetProcState() == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ && state.isSetBoundByNonBgRestrictedApp()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if the given uid/pkg is allowed to have FGS running even if it's background restricted.
+ */
+ private boolean isForegroundServiceAllowedInBackgroundRestricted(int uid, String packageName) {
+ final UidRecord uidRec = mAm.mProcessList.getUidRecordLOSP(uid);
+ ProcessRecord app = null;
+ return uidRec != null && ((app = uidRec.getProcessInPackage(packageName)) != null)
+ && isForegroundServiceAllowedInBackgroundRestricted(app);
}
/**
@@ -1751,8 +1806,7 @@ public final class ActiveServices {
// Apps that are TOP or effectively similar may call startForeground() on
// their services even if they are restricted from doing that while in bg.
if (!ignoreForeground
- && !appIsTopLocked(r.appInfo.uid)
- && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
+ && !isForegroundServiceAllowedInBackgroundRestricted(r.app)) {
Slog.w(TAG,
"Service.startForeground() not allowed due to bg restriction: service "
+ r.shortInstanceName);
@@ -1875,10 +1929,12 @@ public final class ActiveServices {
r.mStartForegroundCount++;
r.mFgsEnterTime = SystemClock.uptimeMillis();
if (!stopProcStatsOp) {
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(true,
- mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(true,
+ mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+ }
}
} else {
stopProcStatsOp = false;
@@ -1913,10 +1969,12 @@ public final class ActiveServices {
if (stopProcStatsOp) {
// We got through to this point with it actively being started foreground,
// and never decided we wanted to keep it like that, so drop it.
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
}
if (alreadyStartedOp) {
@@ -1958,10 +2016,12 @@ public final class ActiveServices {
r.isForeground = false;
r.mFgsExitTime = SystemClock.uptimeMillis();
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
mAm.mAppOpsService.finishOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
@@ -2736,10 +2796,12 @@ public final class ActiveServices {
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// This is the first binding, let the tracker know.
- ServiceState stracker = s.getTracker();
- if (stracker != null) {
- stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
- s.lastActivity);
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = s.getTracker();
+ if (stracker != null) {
+ stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
+ s.lastActivity);
+ }
}
}
}
@@ -3376,9 +3438,11 @@ public final class ActiveServices {
ProcessServiceRecord psr;
if (r.executeNesting == 0) {
r.executeFg = fg;
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
+ synchronized (mAm.mProcessStats.mLock) {
+ final ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
+ }
}
if (r.app != null) {
psr = r.app.mServices;
@@ -3467,6 +3531,8 @@ public final class ActiveServices {
final long now = SystemClock.uptimeMillis();
final String reason;
+ final int oldPosInRestarting = mRestartingServices.indexOf(r);
+ boolean inRestarting = oldPosInRestarting != -1;
if ((r.serviceInfo.applicationInfo.flags
&ApplicationInfo.FLAG_PERSISTENT) == 0) {
long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION;
@@ -3534,56 +3600,89 @@ public final class ActiveServices {
}
if (isServiceRestartBackoffEnabledLocked(r.packageName)) {
- r.nextRestartTime = now + r.restartDelay;
-
- // Make sure that we don't end up restarting a bunch of services
- // all at the same time.
- boolean repeat;
- final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
- do {
- repeat = false;
- for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
- final ServiceRecord r2 = mRestartingServices.get(i);
- if (r2 != r
- && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)
- && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {
- r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
- r.restartDelay = r.nextRestartTime - now;
- repeat = true;
- break;
+ r.nextRestartTime = r.mEarliestRestartTime = now + r.restartDelay;
+
+ if (inRestarting) {
+ // Take it out of the list temporarily for easier maintenance of the list.
+ mRestartingServices.remove(oldPosInRestarting);
+ inRestarting = false;
+ }
+ if (mRestartingServices.isEmpty()) {
+ // Apply the extra delay even if it's the only one in the list.
+ final long extraDelay = getExtraRestartTimeInBetweenLocked();
+ r.nextRestartTime = Math.max(now + extraDelay, r.nextRestartTime);
+ r.restartDelay = r.nextRestartTime - now;
+ } else {
+ // Make sure that we don't end up restarting a bunch of services
+ // all at the same time.
+ boolean repeat;
+ final long restartTimeBetween = getExtraRestartTimeInBetweenLocked()
+ + mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
+ do {
+ repeat = false;
+ final long nextRestartTime = r.nextRestartTime;
+ // mRestartingServices is sorted by nextRestartTime.
+ for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
+ final ServiceRecord r2 = mRestartingServices.get(i);
+ final long nextRestartTime2 = r2.nextRestartTime;
+ if (nextRestartTime >= (nextRestartTime2 - restartTimeBetween)
+ && nextRestartTime < (nextRestartTime2 + restartTimeBetween)) {
+ r.nextRestartTime = nextRestartTime2 + restartTimeBetween;
+ r.restartDelay = r.nextRestartTime - now;
+ repeat = true;
+ break;
+ } else if (nextRestartTime >= nextRestartTime2 + restartTimeBetween) {
+ // This spot fulfills our needs, bail out.
+ break;
+ }
}
- }
- } while (repeat);
+ } while (repeat);
+ }
} else {
// It's been forced to ignore the restart backoff, fix the delay here.
r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;
r.nextRestartTime = now + r.restartDelay;
}
-
} else {
// Persistent processes are immediately restarted, so there is no
// reason to hold of on restarting their services.
r.totalRestartCount++;
r.restartCount = 0;
r.restartDelay = 0;
+ r.mEarliestRestartTime = 0;
r.nextRestartTime = now;
reason = "persistent";
}
- if (!mRestartingServices.contains(r)) {
- r.createdFromFg = false;
- mRestartingServices.add(r);
- r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
+ r.mRestartSchedulingTime = now;
+ if (!inRestarting) {
+ if (oldPosInRestarting == -1) {
+ r.createdFromFg = false;
+ synchronized (mAm.mProcessStats.mLock) {
+ r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
+ }
+ }
+ boolean added = false;
+ for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
+ final ServiceRecord r2 = mRestartingServices.get(i);
+ if (r2.nextRestartTime > r.nextRestartTime) {
+ mRestartingServices.add(i, r);
+ added = true;
+ break;
+ }
+ }
+ if (!added) {
+ mRestartingServices.add(r);
+ }
}
cancelForegroundNotificationLocked(r);
- performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis());
+ performScheduleRestartLocked(r, "Scheduling", reason, now);
return true;
}
- @VisibleForTesting
@GuardedBy("mAm")
void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling,
@NonNull String reason, @UptimeMillisLong long now) {
@@ -3596,6 +3695,161 @@ public final class ActiveServices {
r.userId, r.shortInstanceName, r.restartDelay);
}
+ /**
+ * Reschedule service restarts based on the given memory pressure.
+ *
+ * @param prevMemFactor The previous memory factor.
+ * @param curMemFactor The current memory factor.
+ * @param reason The human-readable text about why we're doing rescheduling.
+ * @param now The uptimeMillis
+ */
+ @GuardedBy("mAm")
+ void rescheduleServiceRestartOnMemoryPressureIfNeededLocked(@MemFactor int prevMemFactor,
+ @MemFactor int curMemFactor, @NonNull String reason, @UptimeMillisLong long now) {
+ final boolean enabled = mAm.mConstants.mEnableExtraServiceRestartDelayOnMemPressure;
+ if (!enabled) {
+ return;
+ }
+ performRescheduleServiceRestartOnMemoryPressureLocked(
+ mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[prevMemFactor],
+ mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[curMemFactor], reason, now);
+ }
+
+ /**
+ * Reschedule service restarts based on if the extra delays are enabled or not.
+ *
+ * @param prevEnable The previous state of whether or not it's enabled.
+ * @param curEnabled The current state of whether or not it's enabled.
+ * @param now The uptimeMillis
+ */
+ @GuardedBy("mAm")
+ void rescheduleServiceRestartOnMemoryPressureIfNeededLocked(boolean prevEnabled,
+ boolean curEnabled, @UptimeMillisLong long now) {
+ if (prevEnabled == curEnabled) {
+ return;
+ }
+ final @MemFactor int memFactor = mAm.mAppProfiler.getLastMemoryLevelLocked();
+ final long delay = mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ performRescheduleServiceRestartOnMemoryPressureLocked(prevEnabled ? delay : 0,
+ curEnabled ? delay : 0, "config", now);
+ }
+
+ /**
+ * Rescan the list of pending restarts, reschedule them if needed.
+ *
+ * @param extraRestartTimeBetween The extra interval between restarts.
+ * @param minRestartTimeBetween The minimal interval between restarts.
+ * @param reason The human-readable text about why we're doing rescheduling.
+ * @param now The uptimeMillis
+ */
+ @GuardedBy("mAm")
+ void rescheduleServiceRestartIfPossibleLocked(long extraRestartTimeBetween,
+ long minRestartTimeBetween, @NonNull String reason, @UptimeMillisLong long now) {
+ final long restartTimeBetween = extraRestartTimeBetween + minRestartTimeBetween;
+ final long spanForInsertOne = restartTimeBetween * 2; // Min space to insert a restart.
+
+ long lastRestartTime = now;
+ int lastRestartTimePos = -1; // The list index where the "lastRestartTime" comes from.
+ for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
+ final ServiceRecord r = mRestartingServices.get(i);
+ if ((r.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
+ || !isServiceRestartBackoffEnabledLocked(r.packageName)) {
+ lastRestartTime = r.nextRestartTime;
+ lastRestartTimePos = i;
+ continue;
+ }
+ if (lastRestartTime + restartTimeBetween <= r.mEarliestRestartTime) {
+ // Bounded by the earliest restart time, honor it; but we also need to
+ // check if the interval between the earlist and its prior one is enough or not.
+ r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime, i > 0
+ ? mRestartingServices.get(i - 1).nextRestartTime + restartTimeBetween
+ : 0));
+ } else {
+ if (lastRestartTime <= now) {
+ // It hasn't moved, this is the first one (besides persistent process),
+ // we don't need to insert the minRestartTimeBetween for it, but need
+ // the extraRestartTimeBetween still.
+ r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime,
+ r.mRestartSchedulingTime + extraRestartTimeBetween));
+ } else {
+ r.nextRestartTime = Math.max(now, lastRestartTime + restartTimeBetween);
+ }
+ if (i > lastRestartTimePos + 1) {
+ // Move the current service record ahead in the list.
+ mRestartingServices.remove(i);
+ mRestartingServices.add(lastRestartTimePos + 1, r);
+ }
+ }
+ // Find the next available slot to insert one if there is any
+ for (int j = lastRestartTimePos + 1; j <= i; j++) {
+ final ServiceRecord r2 = mRestartingServices.get(j);
+ final long timeInBetween = r2.nextRestartTime - (j == 0 ? lastRestartTime
+ : mRestartingServices.get(j - 1).nextRestartTime);
+ if (timeInBetween >= spanForInsertOne) {
+ break;
+ }
+ lastRestartTime = r2.nextRestartTime;
+ lastRestartTimePos = j;
+ }
+ r.restartDelay = r.nextRestartTime - now;
+ performScheduleRestartLocked(r, "Rescheduling", reason, now);
+ }
+ }
+
+ @GuardedBy("mAm")
+ void performRescheduleServiceRestartOnMemoryPressureLocked(long oldExtraDelay,
+ long newExtraDelay, @NonNull String reason, @UptimeMillisLong long now) {
+ final long delta = newExtraDelay - oldExtraDelay;
+ if (delta == 0) {
+ return;
+ }
+ if (delta > 0) {
+ final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN
+ + newExtraDelay;
+ long lastRestartTime = now;
+ // Make the delay in between longer.
+ for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
+ final ServiceRecord r = mRestartingServices.get(i);
+ if ((r.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
+ || !isServiceRestartBackoffEnabledLocked(r.packageName)) {
+ lastRestartTime = r.nextRestartTime;
+ continue;
+ }
+ boolean reschedule = false;
+ if (lastRestartTime <= now) {
+ // It hasn't moved, this is the first one (besides persistent process),
+ // we don't need to insert the minRestartTimeBetween for it, but need
+ // the newExtraDelay still.
+ final long oldVal = r.nextRestartTime;
+ r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime,
+ r.mRestartSchedulingTime + newExtraDelay));
+ reschedule = r.nextRestartTime != oldVal;
+ } else if (r.nextRestartTime - lastRestartTime < restartTimeBetween) {
+ r.nextRestartTime = Math.max(lastRestartTime + restartTimeBetween, now);
+ reschedule = true;
+ }
+ r.restartDelay = r.nextRestartTime - now;
+ lastRestartTime = r.nextRestartTime;
+ if (reschedule) {
+ performScheduleRestartLocked(r, "Rescheduling", reason, now);
+ }
+ }
+ } else if (delta < 0) {
+ // Make the delay in between shorter, we'd do a rescan and reschedule.
+ rescheduleServiceRestartIfPossibleLocked(newExtraDelay,
+ mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN, reason, now);
+ }
+ }
+
+ @GuardedBy("mAm")
+ long getExtraRestartTimeInBetweenLocked() {
+ if (!mAm.mConstants.mEnableExtraServiceRestartDelayOnMemPressure) {
+ return 0;
+ }
+ final @MemFactor int memFactor = mAm.mAppProfiler.getLastMemoryLevelLocked();
+ return mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ }
+
final void performServiceRestartLocked(ServiceRecord r) {
if (!mRestartingServices.contains(r)) {
return;
@@ -3651,8 +3905,10 @@ public final class ActiveServices {
}
}
if (!stillTracking) {
- r.restartTracker.setRestarting(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ r.restartTracker.setRestarting(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
r.restartTracker = null;
}
}
@@ -3682,6 +3938,9 @@ public final class ActiveServices {
performScheduleRestartLocked(r, "Rescheduling", reason, now);
}
}
+ // mRestartingServices is sorted by nextRestartTime.
+ Collections.sort(mRestartingServices,
+ (a, b) -> (int) (a.nextRestartTime - b.nextRestartTime));
}
} else {
removeServiceRestartBackoffEnabledLocked(packageName);
@@ -4172,9 +4431,11 @@ public final class ActiveServices {
+ r);
r.fgRequired = false;
r.fgWaiting = false;
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+ synchronized (mAm.mProcessStats.mLock) {
+ ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+ }
}
mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
@@ -4231,9 +4492,11 @@ public final class ActiveServices {
cancelForegroundNotificationLocked(r);
if (r.isForeground) {
decActiveForegroundAppLocked(smap, r);
- ServiceState stracker = r.getTracker();
- if (stracker != null) {
- stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+ synchronized (mAm.mProcessStats.mLock) {
+ ServiceState stracker = r.getTracker();
+ if (stracker != null) {
+ stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+ }
}
mAm.mAppOpsService.finishOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
@@ -4301,13 +4564,15 @@ public final class ActiveServices {
((ServiceRestarter)r.restarter).setService(null);
}
- int memFactor = mAm.mProcessStats.getMemFactorLocked();
- if (r.tracker != null) {
- r.tracker.setStarted(false, memFactor, now);
- r.tracker.setBound(false, memFactor, now);
- if (r.executeNesting == 0) {
- r.tracker.clearCurrentOwner(r, false);
- r.tracker = null;
+ synchronized (mAm.mProcessStats.mLock) {
+ final int memFactor = mAm.mProcessStats.getMemFactorLocked();
+ if (r.tracker != null) {
+ r.tracker.setStarted(false, memFactor, now);
+ r.tracker.setBound(false, memFactor, now);
+ if (r.executeNesting == 0) {
+ r.tracker.clearCurrentOwner(r, false);
+ r.tracker = null;
+ }
}
}
@@ -4438,8 +4703,10 @@ public final class ActiveServices {
boolean hasAutoCreate = s.hasAutoCreateConnections();
if (!hasAutoCreate) {
if (s.tracker != null) {
- s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
}
bringDownServiceIfNeededLocked(s, true, hasAutoCreate, enqueueOomAdj);
@@ -4531,12 +4798,14 @@ public final class ActiveServices {
private void serviceProcessGoneLocked(ServiceRecord r, boolean enqueueOomAdj) {
if (r.tracker != null) {
- int memFactor = mAm.mProcessStats.getMemFactorLocked();
- long now = SystemClock.uptimeMillis();
- r.tracker.setExecuting(false, memFactor, now);
- r.tracker.setForeground(false, memFactor, now);
- r.tracker.setBound(false, memFactor, now);
- r.tracker.setStarted(false, memFactor, now);
+ synchronized (mAm.mProcessStats.mLock) {
+ final int memFactor = mAm.mProcessStats.getMemFactorLocked();
+ final long now = SystemClock.uptimeMillis();
+ r.tracker.setExecuting(false, memFactor, now);
+ r.tracker.setForeground(false, memFactor, now);
+ r.tracker.setBound(false, memFactor, now);
+ r.tracker.setStarted(false, memFactor, now);
+ }
}
serviceDoneExecutingLocked(r, true, true, enqueueOomAdj);
}
@@ -4583,13 +4852,15 @@ public final class ActiveServices {
}
r.executeFg = false;
if (r.tracker != null) {
- final int memFactor = mAm.mProcessStats.getMemFactorLocked();
- final long now = SystemClock.uptimeMillis();
- r.tracker.setExecuting(false, memFactor, now);
- r.tracker.setForeground(false, memFactor, now);
- if (finishing) {
- r.tracker.clearCurrentOwner(r, false);
- r.tracker = null;
+ synchronized (mAm.mProcessStats.mLock) {
+ final int memFactor = mAm.mProcessStats.getMemFactorLocked();
+ final long now = SystemClock.uptimeMillis();
+ r.tracker.setExecuting(false, memFactor, now);
+ r.tracker.setForeground(false, memFactor, now);
+ if (finishing) {
+ r.tracker.clearCurrentOwner(r, false);
+ r.tracker = null;
+ }
}
}
if (finishing) {
@@ -4604,6 +4875,11 @@ public final class ActiveServices {
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
+
+ // Update the app background restriction of the caller
+ proc.mState.setBackgroundRestricted(appRestrictedAnyInBackground(
+ proc.uid, proc.info.packageName));
+
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
@@ -4647,6 +4923,7 @@ public final class ActiveServices {
// run at this point just because their restart time hasn't come up.
if (mRestartingServices.size() > 0) {
ServiceRecord sr;
+ boolean didImmediateRestart = false;
for (int i=0; i<mRestartingServices.size(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
@@ -4655,6 +4932,18 @@ public final class ActiveServices {
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
+ didImmediateRestart = true;
+ }
+ if (didImmediateRestart) {
+ // Since we kicked off all its pending restarts, there could be some open slots
+ // in the pending restarts list, schedule a check on it. We are posting to the same
+ // handler, so by the time of the check, those immediate restarts should be done.
+ mAm.mHandler.post(() ->
+ rescheduleServiceRestartIfPossibleLocked(
+ getExtraRestartTimeInBetweenLocked(),
+ mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN,
+ "other", SystemClock.uptimeMillis())
+ );
}
}
return didSomething;
@@ -4974,8 +5263,10 @@ public final class ActiveServices {
// down it.
sr.startRequested = false;
if (sr.tracker != null) {
- sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ synchronized (mAm.mProcessStats.mLock) {
+ sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
+ SystemClock.uptimeMillis());
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index ac0a1985ac89..eb37e2d96cb6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -21,6 +21,7 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
+import android.annotation.NonNull;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -31,6 +32,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.PowerExemptionManager;
+import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
@@ -40,6 +42,8 @@ import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
@@ -109,6 +113,10 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout";
static final String KEY_FGS_ATOM_SAMPLE_RATE = "fgs_atom_sample_rate";
static final String KEY_FGS_ALLOW_OPT_OUT = "fgs_allow_opt_out";
+ static final String KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE =
+ "extra_delay_svc_restart_mem_pressure";
+ static final String KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE =
+ "enable_extra_delay_svc_restart_mem_pressure";
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -159,6 +167,25 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 1;
private static final boolean DEFAULT_FGS_ALLOW_OPT_OUT = false;
+ /**
+ * The extra delays we're putting to service restarts, based on current memory pressure.
+ */
+ private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_NORMAL_MEM = 0; // ms
+ private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MODERATE_MEM = 10000; // ms
+ private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_LOW_MEM = 20000; // ms
+ private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_CRITICAL_MEM = 30000; // ms
+ private static final long[] DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE = {
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_NORMAL_MEM,
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MODERATE_MEM,
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_LOW_MEM,
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_CRITICAL_MEM,
+ };
+
+ /**
+ * Whether or not to enable the extra delays to service restarts on memory pressure.
+ */
+ private static final boolean DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE = true;
+
// Flag stored in the DeviceConfig API.
/**
* Maximum number of cached processes.
@@ -501,6 +528,20 @@ final class ActivityManagerConstants extends ContentObserver {
*/
volatile boolean mFgsAllowOptOut = DEFAULT_FGS_ALLOW_OPT_OUT;
+ /*
+ * The extra delays we're putting to service restarts, based on current memory pressure.
+ */
+ @GuardedBy("mService")
+ long[] mExtraServiceRestartDelayOnMemPressure =
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;
+
+ /**
+ * Whether or not to enable the extra delays to service restarts on memory pressure.
+ */
+ @GuardedBy("mService")
+ boolean mEnableExtraServiceRestartDelayOnMemPressure =
+ DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;
+
private final ActivityManagerService mService;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -714,6 +755,12 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_FGS_ALLOW_OPT_OUT:
updateFgsAllowOptOut();
break;
+ case KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE:
+ updateExtraServiceRestartDelayOnMemPressure();
+ break;
+ case KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE:
+ updateEnableExtraServiceRestartDelayOnMemPressure();
+ break;
default:
break;
}
@@ -1064,6 +1111,51 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_FGS_ALLOW_OPT_OUT);
}
+ private void updateExtraServiceRestartDelayOnMemPressure() {
+ synchronized (mService) {
+ final int memFactor = mService.mAppProfiler.getLastMemoryLevelLocked();
+ final long[] prevDelays = mExtraServiceRestartDelayOnMemPressure;
+ mExtraServiceRestartDelayOnMemPressure = parseLongArray(
+ KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE);
+ mService.mServices.performRescheduleServiceRestartOnMemoryPressureLocked(
+ mExtraServiceRestartDelayOnMemPressure[memFactor],
+ prevDelays[memFactor], "config", SystemClock.uptimeMillis());
+ }
+ }
+
+ private void updateEnableExtraServiceRestartDelayOnMemPressure() {
+ synchronized (mService) {
+ final boolean prevEnabled = mEnableExtraServiceRestartDelayOnMemPressure;
+ mEnableExtraServiceRestartDelayOnMemPressure = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
+ DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE);
+ mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ prevEnabled, mEnableExtraServiceRestartDelayOnMemPressure,
+ SystemClock.uptimeMillis());
+ }
+ }
+
+ private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
+ final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ key, null);
+ if (!TextUtils.isEmpty(val)) {
+ final String[] ss = val.split(",");
+ if (ss.length == def.length) {
+ final long[] tmp = new long[ss.length];
+ try {
+ for (int i = 0; i < ss.length; i++) {
+ tmp[i] = Long.parseLong(ss[i]);
+ }
+ return tmp;
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ return def;
+ }
+
private void updateImperceptibleKillExemptions() {
IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear();
IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 35ed4773e087..70ceb92b8631 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -258,6 +258,7 @@ import android.os.IDeviceIdentifiersPolicyService;
import android.os.IPermissionController;
import android.os.IProcessInfoService;
import android.os.IProgressListener;
+import android.os.InputConstants;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
@@ -1831,6 +1832,18 @@ public class ActivityManagerService extends IActivityManager.Stub
}
});
+ mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null,
+ new IAppOpsCallback.Stub() {
+ @Override public void opChanged(int op, int uid, String packageName) {
+ if (op == AppOpsManager.OP_RUN_ANY_IN_BACKGROUND && packageName != null) {
+ synchronized (ActivityManagerService.this) {
+ mServices.updateAppRestrictedAnyInBackgroundLocked(
+ uid, packageName);
+ }
+ }
+ }
+ });
+
final int[] cameraOp = {AppOpsManager.OP_CAMERA};
mAppOpsService.startWatchingActive(cameraOp, new IAppOpsActiveCallback.Stub() {
@Override
@@ -5707,7 +5720,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public int[] checkUriPermissions(@NonNull List<Uri> uris, int pid, int uid,
- final int modeFlags, IBinder callerToken) {
+ final int modeFlags, int userId, IBinder callerToken) {
final int size = uris.size();
int[] res = new int[size];
// Default value DENIED.
@@ -5715,9 +5728,9 @@ public class ActivityManagerService extends IActivityManager.Stub
for (int i = 0; i < size; i++) {
final Uri uri = uris.get(i);
- final int userId = ContentProvider.getUserIdFromUri(uri, mContext.getUserId());
+ final int userIdFromUri = ContentProvider.getUserIdFromUri(uri, userId);
res[i] = checkUriPermission(ContentProvider.getUriWithoutUserId(uri), pid, uid,
- modeFlags, userId, callerToken);
+ modeFlags, userIdFromUri, callerToken);
}
return res;
}
@@ -12628,76 +12641,72 @@ public class ActivityManagerService extends IActivityManager.Stub
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
List<ResolveInfo> receivers = null;
- try {
- HashSet<ComponentName> singleUserReceivers = null;
- boolean scannedFirstReceivers = false;
- for (int user : users) {
- // Skip users that have Shell restrictions
- if (callingUid == SHELL_UID
- && mUserController.hasUserRestriction(
- UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
- continue;
- }
- List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
- .queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
- if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
- // If this is not the system user, we need to check for
- // any receivers that should be filtered out.
- for (int i=0; i<newReceivers.size(); i++) {
- ResolveInfo ri = newReceivers.get(i);
- if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
- newReceivers.remove(i);
- i--;
- }
+ HashSet<ComponentName> singleUserReceivers = null;
+ boolean scannedFirstReceivers = false;
+ for (int user : users) {
+ // Skip users that have Shell restrictions
+ if (callingUid == SHELL_UID
+ && mUserController.hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
+ continue;
+ }
+ List<ResolveInfo> newReceivers = mPackageManagerInt
+ .queryIntentReceivers(intent, resolvedType, pmFlags, callingUid, user);
+ if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
+ // If this is not the system user, we need to check for
+ // any receivers that should be filtered out.
+ for (int i = 0; i < newReceivers.size(); i++) {
+ ResolveInfo ri = newReceivers.get(i);
+ if ((ri.activityInfo.flags & ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
+ newReceivers.remove(i);
+ i--;
}
}
- if (newReceivers != null && newReceivers.size() == 0) {
- newReceivers = null;
- }
- if (receivers == null) {
- receivers = newReceivers;
- } else if (newReceivers != null) {
- // We need to concatenate the additional receivers
- // found with what we have do far. This would be easy,
- // but we also need to de-dup any receivers that are
- // singleUser.
- if (!scannedFirstReceivers) {
- // Collect any single user receivers we had already retrieved.
- scannedFirstReceivers = true;
- for (int i=0; i<receivers.size(); i++) {
- ResolveInfo ri = receivers.get(i);
- if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
- ComponentName cn = new ComponentName(
- ri.activityInfo.packageName, ri.activityInfo.name);
- if (singleUserReceivers == null) {
- singleUserReceivers = new HashSet<ComponentName>();
- }
- singleUserReceivers.add(cn);
- }
- }
- }
- // Add the new results to the existing results, tracking
- // and de-dupping single user receivers.
- for (int i=0; i<newReceivers.size(); i++) {
- ResolveInfo ri = newReceivers.get(i);
+ }
+ if (newReceivers != null && newReceivers.size() == 0) {
+ newReceivers = null;
+ }
+ if (receivers == null) {
+ receivers = newReceivers;
+ } else if (newReceivers != null) {
+ // We need to concatenate the additional receivers
+ // found with what we have do far. This would be easy,
+ // but we also need to de-dup any receivers that are
+ // singleUser.
+ if (!scannedFirstReceivers) {
+ // Collect any single user receivers we had already retrieved.
+ scannedFirstReceivers = true;
+ for (int i = 0; i < receivers.size(); i++) {
+ ResolveInfo ri = receivers.get(i);
if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
ComponentName cn = new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name);
if (singleUserReceivers == null) {
singleUserReceivers = new HashSet<ComponentName>();
}
- if (!singleUserReceivers.contains(cn)) {
- singleUserReceivers.add(cn);
- receivers.add(ri);
- }
- } else {
+ singleUserReceivers.add(cn);
+ }
+ }
+ }
+ // Add the new results to the existing results, tracking
+ // and de-dupping single user receivers.
+ for (int i = 0; i < newReceivers.size(); i++) {
+ ResolveInfo ri = newReceivers.get(i);
+ if ((ri.activityInfo.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+ ComponentName cn = new ComponentName(
+ ri.activityInfo.packageName, ri.activityInfo.name);
+ if (singleUserReceivers == null) {
+ singleUserReceivers = new HashSet<ComponentName>();
+ }
+ if (!singleUserReceivers.contains(cn)) {
+ singleUserReceivers.add(cn);
receivers.add(ri);
}
+ } else {
+ receivers.add(ri);
}
}
}
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
}
if (receivers != null && broadcastAllowList != null) {
for (int i = receivers.size() - 1; i >= 0; i--) {
@@ -13331,8 +13340,7 @@ public class ActivityManagerService extends IActivityManager.Stub
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// Need to resolve the intent to interested receivers...
- if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
- == 0) {
+ if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
receivers = collectReceiverComponents(
intent, resolvedType, callingUid, users, broadcastAllowList);
}
@@ -15332,6 +15340,12 @@ public class ActivityManagerService extends IActivityManager.Stub
@VisibleForTesting
public final class LocalService extends ActivityManagerInternal
implements ActivityManagerLocal {
+
+ @Override
+ public Pair<String, String> getAppProfileStatsForDebugging(long time, int lines) {
+ return mAppProfiler.getAppProfileStatsForDebugging(time, lines);
+ }
+
@Override
public String checkContentProviderAccess(String authority, int userId) {
return mCpHelper.checkContentProviderAccess(authority, userId);
@@ -15986,8 +16000,22 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void inputDispatchingResumed(int pid) {
- // TODO (b/171218828)
- return;
+ final ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(pid);
+ }
+ if (proc != null) {
+ mAppErrors.handleDismissAnrDialogs(proc);
+ }
+ }
+
+ @Override
+ public void rescheduleAnrDialog(Object data) {
+ Message msg = Message.obtain();
+ msg.what = SHOW_NOT_RESPONDING_UI_MSG;
+ msg.obj = (AppNotRespondingDialog.Data) data;
+
+ mUiHandler.sendMessageDelayed(msg, InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
}
@Override
@@ -16630,13 +16658,21 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"scheduleApplicationInfoChanged()");
- synchronized (mProcLock) {
- final long origId = Binder.clearCallingIdentity();
- try {
- updateApplicationInfoLOSP(packageNames, userId);
- } finally {
- Binder.restoreCallingIdentity(origId);
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ final boolean updateFrameworkRes = packageNames.contains("android");
+ synchronized (mProcLock) {
+ updateApplicationInfoLOSP(packageNames, updateFrameworkRes, userId);
+ }
+
+ AppWidgetManagerInternal widgets = LocalServices.getService(
+ AppWidgetManagerInternal.class);
+ if (widgets != null) {
+ widgets.applyResourceOverlaysToWidgets(new HashSet<>(packageNames), userId,
+ updateFrameworkRes);
}
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
@@ -16653,18 +16689,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@GuardedBy(anyOf = {"this", "mProcLock"})
- private void updateApplicationInfoLOSP(@NonNull List<String> packagesToUpdate, int userId) {
- final boolean updateFrameworkRes = packagesToUpdate.contains("android");
+ private void updateApplicationInfoLOSP(@NonNull List<String> packagesToUpdate,
+ boolean updateFrameworkRes, int userId) {
if (updateFrameworkRes) {
ParsingPackageUtils.readConfigUseRoundIcon(null);
}
- AppWidgetManagerInternal widgets = LocalServices.getService(AppWidgetManagerInternal.class);
- if (widgets != null) {
- widgets.applyResourceOverlaysToWidgets(new HashSet<>(packagesToUpdate), userId,
- updateFrameworkRes);
- }
-
mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);
if (updateFrameworkRes) {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index bcb42bb38495..0dfdfe94b6ec 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -1058,6 +1058,7 @@ class AppErrors {
}
synchronized (mProcLock) {
final ProcessErrorStateRecord errState = proc.mErrorState;
+ errState.setAnrData(data);
if (!proc.isPersistent()) {
packageList = proc.getPackageListWithVersionCode();
}
@@ -1109,6 +1110,24 @@ class AppErrors {
}
}
+ void handleDismissAnrDialogs(ProcessRecord proc) {
+ synchronized (mProcLock) {
+ final ProcessErrorStateRecord errState = proc.mErrorState;
+
+ // Cancel any rescheduled ANR dialogs
+ mService.mUiHandler.removeMessages(
+ ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG, errState.getAnrData());
+
+ // Dismiss any ANR dialogs currently visible
+ if (errState.getDialogController().hasAnrDialogs()) {
+ errState.setNotResponding(false);
+ errState.setNotRespondingReport(null);
+ errState.getDialogController().clearAnrDialogs();
+ }
+ proc.mErrorState.setAnrData(null);
+ }
+ }
+
/**
* Information about a process that is currently marked as bad.
*/
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index b233a2ccc6e3..878ef31f143d 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -48,12 +48,14 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
private final ActivityManagerService mService;
private final ProcessRecord mProc;
+ private final Data mData;
public AppNotRespondingDialog(ActivityManagerService service, Context context, Data data) {
super(context);
mService = service;
mProc = data.proc;
+ mData = data;
Resources res = context.getResources();
setCancelable(false);
@@ -165,6 +167,8 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
errState.getDialogController().clearAnrDialogs();
}
mService.mServices.scheduleServiceTimeoutLocked(app);
+ // If the app remains unresponsive, show the dialog again after a delay.
+ mService.mInternal.rescheduleAnrDialog(mData);
}
break;
}
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 36c0de919279..f2fb3714b03a 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -393,6 +393,7 @@ public class AppProfiler {
static final int COLLECT_PSS_BG_MSG = 1;
static final int DEFER_PSS_MSG = 2;
static final int STOP_DEFERRING_PSS_MSG = 3;
+ static final int MEMORY_PRESSURE_CHANGED = 4;
BgHandler(Looper looper) {
super(looper);
}
@@ -409,6 +410,11 @@ public class AppProfiler {
case STOP_DEFERRING_PSS_MSG:
stopDeferPss();
break;
+ case MEMORY_PRESSURE_CHANGED:
+ synchronized (mService) {
+ handleMemoryPressureChangedLocked(msg.arg1, msg.arg2);
+ }
+ break;
}
}
}
@@ -912,12 +918,18 @@ public class AppProfiler {
}
@GuardedBy("mService")
- int getLastMemoryLevelLocked() {
+ @MemFactor int getLastMemoryLevelLocked() {
+ if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) {
+ return mMemFactorOverride;
+ }
return mLastMemoryLevel;
}
@GuardedBy("mService")
boolean isLastMemoryLevelNormal() {
+ if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) {
+ return mMemFactorOverride <= ADJ_MEM_FACTOR_NORMAL;
+ }
return mLastMemoryLevel <= ADJ_MEM_FACTOR_NORMAL;
}
@@ -989,6 +1001,8 @@ public class AppProfiler {
if (memFactor != mLastMemoryLevel) {
EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
+ mBgHandler.obtainMessage(BgHandler.MEMORY_PRESSURE_CHANGED, mLastMemoryLevel, memFactor)
+ .sendToTarget();
}
mLastMemoryLevel = memFactor;
mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
@@ -1636,6 +1650,13 @@ public class AppProfiler {
}
}
+ @GuardedBy("mService")
+ private void handleMemoryPressureChangedLocked(@MemFactor int oldMemFactor,
+ @MemFactor int newMemFactor) {
+ mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ oldMemFactor, newMemFactor, "mem-pressure-event", SystemClock.uptimeMillis());
+ }
+
@GuardedBy("mProfilerLock")
private void stopProfilerLPf(ProcessRecord proc, int profileType) {
if (proc == null || proc == mProfileData.getProfileProc()) {
@@ -2318,6 +2339,27 @@ public class AppProfiler {
}
}
+ Pair<String, String> getAppProfileStatsForDebugging(long time, int linesOfStats) {
+ String cpuLoad = null;
+ String stats = null;
+ synchronized (mProcessCpuTracker) {
+ updateCpuStatsNow();
+ cpuLoad = mProcessCpuTracker.printCurrentLoad();
+ stats = mProcessCpuTracker.printCurrentState(time);
+ }
+ // Only return linesOfStats lines of Cpu stats.
+ int toIndex = 0;
+ for (int i = 0; i <= linesOfStats; i++) {
+ int nextIndex = stats.indexOf('\n', toIndex);
+ if (nextIndex == -1) {
+ toIndex = stats.length();
+ break;
+ }
+ toIndex = nextIndex + 1;
+ }
+ return new Pair(cpuLoad, stats.substring(0, toIndex));
+ }
+
@GuardedBy("mProfilerLock")
void writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
if (mProcessesToGc.size() > 0) {
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 7c336d768006..f32aa2295cb8 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -101,7 +101,7 @@ public final class CachedAppOptimizer {
// Defaults for phenotype flags.
@VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
- @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = false;
+ @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true;
@VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE;
@VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
@@ -276,7 +276,7 @@ public final class CachedAppOptimizer {
DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ;
@GuardedBy("mPhenotypeFlagLock")
private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
- private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
+ private volatile boolean mUseFreezer = false; // set to DEFAULT in init()
@GuardedBy("this")
private int mFreezerDisableCount = 1; // Freezer is initially disabled, until enabled
private final Random mRandom = new Random();
@@ -678,6 +678,8 @@ public final class CachedAppOptimizer {
KEY_USE_FREEZER, DEFAULT_USE_FREEZER)) {
mUseFreezer = isFreezerSupported();
updateFreezerDebounceTimeout();
+ } else {
+ mUseFreezer = false;
}
final boolean useFreezer = mUseFreezer;
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index e6cd509f50dc..916127126117 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -47,6 +47,7 @@ final class ConnectionRecord {
public AssociationState.SourceState association; // Association tracking
String stringName; // Caching of toString.
boolean serviceDead; // Well is it?
+ private Object mProcStatsLock; // Internal lock for accessing AssociationState
// Please keep the following two enum list synced.
private static final int[] BIND_ORIG_ENUMS = new int[] {
@@ -137,23 +138,29 @@ final class ConnectionRecord {
Slog.wtf(TAG_AM, "Inactive holder in referenced service "
+ binding.service.shortInstanceName + ": proc=" + binding.service.app);
} else {
- association = holder.pkg.getAssociationStateLocked(holder.state,
- binding.service.instanceName.getClassName()).startSource(clientUid,
- clientProcessName, clientPackageName);
-
+ mProcStatsLock = binding.service.app.mService.mProcessStats.mLock;
+ synchronized (mProcStatsLock) {
+ association = holder.pkg.getAssociationStateLocked(holder.state,
+ binding.service.instanceName.getClassName()).startSource(clientUid,
+ clientProcessName, clientPackageName);
+ }
}
}
}
public void trackProcState(int procState, int seq, long now) {
if (association != null) {
- association.trackProcState(procState, seq, now);
+ synchronized (mProcStatsLock) {
+ association.trackProcState(procState, seq, now);
+ }
}
}
public void stopAssociation() {
if (association != null) {
- association.stop();
+ synchronized (mProcStatsLock) {
+ association.stop();
+ }
association = null;
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index 3bc4fcf08921..3b9d47d509ad 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -38,6 +38,7 @@ public final class ContentProviderConnection extends Binder {
public final String clientPackage;
public AssociationState.SourceState association;
public final long createTime;
+ private Object mProcStatsLock; // Internal lock for accessing AssociationState
/**
* Internal lock that guards access to the two counters.
@@ -87,23 +88,29 @@ public final class ContentProviderConnection extends Binder {
Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ provider.name.toShortString() + ": proc=" + provider.proc);
} else {
- association = holder.pkg.getAssociationStateLocked(holder.state,
- provider.name.getClassName()).startSource(client.uid, client.processName,
- clientPackage);
-
+ mProcStatsLock = provider.proc.mService.mProcessStats.mLock;
+ synchronized (mProcStatsLock) {
+ association = holder.pkg.getAssociationStateLocked(holder.state,
+ provider.name.getClassName()).startSource(client.uid,
+ client.processName, clientPackage);
+ }
}
}
}
public void trackProcState(int procState, int seq, long now) {
if (association != null) {
- association.trackProcState(procState, seq, now);
+ synchronized (mProcStatsLock) {
+ association.trackProcState(procState, seq, now);
+ }
}
}
public void stopAssociation() {
if (association != null) {
- association.stop();
+ synchronized (mProcStatsLock) {
+ association.stop();
+ }
association = null;
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index 5fd15db79d66..75f31c0ac29f 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -321,6 +321,7 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
final String mOwningProcessName;
int mAcquisitionCount;
AssociationState.SourceState mAssociation;
+ private Object mProcStatsLock; // Internal lock for accessing AssociationState
public ExternalProcessHandle(IBinder token, int owningUid, String owningProcessName) {
mToken = token;
@@ -353,17 +354,21 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ provider.name.toShortString() + ": proc=" + provider.proc);
} else {
- mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
- provider.name.getClassName()).startSource(mOwningUid,
- mOwningProcessName, null);
-
+ mProcStatsLock = provider.proc.mService.mProcessStats.mLock;
+ synchronized (mProcStatsLock) {
+ mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
+ provider.name.getClassName()).startSource(mOwningUid,
+ mOwningProcessName, null);
+ }
}
}
}
public void stopAssociation() {
if (mAssociation != null) {
- mAssociation.stop();
+ synchronized (mProcStatsLock) {
+ mAssociation.stop();
+ }
mAssociation = null;
}
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 93d5c06b40c9..27d8119b84fb 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -511,6 +511,7 @@ public class OomAdjuster {
}
app.mState.resetCachedInfo();
+ app.mState.setCurBoundByNonBgRestrictedApp(false);
UidRecord uidRec = app.getUidRecord();
if (uidRec != null) {
if (DEBUG_UID_OBSERVERS) {
@@ -644,6 +645,7 @@ public class OomAdjuster {
state.setContainsCycle(false);
state.setProcStateChanged(false);
state.resetCachedInfo();
+ state.setCurBoundByNonBgRestrictedApp(false);
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp,
@@ -934,6 +936,7 @@ public class OomAdjuster {
state.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
state.setSetCapability(PROCESS_CAPABILITY_NONE);
state.resetCachedInfo();
+ state.setCurBoundByNonBgRestrictedApp(false);
}
}
mProcessesInCycle.clear();
@@ -1900,6 +1903,7 @@ public class OomAdjuster {
}
int capabilityFromFGS = 0; // capability from foreground service.
+ boolean boundByNonBgRestricted = state.isCurBoundByNonBgRestrictedApp();
boolean scheduleLikeTopApp = false;
for (int is = psr.numberOfRunningServices() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
@@ -2014,6 +2018,11 @@ public class OomAdjuster {
final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
+ boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
+ || clientProcState <= PROCESS_STATE_BOUND_TOP
+ || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
+ && !cstate.isBackgroundRestricted());
+
if (client.mOptRecord.shouldNotFreeze()) {
// Propagate the shouldNotFreeze flag down the bindings.
app.mOptRecord.setShouldNotFreeze(true);
@@ -2336,6 +2345,12 @@ public class OomAdjuster {
// Propagate the shouldNotFreeze flag down the bindings.
app.mOptRecord.setShouldNotFreeze(true);
}
+
+ boundByNonBgRestricted |= cstate.isCurBoundByNonBgRestrictedApp()
+ || clientProcState <= PROCESS_STATE_BOUND_TOP
+ || (clientProcState == PROCESS_STATE_FOREGROUND_SERVICE
+ && !cstate.isBackgroundRestricted());
+
String adjType = null;
if (adj > clientAdj) {
if (state.hasShownUi() && !state.getCachedIsHomeProcess()
@@ -2513,6 +2528,7 @@ public class OomAdjuster {
state.updateLastInvisibleTime(hasVisibleActivities);
state.setHasForegroundActivities(foregroundActivities);
state.setCompletedAdjSeq(mAdjSeq);
+ state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted);
// if curAdj or curProcState improved, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
@@ -2820,8 +2836,10 @@ public class OomAdjuster {
state.setNotCachedSinceIdle(false);
}
if (!doingAll) {
- mService.setProcessTrackerStateLOSP(app,
- mService.mProcessStats.getMemFactorLocked(), now);
+ synchronized (mService.mProcessStats.mLock) {
+ mService.setProcessTrackerStateLOSP(app,
+ mService.mProcessStats.getMemFactorLocked(), now);
+ }
} else {
state.setProcStateChanged(true);
}
@@ -2853,6 +2871,19 @@ public class OomAdjuster {
state.setSetCapability(state.getCurCapability());
}
+ final boolean curBoundByNonBgRestrictedApp = state.isCurBoundByNonBgRestrictedApp();
+ if (curBoundByNonBgRestrictedApp != state.isSetBoundByNonBgRestrictedApp()) {
+ state.setSetBoundByNonBgRestrictedApp(curBoundByNonBgRestrictedApp);
+ if (!curBoundByNonBgRestrictedApp && state.isBackgroundRestricted()) {
+ mService.mHandler.post(() -> {
+ synchronized (mService) {
+ mService.mServices.stopAllForegroundServicesLocked(
+ app.uid, app.info.packageName);
+ }
+ });
+ }
+ }
+
if (changes != 0) {
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Changes in " + app + ": " + changes);
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 7e79ef5a5e69..8d3e44276620 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -117,6 +117,12 @@ class ProcessErrorStateRecord {
private ComponentName mErrorReportReceiver;
/**
+ * ANR dialog data used to dismiss any visible ANR dialogs if the app becomes responsive.
+ */
+ @CompositeRWLock({"mService", "mProcLock"})
+ private AppNotRespondingDialog.Data mAnrData;
+
+ /**
* Optional local handler to be invoked in the process crash.
*/
@CompositeRWLock({"mService", "mProcLock"})
@@ -209,6 +215,16 @@ class ProcessErrorStateRecord {
return mDialogController;
}
+ @GuardedBy({"mService", "mProcLock"})
+ void setAnrData(AppNotRespondingDialog.Data data) {
+ mAnrData = data;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ AppNotRespondingDialog.Data getAnrData() {
+ return mAnrData;
+ }
+
ProcessErrorStateRecord(ProcessRecord app) {
mApp = app;
mService = app.mService;
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index dc6bcd8ab9de..85d06c3dadbf 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -302,6 +302,23 @@ final class ProcessStateRecord {
private int mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
/**
+ * Whether or not the app is background restricted (OP_RUN_ANY_IN_BACKGROUND is NOT allowed).
+ */
+ @GuardedBy("mService")
+ private boolean mBackgroundRestricted = false;
+
+ /**
+ * Whether or not this process is being bound by a non-background restricted app.
+ */
+ @GuardedBy("mService")
+ private boolean mCurBoundByNonBgRestrictedApp = false;
+
+ /**
+ * Last set state of {@link #mCurBoundByNonBgRestrictedApp}.
+ */
+ private boolean mSetBoundByNonBgRestrictedApp = false;
+
+ /**
* Debugging: primary thing impacting oom_adj.
*/
@GuardedBy("mService")
@@ -1113,6 +1130,36 @@ final class ProcessStateRecord {
}
@GuardedBy("mService")
+ boolean isBackgroundRestricted() {
+ return mBackgroundRestricted;
+ }
+
+ @GuardedBy("mService")
+ void setBackgroundRestricted(boolean restricted) {
+ mBackgroundRestricted = restricted;
+ }
+
+ @GuardedBy("mService")
+ boolean isCurBoundByNonBgRestrictedApp() {
+ return mCurBoundByNonBgRestrictedApp;
+ }
+
+ @GuardedBy("mService")
+ void setCurBoundByNonBgRestrictedApp(boolean bound) {
+ mCurBoundByNonBgRestrictedApp = bound;
+ }
+
+ @GuardedBy("mService")
+ boolean isSetBoundByNonBgRestrictedApp() {
+ return mSetBoundByNonBgRestrictedApp;
+ }
+
+ @GuardedBy("mService")
+ void setSetBoundByNonBgRestrictedApp(boolean bound) {
+ mSetBoundByNonBgRestrictedApp = bound;
+ }
+
+ @GuardedBy("mService")
void updateLastInvisibleTime(boolean hasVisibleActivities) {
if (hasVisibleActivities) {
mLastInvisibleTime = Long.MAX_VALUE;
@@ -1164,7 +1211,14 @@ final class ProcessStateRecord {
ActivityManager.printCapabilitiesFull(pw, mSetCapability);
pw.println();
pw.print(prefix); pw.print("allowStartFgsState=");
- pw.println(mAllowStartFgsState);
+ pw.print(mAllowStartFgsState);
+ if (mBackgroundRestricted) {
+ pw.print(" backgroundRestricted=");
+ pw.print(mBackgroundRestricted);
+ pw.print(" boundByNonBgRestrictedApp=");
+ pw.print(mSetBoundByNonBgRestrictedApp);
+ }
+ pw.println();
if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) {
pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi);
pw.print(" pendingUiClean="); pw.println(mApp.mProfile.hasPendingUiClean());
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 804e442bc8de..97ed0a38fabe 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -196,6 +196,22 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
boolean mKeepWarming; // Whether or not it'll keep critical code path of the host warm
+ /**
+ * The original earliest restart time, which considers the number of crashes, etc.,
+ * but doesn't include the extra delays we put in between to scatter the restarts;
+ * it's the earliest time this auto service restart could happen alone(except those
+ * batch restarts which happens at time of process attach).
+ */
+ long mEarliestRestartTime;
+
+ /**
+ * The original time when the service start is scheduled, it does NOT include the reschedules.
+ *
+ * <p>The {@link #restartDelay} would be updated when its restart is rescheduled, but this field
+ * won't, so it could be used when dumping how long the restart is delayed actually.</p>
+ */
+ long mRestartSchedulingTime;
+
static class StartItem {
final ServiceRecord sr;
final boolean taskRemoved;
@@ -373,10 +389,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
if (destroying || destroyTime != 0) {
ProtoUtils.toDuration(proto, ServiceRecordProto.DESTORY_TIME, destroyTime, now);
}
- if (crashCount != 0 || restartCount != 0 || restartDelay != 0 || nextRestartTime != 0) {
+ if (crashCount != 0 || restartCount != 0 || (nextRestartTime - mRestartSchedulingTime) != 0
+ || nextRestartTime != 0) {
long crashToken = proto.start(ServiceRecordProto.CRASH);
proto.write(ServiceRecordProto.Crash.RESTART_COUNT, restartCount);
- ProtoUtils.toDuration(proto, ServiceRecordProto.Crash.RESTART_DELAY, restartDelay, now);
+ ProtoUtils.toDuration(proto, ServiceRecordProto.Crash.RESTART_DELAY,
+ (nextRestartTime - mRestartSchedulingTime), now);
ProtoUtils.toDuration(proto,
ServiceRecordProto.Crash.NEXT_RESTART_TIME, nextRestartTime, now);
proto.write(ServiceRecordProto.Crash.CRASH_COUNT, crashCount);
@@ -504,10 +522,10 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
pw.println();
}
if (crashCount != 0 || restartCount != 0
- || restartDelay != 0 || nextRestartTime != 0) {
+ || (nextRestartTime - mRestartSchedulingTime) != 0 || nextRestartTime != 0) {
pw.print(prefix); pw.print("restartCount="); pw.print(restartCount);
pw.print(" restartDelay=");
- TimeUtils.formatDuration(restartDelay, now, pw);
+ TimeUtils.formatDuration(nextRestartTime - mRestartSchedulingTime, now, pw);
pw.print(" nextRestartTime=");
TimeUtils.formatDuration(nextRestartTime, now, pw);
pw.print(" crashCount="); pw.println(crashCount);
@@ -899,6 +917,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
restartCount = 0;
restartDelay = 0;
restartTime = 0;
+ mEarliestRestartTime = 0;
+ mRestartSchedulingTime = 0;
}
public StartItem findDeliveredStart(int id, boolean taskRemoved, boolean remove) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index c10334470ae1..fc02f1913487 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -84,6 +84,7 @@ public class SettingsToPropertiesMapper {
DeviceConfig.NAMESPACE_CONNECTIVITY,
DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS,
+ DeviceConfig.NAMESPACE_LMKD_NATIVE,
DeviceConfig.NAMESPACE_MEDIA_NATIVE,
DeviceConfig.NAMESPACE_NETD_NATIVE,
DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 4ba59faea9ec..6101e267effc 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -21,6 +21,7 @@ import android.app.ActivityManager;
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -282,6 +283,17 @@ public final class UidRecord {
}
}
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ ProcessRecord getProcessInPackage(String packageName) {
+ for (int i = mProcRecords.size() - 1; i >= 0; i--) {
+ final ProcessRecord app = mProcRecords.valueAt(i);
+ if (app != null && TextUtils.equals(app.info.packageName, packageName)) {
+ return app;
+ }
+ }
+ return null;
+ }
+
@GuardedBy({"mService", "mProcLock"})
void addProcess(ProcessRecord app) {
mProcRecords.add(app);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 099dee537e33..cfd2978d7eeb 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -45,6 +45,9 @@ import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
+import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED;
+import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_RESUMED;
+import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_STARTED;
import static android.app.AppOpsManager.OpEventProxyInfo;
import static android.app.AppOpsManager.RestrictionBypass;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
@@ -1238,6 +1241,11 @@ public class AppOpsService extends IAppOpsService.Stub {
scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid, parent.packageName,
tag, true, event.getAttributionFlags(), event.getAttributionChainId());
}
+ // Note: this always sends MODE_ALLOWED, even if the mode is FOREGROUND
+ // TODO ntmyren: figure out how to get the real mode.
+ scheduleOpStartedIfNeededLocked(parent.op, parent.uid, parent.packageName,
+ tag, event.getFlags(), MODE_ALLOWED, START_TYPE_RESUMED,
+ event.getAttributionFlags(), event.getAttributionChainId());
}
mPausedInProgressEvents = null;
}
@@ -3945,13 +3953,15 @@ public class AppOpsService extends IAppOpsService.Stub {
}
boolean isRestricted = false;
+ int startType = START_TYPE_FAILED;
synchronized (this) {
final Ops ops = getOpsLocked(uid, packageName, attributionTag,
pvr.isAttributionTagValid, pvr.bypass, /* edit */ true);
if (ops == null) {
if (!dryRun) {
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
- flags, AppOpsManager.MODE_IGNORED);
+ flags, AppOpsManager.MODE_IGNORED, startType, attributionFlags,
+ attributionChainId);
}
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+ " package " + packageName + " flags: "
@@ -3977,7 +3987,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
- flags, uidMode);
+ flags, uidMode, startType, attributionFlags, attributionChainId);
}
return new SyncNotedAppOp(uidMode, code, attributionTag, packageName);
}
@@ -3993,7 +4003,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
- flags, mode);
+ flags, mode, startType, attributionFlags, attributionChainId);
}
return new SyncNotedAppOp(mode, code, attributionTag, packageName);
}
@@ -4011,12 +4021,14 @@ public class AppOpsService extends IAppOpsService.Stub {
attributedOp.started(clientId, proxyUid, proxyPackageName,
proxyAttributionTag, uidState.state, flags, attributionFlags,
attributionChainId);
+ startType = START_TYPE_STARTED;
}
} catch (RemoteException e) {
throw new RuntimeException(e);
}
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, flags,
- isRestricted ? MODE_IGNORED : MODE_ALLOWED);
+ isRestricted ? MODE_IGNORED : MODE_ALLOWED, startType, attributionFlags,
+ attributionChainId);
}
}
@@ -4187,7 +4199,9 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName,
- String attributionTag, @OpFlags int flags, @Mode int result) {
+ String attributionTag, @OpFlags int flags, @Mode int result,
+ @AppOpsManager.OnOpStartedListener.StartedType int startedType,
+ @AttributionFlags int attributionFlags, int attributionChainId) {
ArraySet<StartedCallback> dispatchedCallbacks = null;
final int callbackListCount = mStartedWatchers.size();
for (int i = 0; i < callbackListCount; i++) {
@@ -4213,12 +4227,13 @@ public class AppOpsService extends IAppOpsService.Stub {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpStarted,
this, dispatchedCallbacks, code, uid, pkgName, attributionTag, flags,
- result));
+ result, startedType, attributionFlags, attributionChainId));
}
private void notifyOpStarted(ArraySet<StartedCallback> callbacks,
int code, int uid, String packageName, String attributionTag, @OpFlags int flags,
- @Mode int result) {
+ @Mode int result, @AppOpsManager.OnOpStartedListener.StartedType int startedType,
+ @AttributionFlags int attributionFlags, int attributionChainId) {
final long identity = Binder.clearCallingIdentity();
try {
final int callbackCount = callbacks.size();
@@ -4226,7 +4241,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final StartedCallback callback = callbacks.valueAt(i);
try {
callback.mCallback.opStarted(code, uid, packageName, attributionTag, flags,
- result);
+ result, startedType, attributionFlags, attributionChainId);
} catch (RemoteException e) {
/* do nothing */
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index fcd198e8831c..2f69abfd04e0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -738,6 +738,11 @@ public class AudioService extends IAudioService.Stub
private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
private long mLoweredFromNormalToVibrateTime;
+ // Uid of the active hotword detection service to check if caller is the one or not.
+ @GuardedBy("mHotwordDetectionServiceUidLock")
+ private int mHotwordDetectionServiceUid = android.os.Process.INVALID_UID;
+ private final Object mHotwordDetectionServiceUidLock = new Object();
+
// Array of Uids of valid accessibility services to check if caller is one of them
private final Object mAccessibilityServiceUidsLock = new Object();
@GuardedBy("mAccessibilityServiceUidsLock")
@@ -1339,6 +1344,9 @@ public class AudioService extends IAudioService.Stub
updateAssistantUId(true);
AudioSystem.setRttEnabled(mRttEnabled);
}
+ synchronized (mHotwordDetectionServiceUidLock) {
+ AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+ }
synchronized (mAccessibilityServiceUidsLock) {
AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
}
@@ -9082,6 +9090,16 @@ public class AudioService extends IAudioService.Stub
}
@Override
+ public void setHotwordDetectionServiceUid(int uid) {
+ synchronized (mHotwordDetectionServiceUidLock) {
+ if (mHotwordDetectionServiceUid != uid) {
+ mHotwordDetectionServiceUid = uid;
+ AudioSystem.setHotwordDetectionServiceUid(mHotwordDetectionServiceUid);
+ }
+ }
+ }
+
+ @Override
public void setAccessibilityServiceUids(IntArray uids) {
synchronized (mAccessibilityServiceUidsLock) {
if (uids.size() == 0) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index 973fbd2bba17..6d567807f357 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -367,6 +367,14 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback {
}
/**
+ * Same as {@link AudioSystem#setHotwordDetectionServiceUid(int)}
+ * Communicate UID of current HotwordDetectionService to audio policy service.
+ */
+ public int setHotwordDetectionServiceUid(int uid) {
+ return AudioSystem.setHotwordDetectionServiceUid(uid);
+ }
+
+ /**
* Same as {@link AudioSystem#setCurrentImeUid(int)}
* Communicate UID of current InputMethodService to audio policy service.
*/
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index f4327e8a104d..6f38ed04cd96 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -82,7 +82,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
private long mStartTimeMs;
- protected boolean mAuthAttempted;
+ private boolean mAuthAttempted;
// TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
// the state. We should think of a way to improve this in the future.
@@ -98,6 +98,12 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
*/
protected abstract void handleLifecycleAfterAuth(boolean authenticated);
+ /**
+ * @return true if a user was detected (i.e. face was found, fingerprint sensor was touched.
+ * etc)
+ */
+ public abstract boolean wasUserDetected();
+
public AuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
@@ -180,7 +186,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
+ ", isBP: " + isBiometricPrompt()
+ ", listener: " + listener
+ ", requireConfirmation: " + mRequireConfirmation
- + ", user: " + getTargetUserId());
+ + ", user: " + getTargetUserId()
+ + ", clientMonitor: " + toString());
final PerformanceTracker pm = PerformanceTracker.getInstanceForSensorId(getSensorId());
if (isCryptoOperation()) {
@@ -304,6 +311,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
public void handleLifecycleAfterAuth() {
AuthenticationClient.this.handleLifecycleAfterAuth(true /* authenticated */);
}
+
+ @Override
+ public void sendAuthenticationCanceled() {
+ sendCancelOnly(listener);
+ }
});
} else {
// Allow system-defined limit of number of attempts before giving up
@@ -338,10 +350,30 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
public void handleLifecycleAfterAuth() {
AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
}
+
+ @Override
+ public void sendAuthenticationCanceled() {
+ sendCancelOnly(listener);
+ }
});
}
}
+ private void sendCancelOnly(@Nullable ClientMonitorCallbackConverter listener) {
+ if (listener == null) {
+ Slog.e(TAG, "Unable to sendAuthenticationCanceled, listener null");
+ return;
+ }
+ try {
+ listener.onError(getSensorId(),
+ getCookie(),
+ BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+ 0 /* vendorCode */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+
@Override
public void onAcquired(int acquiredInfo, int vendorCode) {
super.onAcquired(acquiredInfo, vendorCode);
@@ -355,9 +387,11 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
}
@Override
- public void onError(int errorCode, int vendorCode) {
+ public void onError(@BiometricConstants.Errors int errorCode, int vendorCode) {
super.onError(errorCode, vendorCode);
mState = STATE_STOPPED;
+
+ CoexCoordinator.getInstance().onAuthenticationError(this, errorCode, this::vibrateError);
}
/**
@@ -419,4 +453,8 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
public boolean interruptsPrecedingClients() {
return true;
}
+
+ public boolean wasAuthAttempted() {
+ return mAuthAttempted;
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
index a15ecada3cae..25d4a38cd475 100644
--- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
@@ -22,6 +22,7 @@ import static com.android.server.biometrics.sensors.BiometricScheduler.sensorTyp
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricConstants;
import android.os.Handler;
import android.os.Looper;
import android.util.Slog;
@@ -54,7 +55,7 @@ public class CoexCoordinator {
/**
* Callback interface notifying the owner of "results" from the CoexCoordinator's business
- * logic.
+ * logic for accept and reject.
*/
interface Callback {
/**
@@ -73,6 +74,22 @@ public class CoexCoordinator {
* from scheduler if auth was successful).
*/
void handleLifecycleAfterAuth();
+
+ /**
+ * Requests the owner to notify the caller that authentication was canceled.
+ */
+ void sendAuthenticationCanceled();
+ }
+
+ /**
+ * Callback interface notifying the owner of "results" from the CoexCoordinator's business
+ * logic for errors.
+ */
+ interface ErrorCallback {
+ /**
+ * Requests the owner to initiate a vibration for this event.
+ */
+ void sendHapticFeedback();
}
private static CoexCoordinator sInstance;
@@ -198,6 +215,9 @@ public class CoexCoordinator {
mClientMap.remove(sensorType);
}
+ /**
+ * Notify the coordinator that authentication succeeded (accepted)
+ */
public void onAuthenticationSucceeded(long currentTimeMillis,
@NonNull AuthenticationClient<?> client,
@NonNull Callback callback) {
@@ -268,6 +288,9 @@ public class CoexCoordinator {
}
}
+ /**
+ * Notify the coordinator that a rejection has occurred.
+ */
public void onAuthenticationRejected(long currentTimeMillis,
@NonNull AuthenticationClient<?> client,
@LockoutTracker.LockoutMode int lockoutMode,
@@ -352,11 +375,63 @@ public class CoexCoordinator {
}
}
+ /**
+ * Notify the coordinator that an error has occurred.
+ */
+ public void onAuthenticationError(@NonNull AuthenticationClient<?> client,
+ @BiometricConstants.Errors int error, @NonNull ErrorCallback callback) {
+ // Figure out non-coex state
+ final boolean shouldUsuallyVibrate;
+ if (isCurrentFaceAuth(client)) {
+ final boolean notDetectedOnKeyguard = client.isKeyguard() && !client.wasUserDetected();
+ final boolean authAttempted = client.wasAuthAttempted();
+
+ switch (error) {
+ case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
+ case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
+ case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
+ shouldUsuallyVibrate = authAttempted && !notDetectedOnKeyguard;
+ break;
+ default:
+ shouldUsuallyVibrate = false;
+ break;
+ }
+ } else {
+ shouldUsuallyVibrate = false;
+ }
+
+ // Figure out coex state
+ final boolean keyguardAdvancedLogic = mAdvancedLogicEnabled && client.isKeyguard();
+ final boolean hapticSuppressedByCoex;
+
+ if (keyguardAdvancedLogic) {
+ if (isSingleAuthOnly(client)) {
+ hapticSuppressedByCoex = false;
+ } else {
+ hapticSuppressedByCoex = isCurrentFaceAuth(client)
+ && !client.isKeyguardBypassEnabled();
+ }
+ } else {
+ hapticSuppressedByCoex = false;
+ }
+
+ // Combine and send feedback if appropriate
+ Slog.d(TAG, "shouldUsuallyVibrate: " + shouldUsuallyVibrate
+ + ", hapticSuppressedByCoex: " + hapticSuppressedByCoex);
+ if (shouldUsuallyVibrate && !hapticSuppressedByCoex) {
+ callback.sendHapticFeedback();
+ }
+ }
+
@Nullable
private SuccessfulAuth popSuccessfulFaceAuthIfExists(long currentTimeMillis) {
for (SuccessfulAuth auth : mSuccessfulAuths) {
if (currentTimeMillis - auth.mAuthTimestamp >= SUCCESSFUL_AUTH_VALID_DURATION_MS) {
- Slog.d(TAG, "Removing stale auth: " + auth);
+ // TODO(b/193089985): This removes the auth but does not notify the client with
+ // an appropriate lifecycle event (such as ERROR_CANCELED), and violates the
+ // API contract. However, this might be OK for now since the validity duration
+ // is way longer than the time it takes to auth with fingerprint.
+ Slog.e(TAG, "Removing stale auth: " + auth);
mSuccessfulAuths.remove(auth);
} else if (auth.mSensorType == SENSOR_TYPE_FACE) {
mSuccessfulAuths.remove(auth);
@@ -367,9 +442,13 @@ public class CoexCoordinator {
}
private void removeAndFinishAllFaceFromQueue() {
+ // Note that these auth are all successful, but have never notified the client (e.g.
+ // keyguard). To comply with the authentication lifecycle, we must notify the client that
+ // auth is "done". The safest thing to do is to send ERROR_CANCELED.
for (SuccessfulAuth auth : mSuccessfulAuths) {
if (auth.mSensorType == SENSOR_TYPE_FACE) {
- Slog.d(TAG, "Removing from queue and finishing: " + auth);
+ Slog.d(TAG, "Removing from queue, canceling, and finishing: " + auth);
+ auth.mCallback.sendAuthenticationCanceled();
auth.mCallback.handleLifecycleAfterAuth();
mSuccessfulAuths.remove(auth);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index f7fd8d0972f6..d66a27920f49 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -127,7 +127,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
}
- private boolean wasUserDetected() {
+ @Override
+ public boolean wasUserDetected() {
// Do not provide haptic feedback if the user was not detected, and an error (usually
// ERROR_TIMEOUT) is received.
return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
@@ -160,7 +161,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
@Override
- public void onError(int error, int vendorCode) {
+ public void onError(@BiometricConstants.Errors int error, int vendorCode) {
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -169,25 +170,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
vendorCode,
getTargetUserId()));
- switch (error) {
- case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
- if (!wasUserDetected() && !isBiometricPrompt()) {
- // No vibration if user was not detected on keyguard
- break;
- }
- case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
- case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
- if (mAuthAttempted) {
- // Only vibrate if auth was attempted. If the user was already locked out prior
- // to starting authentication, do not vibrate.
- vibrateError();
- }
- break;
- case BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL:
- BiometricNotificationUtils.showReEnrollmentNotification(getContext());
- break;
- default:
- break;
+ if (error == BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL) {
+ BiometricNotificationUtils.showReEnrollmentNotification(getContext());
}
super.onError(error, vendorCode);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index c33b957223a4..33950af2216f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -115,7 +115,8 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
}
}
- private boolean wasUserDetected() {
+ @Override
+ public boolean wasUserDetected() {
// Do not provide haptic feedback if the user was not detected, and an error (usually
// ERROR_TIMEOUT) is received.
return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
@@ -147,7 +148,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
}
@Override
- public void onError(int error, int vendorCode) {
+ public void onError(@BiometricConstants.Errors int error, int vendorCode) {
mUsageStats.addEvent(new UsageStats.AuthenticationEvent(
getStartTimeMs(),
System.currentTimeMillis() - getStartTimeMs() /* latency */,
@@ -156,24 +157,6 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
vendorCode,
getTargetUserId()));
- switch (error) {
- case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT:
- if (!wasUserDetected() && !isBiometricPrompt()) {
- // No vibration if user was not detected on keyguard
- break;
- }
- case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT:
- case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
- if (mAuthAttempted) {
- // Only vibrate if auth was attempted. If the user was already locked out prior
- // to starting authentication, do not vibrate.
- vibrateError();
- }
- break;
- default:
- break;
- }
-
super.onError(error, vendorCode);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 8835c1e02610..37ee76adeece 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -106,6 +106,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
}
@Override
+ public boolean wasUserDetected() {
+ // TODO: Update if it needs to be used for fingerprint, i.e. success/reject, error_timeout
+ return false;
+ }
+
+ @Override
public void onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
super.onAuthenticated(identifier, authenticated, token);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 83f1480f4611..5060744bb33e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -153,6 +153,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
}
@Override
+ public boolean wasUserDetected() {
+ // TODO: Update if it needs to be used for fingerprint, i.e. success/reject, error_timeout
+ return false;
+ }
+
+ @Override
public @LockoutTracker.LockoutMode int handleFailedAttempt(int userId) {
mLockoutFrameworkImpl.addFailedAttemptForUser(userId);
return super.handleFailedAttempt(userId);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 9f806af5b444..806bcc29f305 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -16,7 +16,9 @@
package com.android.server.display;
+import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
@@ -105,6 +107,34 @@ abstract class DisplayDevice {
}
/**
+ * Returns the window token of the level of the WindowManager hierarchy to mirror, or null
+ * if layer mirroring by SurfaceFlinger should not be performed.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ @Nullable
+ public IBinder getWindowTokenClientToMirrorLocked() {
+ return null;
+ }
+
+ /**
+ * Updates the window token of the level of the level of the WindowManager hierarchy to mirror.
+ * If windowToken is null, then no layer mirroring by SurfaceFlinger to should be performed.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ public void setWindowTokenClientToMirrorLocked(IBinder windowToken) {
+ }
+
+ /**
+ * Returns the default size of the surface associated with the display, or null if the surface
+ * is not provided for layer mirroring by SurfaceFlinger.
+ * For now, only used for mirroring started from MediaProjection.
+ */
+ @Nullable
+ public Point getDisplaySurfaceDefaultSize() {
+ return null;
+ }
+
+ /**
* Gets the name of the display device.
*
* @return The display device name.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index afd18894f531..1adcf4074db9 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -63,8 +63,6 @@ import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
-import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -636,6 +634,9 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
if (display != null) {
+ // Do not let constrain be overwritten by override from WindowManager.
+ info.shouldConstrainMetricsForLauncher =
+ display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher;
if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
handleLogicalDisplayChangedLocked(display);
scheduleTraversalLocked(false);
@@ -1723,6 +1724,21 @@ public final class DisplayManagerService extends SystemService {
}
}
+ void setShouldConstrainMetricsForLauncher(boolean constrain) {
+ // Apply constrain for every display.
+ synchronized (mSyncRoot) {
+ int[] displayIds = mLogicalDisplayMapper.getDisplayIdsLocked(Process.myUid());
+ for (int i : displayIds) {
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(i);
+ if (display == null) {
+ return;
+ }
+ display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher = constrain;
+ setDisplayInfoOverrideFromWindowManagerInternal(i, display.getDisplayInfoLocked());
+ }
+ }
+ }
+
private void clearViewportsLocked() {
mViewports.clear();
}
@@ -1749,10 +1765,13 @@ public final class DisplayManagerService extends SystemService {
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
+ // Mirror the part of WM hierarchy that corresponds to the provided window token.
+ IBinder windowTokenClientToMirror = device.getWindowTokenClientToMirrorLocked();
+
// Find the logical display that the display device is showing.
// Certain displays only ever show their own content.
LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
- if (!ownContent) {
+ if (!ownContent && windowTokenClientToMirror == null) {
if (display != null && !display.hasContentLocked()) {
// If the display does not have any content of its own, then
// automatically mirror the requested logical display contents if possible.
@@ -3314,6 +3333,40 @@ public final class DisplayManagerService extends SystemService {
}
return config.getRefreshRateLimitations();
}
+
+ @Override
+ public IBinder getWindowTokenClientToMirror(int displayId) {
+ final DisplayDevice device;
+ synchronized (mSyncRoot) {
+ device = getDeviceForDisplayLocked(displayId);
+ if (device == null) {
+ return null;
+ }
+ }
+ return device.getWindowTokenClientToMirrorLocked();
+ }
+
+ @Override
+ public void setWindowTokenClientToMirror(int displayId, IBinder windowToken) {
+ synchronized (mSyncRoot) {
+ final DisplayDevice device = getDeviceForDisplayLocked(displayId);
+ if (device != null) {
+ device.setWindowTokenClientToMirrorLocked(windowToken);
+ }
+ }
+ }
+
+ @Override
+ public Point getDisplaySurfaceDefaultSize(int displayId) {
+ final DisplayDevice device;
+ synchronized (mSyncRoot) {
+ device = getDeviceForDisplayLocked(displayId);
+ if (device == null) {
+ return null;
+ }
+ }
+ return device.getDisplaySurfaceDefaultSize();
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 48edb73ac81d..94e64f070ef8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -58,6 +58,8 @@ class DisplayManagerShellCommand extends ShellCommand {
return setDisplayModeDirectorLoggingEnabled(false);
case "dwb-set-cct":
return setAmbientColorTemperatureOverride();
+ case "constrain-launcher-metrics":
+ return setConstrainLauncherMetrics();
default:
return handleDefaultCommands(cmd);
}
@@ -88,6 +90,9 @@ class DisplayManagerShellCommand extends ShellCommand {
pw.println(" Disable display mode director logging.");
pw.println(" dwb-set-cct CCT");
pw.println(" Sets the ambient color temperature override to CCT (use -1 to disable).");
+ pw.println(" constrain-launcher-metrics [true|false]");
+ pw.println(" Sets if Display#getRealSize and getRealMetrics should be constrained for ");
+ pw.println(" Launcher.");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
@@ -150,4 +155,15 @@ class DisplayManagerShellCommand extends ShellCommand {
mService.setAmbientColorTemperatureOverride(cct);
return 0;
}
+
+ private int setConstrainLauncherMetrics() {
+ String constrainText = getNextArg();
+ if (constrainText == null) {
+ getErrPrintWriter().println("Error: no value specified");
+ return 1;
+ }
+ boolean constrain = Boolean.parseBoolean(constrainText);
+ mService.setShouldConstrainMetricsForLauncher(constrain);
+ return 0;
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index b0ad11816539..a25cfd8f3ba4 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -52,6 +52,7 @@ import android.view.Display;
import android.view.DisplayInfo;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
@@ -153,7 +154,7 @@ public class DisplayModeDirector {
updateVoteLocked(displayId, priority, vote);
}
};
- mSensorObserver = new SensorObserver(context, ballotBox);
+ mSensorObserver = new SensorObserver(context, ballotBox, injector);
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
mDeviceConfig = injector.getDeviceConfig();
@@ -2129,27 +2130,36 @@ public class DisplayModeDirector {
}
}
- private static class SensorObserver implements ProximityActiveListener {
- private static final String PROXIMITY_SENSOR_NAME = null;
- private static final String PROXIMITY_SENSOR_TYPE = Sensor.STRING_TYPE_PROXIMITY;
+ private static final class SensorObserver implements ProximityActiveListener,
+ DisplayManager.DisplayListener {
+ private final String mProximitySensorName = null;
+ private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
private final BallotBox mBallotBox;
private final Context mContext;
+ private final Injector mInjector;
+ @GuardedBy("mSensorObserverLock")
+ private final SparseBooleanArray mDozeStateByDisplay = new SparseBooleanArray();
+ private final Object mSensorObserverLock = new Object();
private DisplayManager mDisplayManager;
private DisplayManagerInternal mDisplayManagerInternal;
+ @GuardedBy("mSensorObserverLock")
private boolean mIsProxActive = false;
- SensorObserver(Context context, BallotBox ballotBox) {
+ SensorObserver(Context context, BallotBox ballotBox, Injector injector) {
mContext = context;
mBallotBox = ballotBox;
+ mInjector = injector;
}
@Override
public void onProximityActive(boolean isActive) {
- if (mIsProxActive != isActive) {
- mIsProxActive = isActive;
- recalculateVotes();
+ synchronized (mSensorObserverLock) {
+ if (mIsProxActive != isActive) {
+ mIsProxActive = isActive;
+ recalculateVotesLocked();
+ }
}
}
@@ -2160,17 +2170,27 @@ public class DisplayModeDirector {
final SensorManagerInternal sensorManager =
LocalServices.getService(SensorManagerInternal.class);
sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
+
+ synchronized (mSensorObserverLock) {
+ for (Display d : mDisplayManager.getDisplays()) {
+ mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
+ }
+ }
+ mInjector.registerDisplayListener(this, BackgroundThread.getHandler(),
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
}
- private void recalculateVotes() {
+ private void recalculateVotesLocked() {
final Display[] displays = mDisplayManager.getDisplays();
for (Display d : displays) {
int displayId = d.getDisplayId();
Vote vote = null;
- if (mIsProxActive) {
+ if (mIsProxActive && !mDozeStateByDisplay.get(displayId)) {
final RefreshRateRange rate =
mDisplayManagerInternal.getRefreshRateForDisplayAndSensor(
- displayId, PROXIMITY_SENSOR_NAME, PROXIMITY_SENSOR_TYPE);
+ displayId, mProximitySensorName, mProximitySensorType);
if (rate != null) {
vote = Vote.forRefreshRates(rate.min, rate.max);
}
@@ -2181,7 +2201,44 @@ public class DisplayModeDirector {
void dumpLocked(PrintWriter pw) {
pw.println(" SensorObserver");
- pw.println(" mIsProxActive=" + mIsProxActive);
+ synchronized (mSensorObserverLock) {
+ pw.println(" mIsProxActive=" + mIsProxActive);
+ pw.println(" mDozeStateByDisplay:");
+ for (int i = 0; i < mDozeStateByDisplay.size(); i++) {
+ final int id = mDozeStateByDisplay.keyAt(i);
+ final boolean dozed = mDozeStateByDisplay.valueAt(i);
+ pw.println(" " + id + " -> " + dozed);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId));
+ synchronized (mSensorObserverLock) {
+ mDozeStateByDisplay.put(displayId, isDozeState);
+ recalculateVotesLocked();
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ boolean wasDozeState = mDozeStateByDisplay.get(displayId);
+ synchronized (mSensorObserverLock) {
+ mDozeStateByDisplay.put(displayId,
+ mInjector.isDozeState(mDisplayManager.getDisplay(displayId)));
+ if (wasDozeState != mDozeStateByDisplay.get(displayId)) {
+ recalculateVotesLocked();
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mSensorObserverLock) {
+ mDozeStateByDisplay.delete(displayId);
+ recalculateVotesLocked();
+ }
}
}
@@ -2413,6 +2470,8 @@ public class DisplayModeDirector {
Handler handler, long flags);
BrightnessInfo getBrightnessInfo(int displayId);
+
+ boolean isDozeState(Display d);
}
@VisibleForTesting
@@ -2465,6 +2524,14 @@ public class DisplayModeDirector {
return null;
}
+ @Override
+ public boolean isDozeState(Display d) {
+ if (d == null) {
+ return false;
+ }
+ return Display.isDozeState(d.getState());
+ }
+
private DisplayManager getDisplayManager() {
if (mDisplayManager == null) {
mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 5186744d5c27..86c9ca937482 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -233,6 +233,8 @@ final class LogicalDisplay {
info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
info.roundedCorners = mOverrideDisplayInfo.roundedCorners;
+ info.shouldConstrainMetricsForLauncher =
+ mOverrideDisplayInfo.shouldConstrainMetricsForLauncher;
}
mInfo.set(info);
}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index b7931c8a8424..34d2b0160c3c 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -31,7 +31,9 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST
import static com.android.server.display.DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED;
+import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Point;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.media.projection.IMediaProjection;
@@ -231,6 +233,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
private Display.Mode mMode;
private boolean mIsDisplayOn;
private int mDisplayIdToMirror;
+ private IBinder mWindowTokenClientToMirror;
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
int ownerUid, String ownerPackageName, Surface surface, int flags,
@@ -253,6 +256,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
mUniqueIndex = uniqueIndex;
mIsDisplayOn = surface != null;
mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror();
+ mWindowTokenClientToMirror = virtualDisplayConfig.getWindowTokenClientToMirror();
}
@Override
@@ -282,6 +286,26 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
return mDisplayIdToMirror;
}
+ @Override
+ @Nullable
+ public IBinder getWindowTokenClientToMirrorLocked() {
+ return mWindowTokenClientToMirror;
+ }
+
+ @Override
+ public void setWindowTokenClientToMirrorLocked(IBinder windowToken) {
+ if (mWindowTokenClientToMirror != windowToken) {
+ mWindowTokenClientToMirror = windowToken;
+ sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
+ sendTraversalRequestLocked();
+ }
+ }
+
+ @Override
+ public Point getDisplaySurfaceDefaultSize() {
+ return mSurface.getDefaultSize();
+ }
+
@VisibleForTesting
Surface getSurfaceLocked() {
return mSurface;
@@ -362,6 +386,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
pw.println("mStopped=" + mStopped);
pw.println("mDisplayIdToMirror=" + mDisplayIdToMirror);
+ pw.println("mWindowTokenClientToMirror=" + mWindowTokenClientToMirror);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index ad2ef2a2b665..05e764b92797 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -94,6 +94,21 @@ final class HdmiCecController {
private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
+ /*
+ * The three flags below determine the action when a message is received. If CEC_DISABLED_IGNORE
+ * bit is set in ACTION_ON_RECEIVE_MSG, then the message is forwarded irrespective of whether
+ * CEC is enabled or disabled. The other flags/bits are also ignored.
+ */
+ private static final int CEC_DISABLED_IGNORE = 1 << 0;
+
+ /* If CEC_DISABLED_LOG_WARNING bit is set, a warning message is printed if CEC is disabled. */
+ private static final int CEC_DISABLED_LOG_WARNING = 1 << 1;
+
+ /* If CEC_DISABLED_DROP_MSG bit is set, the message is dropped if CEC is disabled. */
+ private static final int CEC_DISABLED_DROP_MSG = 1 << 2;
+
+ private static final int ACTION_ON_RECEIVE_MSG = CEC_DISABLED_LOG_WARNING;
+
/** Cookie for matching the right end point. */
protected static final int HDMI_CEC_HAL_DEATH_COOKIE = 353;
@@ -568,6 +583,16 @@ final class HdmiCecController {
@VisibleForTesting
void onReceiveCommand(HdmiCecMessage message) {
assertRunOnServiceThread();
+ if (((ACTION_ON_RECEIVE_MSG & CEC_DISABLED_IGNORE) == 0)
+ && !mService.isControlEnabled()
+ && !HdmiCecMessage.isCecTransportMessage(message.getOpcode())) {
+ if ((ACTION_ON_RECEIVE_MSG & CEC_DISABLED_LOG_WARNING) != 0) {
+ HdmiLogger.warning("Message " + message + " received when cec disabled");
+ }
+ if ((ACTION_ON_RECEIVE_MSG & CEC_DISABLED_DROP_MSG) != 0) {
+ return;
+ }
+ }
if (mService.isAddressAllocated() && !isAcceptableAddress(message.getDestination())) {
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
index 15a316739134..e3292a35bf6b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
@@ -307,5 +307,16 @@ public final class HdmiCecMessage {
private static boolean isUserControlPressedMessage(int opcode) {
return Constants.MESSAGE_USER_CONTROL_PRESSED == opcode;
}
+
+ static boolean isCecTransportMessage(int opcode) {
+ switch (opcode) {
+ case Constants.MESSAGE_REQUEST_CURRENT_LATENCY:
+ case Constants.MESSAGE_REPORT_CURRENT_LATENCY:
+ case Constants.MESSAGE_CDC_MESSAGE:
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 0c55138aa0c8..b0c0c831ac97 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1680,11 +1680,6 @@ public class HdmiControlService extends SystemService {
Slog.e(TAG, "Callback cannot be null");
return;
}
- if (isPowerStandby()) {
- Slog.e(TAG, "Device is in standby. Not handling deviceSelect");
- invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
- return;
- }
HdmiCecLocalDeviceTv tv = tv();
if (tv == null) {
if (!mAddressAllocated) {
@@ -1727,11 +1722,6 @@ public class HdmiControlService extends SystemService {
Slog.e(TAG, "Callback cannot be null");
return;
}
- if (isPowerStandby()) {
- Slog.e(TAG, "Device is in standby. Not handling portSelect");
- invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
- return;
- }
HdmiCecLocalDeviceTv tv = tv();
if (tv != null) {
tv.doManualPortSwitching(portId, callback);
diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java
new file mode 100644
index 000000000000..4d36078e3359
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Feature action that queries the Short Audio Descriptor (SAD) of another device. This action is
+ * initiated from the Android system working as TV device to get the SAD of the connected audio
+ * system device.
+ * <p>
+ * Package-private
+ */
+final class RequestSadAction extends HdmiCecFeatureAction {
+ private static final String TAG = "RequestSadAction";
+
+ // State in which the action is waiting for <Report Short Audio Descriptor>.
+ private static final int STATE_WAITING_FOR_REPORT_SAD = 1;
+
+ private static final List<Integer> ALL_CEC_CODECS = new ArrayList<Integer>(Arrays.asList(
+ Constants.AUDIO_CODEC_LPCM,
+ Constants.AUDIO_CODEC_DD,
+ Constants.AUDIO_CODEC_MPEG1,
+ Constants.AUDIO_CODEC_MP3,
+ Constants.AUDIO_CODEC_MPEG2,
+ Constants.AUDIO_CODEC_AAC,
+ Constants.AUDIO_CODEC_DTS,
+ Constants.AUDIO_CODEC_ATRAC,
+ Constants.AUDIO_CODEC_ONEBITAUDIO,
+ Constants.AUDIO_CODEC_DDP,
+ Constants.AUDIO_CODEC_DTSHD,
+ Constants.AUDIO_CODEC_TRUEHD,
+ Constants.AUDIO_CODEC_DST,
+ Constants.AUDIO_CODEC_WMAPRO,
+ Constants.AUDIO_CODEC_MAX));
+ private static final int MAX_SAD_PER_REQUEST = 4;
+ private static final int RETRY_COUNTER_MAX = 1;
+ private final int mTargetAddress;
+ private final RequestSadCallback mCallback;
+ // List of all valid SADs reported by the target device. Not parsed nor deduplicated.
+ private final List<byte[]> mSupportedSads = new ArrayList<>();
+ private int mQueriedSadCount = 0; // Number of SADs queries that has already been completed
+ private int mTimeoutRetry = 0; // Number of times we have already retried on time-out
+
+ /**
+ * Constructor.
+ *
+ * @param source an instance of {@link HdmiCecLocalDevice}.
+ * @param targetAddress the logical address the SAD is directed at.
+ */
+ RequestSadAction(HdmiCecLocalDevice source, int targetAddress, RequestSadCallback callback) {
+ super(source);
+ mTargetAddress = targetAddress;
+ mCallback = Objects.requireNonNull(callback);
+ }
+
+
+ @Override
+ boolean start() {
+ querySad();
+ return true;
+ }
+
+ private void querySad() {
+ if (mQueriedSadCount >= ALL_CEC_CODECS.size()) {
+ wrapUpAndFinish();
+ return;
+ }
+ int[] codecsToQuery = ALL_CEC_CODECS.subList(mQueriedSadCount,
+ Math.min(ALL_CEC_CODECS.size(), mQueriedSadCount + MAX_SAD_PER_REQUEST))
+ .stream().mapToInt(i -> i).toArray();
+ sendCommand(HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(getSourceAddress(),
+ mTargetAddress, codecsToQuery));
+ mState = STATE_WAITING_FOR_REPORT_SAD;
+ addTimer(mState, HdmiConfig.TIMEOUT_MS);
+ }
+
+ @Override
+ boolean processCommand(HdmiCecMessage cmd) {
+ if (mState != STATE_WAITING_FOR_REPORT_SAD
+ || mTargetAddress != cmd.getSource()) {
+ return false;
+ }
+ if (cmd.getOpcode() == Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR) {
+ if (cmd.getParams() == null || cmd.getParams().length == 0
+ || cmd.getParams().length % 3 != 0) {
+ // Invalid message. Wait for time-out and query again.
+ return true;
+ }
+ for (int i = 0; i < cmd.getParams().length - 2; i += 3) {
+ if (isValidCodec(cmd.getParams()[i])) {
+ byte[] sad = new byte[]{cmd.getParams()[i], cmd.getParams()[i + 1],
+ cmd.getParams()[i + 2]};
+ updateResult(sad);
+ }
+ // Don't include invalid codecs in the result. Don't query again.
+ Slog.w(TAG, "Received invalid codec " + cmd.getParams()[i] + ".");
+ }
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ return true;
+ }
+ if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
+ && (cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR
+ && (cmd.getParams()[1] & 0xFF) == Constants.ABORT_INVALID_OPERAND) {
+ // Queried SADs are not supported
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValidCodec(byte codec) {
+ return Constants.AUDIO_CODEC_NONE < (codec & 0xFF)
+ && (codec & 0xFF) <= Constants.AUDIO_CODEC_MAX;
+ }
+
+ private void updateResult(byte[] sad) {
+ mSupportedSads.add(sad);
+ }
+
+ @Override
+ void handleTimerEvent(int state) {
+ if (mState != state) {
+ return;
+ }
+ if (state == STATE_WAITING_FOR_REPORT_SAD) {
+ if (++mTimeoutRetry <= RETRY_COUNTER_MAX) {
+ querySad();
+ return;
+ }
+ mQueriedSadCount += MAX_SAD_PER_REQUEST;
+ mTimeoutRetry = 0;
+ querySad();
+ }
+ }
+
+ private void wrapUpAndFinish() {
+ mCallback.onRequestSadDone(mSupportedSads);
+ finish();
+ }
+
+ /**
+ * Interface used to report result of SAD request.
+ */
+ interface RequestSadCallback {
+ /**
+ * Called when SAD request is done.
+ *
+ * @param sads a list of all supported SADs. It can be an empty list.
+ */
+ void onRequestSadDone(List<byte[]> supportedSads);
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9755bdfb6e0b..c905fe07cf6d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -189,7 +189,7 @@ public class InputManagerService extends IInputManager.Stub
private final InputManagerHandler mHandler;
// Context cache used for loading pointer resources.
- private Context mDisplayContext;
+ private Context mPointerIconDisplayContext;
private final File mDoubleTouchGestureEnableFile;
@@ -839,21 +839,31 @@ public class InputManagerService extends IInputManager.Stub
throw new IllegalArgumentException("mode is invalid");
}
if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
- if (event instanceof MotionEvent) {
- final Context dispCtx = getContextForDisplay(event.getDisplayId());
- final Display display = dispCtx.getDisplay();
+ // Motion events that are pointer events or relative mouse events will need to have the
+ // inverse display rotation applied to them.
+ if (event instanceof MotionEvent
+ && (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
+ || event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE))) {
+ Context displayContext = getContextForDisplay(event.getDisplayId());
+ if (displayContext == null) {
+ displayContext = Objects.requireNonNull(
+ getContextForDisplay(Display.DEFAULT_DISPLAY));
+ }
+ final Display display = displayContext.getDisplay();
final int rotation = display.getRotation();
if (rotation != ROTATION_0) {
final MotionEvent motion = (MotionEvent) event;
// Injections are currently expected to be in the space of the injector (ie.
- // usually assumed to be post-rotated). Thus we need to unrotate into raw
+ // usually assumed to be post-rotated). Thus we need to un-rotate into raw
// input coordinates for dispatch.
final Point sz = new Point();
- display.getRealSize(sz);
- if ((rotation % 2) != 0) {
- final int tmpX = sz.x;
- sz.x = sz.y;
- sz.y = tmpX;
+ if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+ display.getRealSize(sz);
+ if ((rotation % 2) != 0) {
+ final int tmpX = sz.x;
+ sz.x = sz.y;
+ sz.y = tmpX;
+ }
}
motion.applyTransform(MotionEvent.createRotateMatrix(
(4 - rotation), sz.x, sz.y));
@@ -1742,6 +1752,11 @@ public class InputManagerService extends IInputManager.Stub
/** Clean up input window handles of the given display. */
public void onDisplayRemoved(int displayId) {
+ if (mPointerIconDisplayContext != null
+ && mPointerIconDisplayContext.getDisplay().getDisplayId() == displayId) {
+ mPointerIconDisplayContext = null;
+ }
+
nativeDisplayRemoved(mPtr, displayId);
}
@@ -2969,24 +2984,43 @@ public class InputManagerService extends IInputManager.Stub
// Native callback.
private PointerIcon getPointerIcon(int displayId) {
- return PointerIcon.getDefaultIcon(getContextForDisplay(displayId));
+ return PointerIcon.getDefaultIcon(getContextForPointerIcon(displayId));
}
- private Context getContextForDisplay(int displayId) {
- if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) {
- return mDisplayContext;
+ @NonNull
+ private Context getContextForPointerIcon(int displayId) {
+ if (mPointerIconDisplayContext != null
+ && mPointerIconDisplayContext.getDisplay().getDisplayId() == displayId) {
+ return mPointerIconDisplayContext;
+ }
+
+ // Create and cache context for non-default display.
+ mPointerIconDisplayContext = getContextForDisplay(displayId);
+
+ // Fall back to default display if the requested displayId does not exist.
+ if (mPointerIconDisplayContext == null) {
+ mPointerIconDisplayContext = getContextForDisplay(Display.DEFAULT_DISPLAY);
}
+ return mPointerIconDisplayContext;
+ }
+ @Nullable
+ private Context getContextForDisplay(int displayId) {
+ if (displayId == Display.INVALID_DISPLAY) {
+ return null;
+ }
if (mContext.getDisplay().getDisplayId() == displayId) {
- mDisplayContext = mContext;
- return mDisplayContext;
+ return mContext;
}
- // Create and cache context for non-default display.
- final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ final DisplayManager displayManager = Objects.requireNonNull(
+ mContext.getSystemService(DisplayManager.class));
final Display display = displayManager.getDisplay(displayId);
- mDisplayContext = mContext.createDisplayContext(display);
- return mDisplayContext;
+ if (display == null) {
+ return null;
+ }
+
+ return mContext.createDisplayContext(display);
}
// Native callback.
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index 720be826fd38..29aa2a873cc9 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -313,8 +313,13 @@ public class InputShellCommand extends ShellCommand {
injectKeyEvent(event);
if (longpress) {
+ try {
+ Thread.sleep(ViewConfiguration.getLongPressTimeout());
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
// Some long press behavior would check the event time, we set a new event time here.
- final long nextEventTime = now + ViewConfiguration.getGlobalActionKeyTimeout();
+ final long nextEventTime = now + ViewConfiguration.getLongPressTimeout();
injectKeyEvent(KeyEvent.changeTimeRepeat(event, nextEventTime, 1 /* repeatCount */,
KeyEvent.FLAG_LONG_PRESS));
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 35c0e9abf7ba..02bc1e963321 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -58,10 +58,10 @@ import android.annotation.BinderThread;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
-import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.UiThread;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -182,6 +182,7 @@ import com.android.internal.view.IInputSessionCallback;
import com.android.internal.view.InlineSuggestionsRequestInfo;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener;
import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -262,6 +263,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
+ private static final String HANDLER_THREAD_NAME = "android.imms";
/**
* Binding flags for establishing connection to the {@link InputMethodService}.
@@ -1592,7 +1594,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mIPackageManager = AppGlobals.getPackageManager();
mContext = context;
mRes = context.getResources();
- mHandler = new Handler(this);
+ // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading
+ // additional subtypes in switchUserOnHandlerLocked().
+ final ServiceThread thread = new ServiceThread(
+ HANDLER_THREAD_NAME, Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */);
+ thread.start();
+ mHandler = Handler.createAsync(thread.getLooper(), this);
// Note: SettingsObserver doesn't register observers in its constructor.
mSettingsObserver = new SettingsObserver(mHandler);
mIWindowManager = IWindowManager.Stub.asInterface(
@@ -1601,7 +1608,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mImeDisplayValidator = displayId -> mWindowManagerInternal.getDisplayImePolicy(displayId);
- mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
+ mCaller = new HandlerCaller(context, thread.getLooper(), new HandlerCaller.Callback() {
@Override
public void executeMessage(Message msg) {
handleMessage(msg);
@@ -4159,7 +4166,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- void setEnabledSessionInMainThread(SessionState session) {
+ void setEnabledSessionInHandlerThread(SessionState session) {
if (mEnabledSession != session) {
if (mEnabledSession != null && mEnabledSession.session != null) {
try {
@@ -4179,7 +4186,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- @MainThread
+ @UiThread
@Override
public boolean handleMessage(Message msg) {
SomeArgs args;
@@ -4356,7 +4363,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final IInputContext inputContext = (IInputContext) args.arg3;
final EditorInfo editorInfo = (EditorInfo) args.arg4;
try {
- setEnabledSessionInMainThread(session);
+ setEnabledSessionInHandlerThread(session);
session.method.startInput(startInputToken, inputContext, missingMethods,
editorInfo, restarting);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index db2a43f7a00d..2178672cbea9 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -192,9 +192,7 @@ public class LocationEventLog extends LocalEventLog {
/** Logs a new incoming location for a location provider. */
public void logProviderReceivedLocations(String provider, int numLocations) {
- if (D) {
- addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
- }
+ addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
}
/** Logs a location deliver for a client of a location provider. */
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 87982cd996b5..65a3ad0747cd 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -471,7 +471,9 @@ public class MediaSessionService extends SystemService implements Monitor {
for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
SessionsListenerRecord listener = mSessionsListeners.get(i);
try {
- enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
+ String packageName = listener.componentName == null ? null :
+ listener.componentName.getPackageName();
+ enforceMediaPermissions(packageName, listener.pid, listener.uid,
listener.userId);
} catch (SecurityException e) {
Log.i(TAG, "ActiveSessionsListener " + listener.componentName
@@ -593,15 +595,13 @@ public class MediaSessionService extends SystemService implements Monitor {
* for the caller's user</li>
* </ul>
*/
- private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
+ private void enforceMediaPermissions(String packageName, int pid, int uid,
int resolvedUserId) {
if (hasStatusBarServicePermission(pid, uid)) return;
- // TODO: Refactor to use hasMediaControlPermission and hasEnabledNotificationListener
- if (mContext
- .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
- != PackageManager.PERMISSION_GRANTED
- && !isEnabledNotificationListener(compName,
- UserHandle.getUserHandleForUid(uid), resolvedUserId)) {
+ if (hasMediaControlPermission(pid, uid)) return;
+
+ if (packageName == null || !hasEnabledNotificationListener(
+ packageName, UserHandle.getUserHandleForUid(uid), resolvedUserId)) {
throw new SecurityException("Missing permission to control media.");
}
}
@@ -632,29 +632,26 @@ public class MediaSessionService extends SystemService implements Monitor {
}
/**
- * This checks if the component is an enabled notification listener for the
+ * This checks if the given package has an enabled notification listener for the
* specified user. Enabled components may only operate on behalf of the user
* they're running as.
*
- * @param compName The component that is enabled.
+ * @param packageName The package name.
* @param userHandle The user handle of the caller.
* @param forUserId The user id they're making the request on behalf of.
- * @return True if the component is enabled, false otherwise
+ * @return True if the app has an enabled notification listener for the user, false otherwise
*/
- private boolean isEnabledNotificationListener(ComponentName compName, UserHandle userHandle,
- int forUserId) {
+ private boolean hasEnabledNotificationListener(String packageName,
+ UserHandle userHandle, int forUserId) {
if (userHandle.getIdentifier() != forUserId) {
// You may not access another user's content as an enabled listener.
return false;
}
if (DEBUG) {
- Log.d(TAG, "Checking if enabled notification listener " + compName);
- }
- if (compName != null) {
- return mNotificationManager.hasEnabledNotificationListener(compName.getPackageName(),
- userHandle);
+ Log.d(TAG, "Checking whether the package " + packageName + " has an"
+ + " enabled notification listener.");
}
- return false;
+ return mNotificationManager.hasEnabledNotificationListener(packageName, userHandle);
}
/*
@@ -1237,16 +1234,16 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
- public MediaSession.Token getMediaKeyEventSession() {
+ public MediaSession.Token getMediaKeyEventSession(final String packageName) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " get the media key event session");
- }
+ enforcePackageName(packageName, uid);
+ enforceMediaPermissions(packageName, pid, uid, userId);
+
MediaSessionRecordImpl record;
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1268,16 +1265,16 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
- public String getMediaKeyEventSessionPackageName() {
+ public String getMediaKeyEventSessionPackageName(final String packageName) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " get the media key event session package");
- }
+ enforcePackageName(packageName, uid);
+ enforceMediaPermissions(packageName, pid, uid, userId);
+
MediaSessionRecordImpl record;
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1588,20 +1585,22 @@ public class MediaSessionService extends SystemService implements Monitor {
@Override
public void addOnMediaKeyEventSessionChangedListener(
- final IOnMediaKeyEventSessionChangedListener listener) {
+ final IOnMediaKeyEventSessionChangedListener listener,
+ final String packageName) {
if (listener == null) {
- Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+ Log.w(TAG, "addOnMediaKeyEventSessionChangedListener: listener is null, ignoring");
return;
}
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ final int userId = userHandle.getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " add MediaKeyEventSessionChangedListener");
- }
+ enforcePackageName(packageName, uid);
+ enforceMediaPermissions(packageName, pid, uid, userId);
+
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null || user.mFullUserId != userId) {
@@ -1611,7 +1610,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
user.addOnMediaKeyEventSessionChangedListenerLocked(listener, uid);
Log.d(TAG, "The MediaKeyEventSessionChangedListener (" + listener.asBinder()
- + ") is added by " + getCallingPackageName(uid));
+ + ") is added by " + packageName);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -1622,18 +1621,16 @@ public class MediaSessionService extends SystemService implements Monitor {
public void removeOnMediaKeyEventSessionChangedListener(
final IOnMediaKeyEventSessionChangedListener listener) {
if (listener == null) {
- Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: lister is null, ignoring");
+ Log.w(TAG, "removeOnMediaKeyEventSessionChangedListener: listener is null,"
+ + " ignoring");
return;
}
+
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
final long token = Binder.clearCallingIdentity();
try {
- if (!hasMediaControlPermission(pid, uid)) {
- throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
- + " remove MediaKeyEventSessionChangedListener");
- }
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null || user.mFullUserId != userId) {
@@ -2116,7 +2113,7 @@ public class MediaSessionService extends SystemService implements Monitor {
int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
// Check if they have the permissions or their component is enabled for the user
// they're calling from.
- enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
+ enforceMediaPermissions(packageName, pid, uid, resolvedUserId);
return resolvedUserId;
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 6ae4dd0a46b9..7889ff219b4e 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -250,6 +250,14 @@ public abstract class ApexManager {
throws PackageManagerException;
/**
+ * Returns {@code ApeInfo} about apex sessions that have been marked ready via
+ * {@link #markStagedSessionReady(int)}
+ *
+ * Returns empty array if there is no staged apex session or if there is any error.
+ */
+ abstract ApexInfo[] getStagedApexInfos(ApexSessionParams params);
+
+ /**
* Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
* applied at next reboot.
*
@@ -758,6 +766,19 @@ public abstract class ApexManager {
}
@Override
+ ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+ try {
+ return waitForApexService().getStagedApexInfos(params);
+ } catch (RemoteException re) {
+ Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
+ return new ApexInfo[0];
+ }
+ }
+
+ @Override
void markStagedSessionReady(int sessionId) throws PackageManagerException {
try {
waitForApexService().markStagedSessionReady(sessionId);
@@ -1250,6 +1271,11 @@ public abstract class ApexManager {
}
@Override
+ ApexInfo[] getStagedApexInfos(ApexSessionParams params) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
void markStagedSessionReady(int sessionId) {
throw new UnsupportedOperationException();
}
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index e87dbed9d58a..45ce3980d543 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -1207,7 +1207,10 @@ final class InstallParams extends HandlerParams {
// Check for shared user id changes
String invalidPackageName = null;
if (!Objects.equals(oldPackage.getSharedUserId(),
- parsedPackage.getSharedUserId())) {
+ parsedPackage.getSharedUserId())
+ // Don't mark as invalid if the app is trying to
+ // leave a sharedUserId
+ && parsedPackage.getSharedUserId() != null) {
invalidPackageName = parsedPackage.getPackageName();
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index fdbcf850cbbd..3d63dcf7868f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2615,11 +2615,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
- if (returnCode == INSTALL_SUCCEEDED) {
- onVerificationComplete();
- } else {
- onSessionVerificationFailure(returnCode, msg);
- }
+ mHandler.post(() -> {
+ if (returnCode == INSTALL_SUCCEEDED) {
+ onVerificationComplete();
+ } else {
+ onSessionVerificationFailure(returnCode, msg);
+ }
+ });
}
};
} else {
@@ -2639,6 +2641,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mInstallSource, mInstallerUid, mSigningDetails, sessionId, mPackageLite, mPm);
}
+ @WorkerThread
private void onVerificationComplete() {
// APK verification is done. Continue the installation depending on whether it is a
// staged session or not. For a staged session, we will hand it over to the staging
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c9e48291fcb5..d2c15ab23c83 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -289,6 +289,7 @@ import android.util.MathUtils;
import android.util.PackageUtils;
import android.util.Pair;
import android.util.PrintStreamPrinter;
+import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -327,6 +328,7 @@ import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
+import com.android.server.IntentResolver;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.PackageWatchdog;
@@ -701,6 +703,20 @@ public class PackageManagerService extends IPackageManager.Stub
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
private static final long ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES = 142191088;
+ /**
+ * Components of apps targeting Android T and above will stop receiving intents from
+ * external callers that do not match its declared intent filters.
+ *
+ * When an app registers an exported component in its manifest and adds an <intent-filter>,
+ * the component can be started by any intent - even those that do not match the intent filter.
+ * This has proven to be something that many developers find counterintuitive.
+ * Without checking the intent when the component is started, in some circumstances this can
+ * allow 3P apps to trigger internal-only functionality.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+ private static final long ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS = 161252188;
+
public static final String PLATFORM_PACKAGE_NAME = "android";
static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -2160,9 +2176,11 @@ public class PackageManagerService extends IPackageManager.Stub
false /* requireFullPermission */, false /* checkShell */,
"query intent activities");
final String pkgName = intent.getPackage();
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
@@ -2172,8 +2190,9 @@ public class PackageManagerService extends IPackageManager.Stub
comp != null || pkgName != null /*onlyExposedExplicitly*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
flags));
+ List<ResolveInfo> list = Collections.emptyList();
+ boolean skipPostResolution = false;
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
// When specifying an explicit component, we prevent the activity from being
@@ -2216,35 +2235,45 @@ public class PackageManagerService extends IPackageManager.Stub
if (!blockInstantResolution && !blockNormalResolution) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, filterCallingUid);
}
}
-
- return applyPostResolutionFilter(
- list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
- resolveForStart,
- userId, intent);
+ } else {
+ QueryIntentActivitiesResult lockedResult =
+ queryIntentActivitiesInternalBody(
+ intent, resolvedType, flags, filterCallingUid, userId,
+ resolveForStart, allowDynamicSplits, pkgName, instantAppPkgName);
+ if (lockedResult.answer != null) {
+ skipPostResolution = true;
+ list = lockedResult.answer;
+ } else {
+ if (lockedResult.addInstant) {
+ String callingPkgName = getInstantAppPackageName(filterCallingUid);
+ boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+ lockedResult.result = maybeAddInstantAppInstaller(
+ lockedResult.result, intent, resolvedType, flags,
+ userId, resolveForStart, isRequesterInstantApp);
+ }
+ if (lockedResult.sortResult) {
+ lockedResult.result.sort(RESOLVE_PRIORITY_SORTER);
+ }
+ list = lockedResult.result;
+ }
}
- QueryIntentActivitiesResult lockedResult =
- queryIntentActivitiesInternalBody(
- intent, resolvedType, flags, filterCallingUid, userId, resolveForStart,
- allowDynamicSplits, pkgName, instantAppPkgName);
- if (lockedResult.answer != null) {
- return lockedResult.answer;
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, filterCallingUid);
}
- if (lockedResult.addInstant) {
- String callingPkgName = getInstantAppPackageName(filterCallingUid);
- boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
- lockedResult.result = maybeAddInstantAppInstaller(lockedResult.result, intent,
- resolvedType, flags, userId, resolveForStart, isRequesterInstantApp);
- }
- if (lockedResult.sortResult) {
- Collections.sort(lockedResult.result, RESOLVE_PRIORITY_SORTER);
- }
- return applyPostResolutionFilter(
- lockedResult.result, instantAppPkgName, allowDynamicSplits, filterCallingUid,
+ return skipPostResolution ? list : applyPostResolutionFilter(
+ list, instantAppPkgName, allowDynamicSplits, filterCallingUid,
resolveForStart, userId, intent);
}
@@ -2267,15 +2296,17 @@ public class PackageManagerService extends IPackageManager.Stub
final String instantAppPkgName = getInstantAppPackageName(callingUid);
flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
}
+ List<ResolveInfo> list = Collections.emptyList();
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ServiceInfo si = getServiceInfo(comp, flags, userId);
if (si != null) {
// When specifying an explicit component, we prevent the service from being
@@ -2308,14 +2339,26 @@ public class PackageManagerService extends IPackageManager.Stub
if (!blockInstantResolution && !blockNormalResolution) {
final ResolveInfo ri = new ResolveInfo();
ri.serviceInfo = si;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, intent, resolvedType, callingUid);
}
}
- return list;
+ } else {
+ list = queryIntentServicesInternalBody(intent, resolvedType, flags,
+ userId, callingUid, instantAppPkgName);
}
- return queryIntentServicesInternalBody(intent, resolvedType, flags,
- userId, callingUid, instantAppPkgName);
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, false, originalIntent, resolvedType, callingUid);
+ }
+
+ return list;
}
protected @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
@@ -5544,10 +5587,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
- private static final ThreadLocal<ThreadComputer> sThreadComputer = new ThreadLocal<>() {
- @Override protected ThreadComputer initialValue() {
- return new ThreadComputer();
- }};
+ private static final ThreadLocal<ThreadComputer> sThreadComputer =
+ ThreadLocal.withInitial(ThreadComputer::new);
/**
* This lock is used to make reads from {@link #sSnapshotInvalid} and
@@ -8136,7 +8177,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
if (matches.size() == 1) {
return matches.get(0).getComponentInfo().packageName;
} else if (matches.size() == 0) {
@@ -8232,7 +8273,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
ResolveInfo best = null;
final int N = matches.size();
for (int i = 0; i < N; i++) {
@@ -8260,7 +8301,7 @@ public class PackageManagerService extends IPackageManager.Stub
Intent intent = new Intent(Intent.ACTION_DOMAINS_NEED_VERIFICATION);
List<ResolveInfo> matches = queryIntentReceiversInternal(intent, null,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/);
+ UserHandle.USER_SYSTEM, Binder.getCallingUid());
ResolveInfo best = null;
final int N = matches.size();
for (int i = 0; i < N; i++) {
@@ -10939,30 +10980,32 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentReceivers(Intent intent,
String resolvedType, int flags, int userId) {
- return new ParceledListSlice<>(
- queryIntentReceiversInternal(intent, resolvedType, flags, userId,
- false /*allowDynamicSplits*/));
+ return new ParceledListSlice<>(queryIntentReceiversInternal(intent, resolvedType,
+ flags, userId, Binder.getCallingUid()));
}
+ // In this method, we have to know the actual calling UID, but in some cases Binder's
+ // call identity is removed, so the UID has to be passed in explicitly.
private @NonNull List<ResolveInfo> queryIntentReceiversInternal(Intent intent,
- String resolvedType, int flags, int userId, boolean allowDynamicSplits) {
+ String resolvedType, int flags, int userId, int filterCallingUid) {
if (!mUserManager.exists(userId)) return Collections.emptyList();
- final int callingUid = Binder.getCallingUid();
- enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+ enforceCrossUserPermission(filterCallingUid, userId, false /*requireFullPermission*/,
false /*checkShell*/, "query intent receivers");
- final String instantAppPkgName = getInstantAppPackageName(callingUid);
- flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/,
+ final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+ flags = updateFlagsForResolve(flags, userId, filterCallingUid, false /*includeInstantApps*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
flags));
+ Intent originalIntent = null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
+ originalIntent = intent;
intent = intent.getSelector();
comp = intent.getComponent();
}
}
+ List<ResolveInfo> list = Collections.emptyList();
if (comp != null) {
- final List<ResolveInfo> list = new ArrayList<>(1);
final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
if (ai != null) {
// When specifying an explicit component, we prevent the activity from being
@@ -10998,40 +11041,44 @@ public class PackageManagerService extends IPackageManager.Stub
if (!blockResolution) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
+ list = new ArrayList<>(1);
list.add(ri);
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, true, intent, resolvedType, filterCallingUid);
}
}
- return applyPostResolutionFilter(
- list, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
- }
-
- // reader
- synchronized (mLock) {
- String pkgName = intent.getPackage();
- if (pkgName == null) {
- final List<ResolveInfo> result =
- mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
- if (result == null) {
- return Collections.emptyList();
+ } else {
+ // reader
+ synchronized (mLock) {
+ String pkgName = intent.getPackage();
+ if (pkgName == null) {
+ final List<ResolveInfo> result =
+ mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
+ if (result != null) {
+ list = result;
+ }
}
- return applyPostResolutionFilter(
- result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
- }
- final AndroidPackage pkg = mPackages.get(pkgName);
- if (pkg != null) {
- final List<ResolveInfo> result = mComponentResolver.queryReceivers(
- intent, resolvedType, flags, pkg.getReceivers(), userId);
- if (result == null) {
- return Collections.emptyList();
+ final AndroidPackage pkg = mPackages.get(pkgName);
+ if (pkg != null) {
+ final List<ResolveInfo> result = mComponentResolver.queryReceivers(
+ intent, resolvedType, flags, pkg.getReceivers(), userId);
+ if (result != null) {
+ list = result;
+ }
}
- return applyPostResolutionFilter(
- result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
- intent);
}
- return Collections.emptyList();
}
+
+ if (originalIntent != null) {
+ // We also have to ensure all components match the original intent
+ applyEnforceIntentFilterMatching(
+ mInjector.getCompatibility(), mComponentResolver,
+ list, true, originalIntent, resolvedType, filterCallingUid);
+ }
+
+ return applyPostResolutionFilter(
+ list, instantAppPkgName, false, filterCallingUid, false, userId, intent);
}
@Override
@@ -11073,6 +11120,68 @@ public class PackageManagerService extends IPackageManager.Stub
includeInstantApps);
}
+ // Static to give access to ComputeEngine
+ private static void applyEnforceIntentFilterMatching(
+ PlatformCompat compat, ComponentResolver resolver,
+ List<ResolveInfo> resolveInfos, boolean isReceiver,
+ Intent intent, String resolvedType, int filterCallingUid) {
+ // Do not enforce filter matching when the caller is system or root.
+ // see ActivityManager#checkComponentPermission(String, int, int, boolean)
+ if (filterCallingUid == Process.ROOT_UID || filterCallingUid == Process.SYSTEM_UID) {
+ return;
+ }
+
+ final Printer logPrinter = DEBUG_INTENT_MATCHING
+ ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
+ : null;
+
+ for (int i = resolveInfos.size() - 1; i >= 0; --i) {
+ final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
+
+ // Do not enforce filter matching when the caller is the same app
+ if (info.applicationInfo.uid == filterCallingUid) {
+ continue;
+ }
+
+ // Only enforce filter matching if target app's target SDK >= T
+ if (!compat.isChangeEnabledInternal(
+ ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
+ continue;
+ }
+
+ final ParsedMainComponent comp;
+ if (info instanceof ActivityInfo) {
+ if (isReceiver) {
+ comp = resolver.getReceiver(info.getComponentName());
+ } else {
+ comp = resolver.getActivity(info.getComponentName());
+ }
+ } else if (info instanceof ServiceInfo) {
+ comp = resolver.getService(info.getComponentName());
+ } else {
+ // This shall never happen
+ throw new IllegalArgumentException("Unsupported component type");
+ }
+
+ if (comp.getIntents().isEmpty()) {
+ continue;
+ }
+
+ final boolean match = comp.getIntents().stream().anyMatch(
+ f -> IntentResolver.intentMatchesFilter(f, intent, resolvedType));
+ if (!match) {
+ Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
+ Slog.w(TAG, "Access blocked: " + comp.getComponentName());
+ if (DEBUG_INTENT_MATCHING) {
+ Slog.v(TAG, "Component intent filters:");
+ comp.getIntents().forEach(f -> f.dump(logPrinter, " "));
+ Slog.v(TAG, "-----------------------------");
+ }
+ resolveInfos.remove(i);
+ }
+ }
+ }
+
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentContentProviders(Intent intent,
String resolvedType, int flags, int userId) {
@@ -13528,10 +13637,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
-
-
-
-
/**
* Returns the actual scan flags depending upon the state of the other settings.
* <p>Updated system applications will not have the following flags set
@@ -13699,10 +13804,10 @@ public class PackageManagerService extends IPackageManager.Stub
*/
boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
throws PackageManagerException {
- if (!result.mExistingSettingCopied) {
+ if (!result.mExistingSettingCopied || result.mNeedsNewAppId) {
// THROWS: when we can't allocate a user id. add call to check if there's
// enough space to ensure we won't throw; otherwise, don't modify state
- return mSettings.registerAppIdLPw(result.mPkgSetting);
+ return mSettings.registerAppIdLPw(result.mPkgSetting, result.mNeedsNewAppId);
}
return false;
}
@@ -14072,15 +14177,25 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ boolean leavingSharedUser = false;
+
if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + parsedPackage.getPackageName() + " shared user changed from "
- + (pkgSetting.sharedUser != null
- ? pkgSetting.sharedUser.name : "<nothing>")
- + " to "
- + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
- + "; replacing with new");
- pkgSetting = null;
+ if (pkgSetting.sharedUser != null && sharedUserSetting == null) {
+ leavingSharedUser = true;
+ // Log that something is leaving shareduid and keep going
+ Slog.i(TAG,
+ "Package " + parsedPackage.getPackageName() + " shared user changed from "
+ + pkgSetting.sharedUser.name + " to " + "<nothing>.");
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Package " + parsedPackage.getPackageName() + " shared user changed from "
+ + (pkgSetting.sharedUser != null
+ ? pkgSetting.sharedUser.name : "<nothing>")
+ + " to "
+ + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
+ + "; replacing with new");
+ pkgSetting = null;
+ }
}
String[] usesStaticLibraries = null;
@@ -14356,7 +14471,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
- !createNewPackage /* existingSettingCopied */, staticSharedLibraryInfo,
+ !createNewPackage /* existingSettingCopied */,
+ leavingSharedUser /* needsNewAppId */, staticSharedLibraryInfo,
dynamicSharedLibraryInfos);
}
@@ -21735,6 +21851,10 @@ public class PackageManagerService extends IPackageManager.Stub
continue;
}
+ // TODO@ashfall check ScanResult.mNeedsNewAppId, and if true instead
+ // of creating app data, migrate / change ownership of existing
+ // data.
+
if (ps.getInstalled(user.id)) {
// TODO: when user data is locked, mark that we're still dirty
prepareAppData(batch, pkg, user.id, flags).thenRun(() -> {
@@ -22399,7 +22519,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
boolean readPermissionStateForUser(@UserIdInt int userId) {
- synchronized (mPackages) {
+ synchronized (mLock) {
mPermissionManager.writeLegacyPermissionStateTEMP();
mSettings.readPermissionStateForUserSyncLPr(userId);
mPermissionManager.readLegacyPermissionStateTEMP();
@@ -22471,7 +22591,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (packageName == null || alias == null) {
return null;
}
- synchronized(mLock) {
+ synchronized (mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
if (pkg == null
|| shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -22518,7 +22638,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (packageName == null || ks == null) {
return false;
}
- synchronized(mLock) {
+ synchronized (mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
if (pkg == null
|| shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()),
@@ -23401,6 +23521,13 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
+ public List<ResolveInfo> queryIntentReceivers(Intent intent,
+ String resolvedType, int flags, int filterCallingUid, int userId) {
+ return PackageManagerService.this.queryIntentReceiversInternal(intent, resolvedType,
+ flags, userId, filterCallingUid);
+ }
+
+ @Override
public List<ResolveInfo> queryIntentServices(
Intent intent, int flags, int callingUid, int userId) {
final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 3d1a841fd5e7..717f3d57ec38 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -176,6 +176,10 @@ public abstract class PackageSettingBase extends SettingBase {
name = orig.name;
realName = orig.realName;
doCopy(orig);
+ // Clone the user states.
+ for (int i = 0; i < mUserState.size(); i++) {
+ mUserState.put(mUserState.keyAt(i), new PackageUserState(mUserState.valueAt(i)));
+ }
}
public void setInstallerPackageName(String packageName) {
@@ -314,6 +318,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setInstalled(boolean inst, int userId) {
modifyUserState(userId).installed = inst;
+ onChanged();
}
boolean getInstalled(int userId) {
@@ -326,6 +331,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setInstallReason(int installReason, int userId) {
modifyUserState(userId).installReason = installReason;
+ onChanged();
}
int getUninstallReason(int userId) {
@@ -334,10 +340,13 @@ public abstract class PackageSettingBase extends SettingBase {
void setUninstallReason(@UninstallReason int uninstallReason, int userId) {
modifyUserState(userId).uninstallReason = uninstallReason;
+ onChanged();
}
boolean setOverlayPaths(OverlayPaths overlayPaths, int userId) {
- return modifyUserState(userId).setOverlayPaths(overlayPaths);
+ boolean returnValue = modifyUserState(userId).setOverlayPaths(overlayPaths);
+ onChanged();
+ return returnValue;
}
OverlayPaths getOverlayPaths(int userId) {
@@ -346,7 +355,10 @@ public abstract class PackageSettingBase extends SettingBase {
boolean setOverlayPathsForLibrary(String libName, OverlayPaths overlayPaths,
int userId) {
- return modifyUserState(userId).setSharedLibraryOverlayPaths(libName, overlayPaths);
+ boolean returnValue = modifyUserState(userId)
+ .setSharedLibraryOverlayPaths(libName, overlayPaths);
+ onChanged();
+ return returnValue;
}
Map<String, OverlayPaths> getOverlayPathsForLibrary(int userId) {
@@ -395,6 +407,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setCeDataInode(long ceDataInode, int userId) {
modifyUserState(userId).ceDataInode = ceDataInode;
+ onChanged();
}
boolean getStopped(int userId) {
@@ -403,6 +416,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setStopped(boolean stop, int userId) {
modifyUserState(userId).stopped = stop;
+ onChanged();
}
boolean getNotLaunched(int userId) {
@@ -411,6 +425,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setNotLaunched(boolean stop, int userId) {
modifyUserState(userId).notLaunched = stop;
+ onChanged();
}
boolean getHidden(int userId) {
@@ -419,6 +434,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setHidden(boolean hidden, int userId) {
modifyUserState(userId).hidden = hidden;
+ onChanged();
}
int getDistractionFlags(int userId) {
@@ -427,6 +443,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setDistractionFlags(int distractionFlags, int userId) {
modifyUserState(userId).distractionFlags = distractionFlags;
+ onChanged();
}
boolean getSuspended(int userId) {
@@ -487,6 +504,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setInstantApp(boolean instantApp, int userId) {
modifyUserState(userId).instantApp = instantApp;
+ onChanged();
}
boolean getVirtulalPreload(int userId) {
@@ -495,6 +513,7 @@ public abstract class PackageSettingBase extends SettingBase {
void setVirtualPreload(boolean virtualPreload, int userId) {
modifyUserState(userId).virtualPreload = virtualPreload;
+ onChanged();
}
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
@@ -547,20 +566,24 @@ public abstract class PackageSettingBase extends SettingBase {
void setEnabledComponents(ArraySet<String> components, int userId) {
modifyUserState(userId).enabledComponents = components;
+ onChanged();
}
void setDisabledComponents(ArraySet<String> components, int userId) {
modifyUserState(userId).disabledComponents = components;
+ onChanged();
}
void setEnabledComponentsCopy(ArraySet<String> components, int userId) {
modifyUserState(userId).enabledComponents = components != null
? new ArraySet<String>(components) : null;
+ onChanged();
}
void setDisabledComponentsCopy(ArraySet<String> components, int userId) {
modifyUserState(userId).disabledComponents = components != null
? new ArraySet<String>(components) : null;
+ onChanged();
}
PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
@@ -582,10 +605,12 @@ public abstract class PackageSettingBase extends SettingBase {
void addDisabledComponent(String componentClassName, int userId) {
modifyUserStateComponents(userId, true, false).disabledComponents.add(componentClassName);
+ onChanged();
}
void addEnabledComponent(String componentClassName, int userId) {
modifyUserStateComponents(userId, false, true).enabledComponents.add(componentClassName);
+ onChanged();
}
boolean enableComponentLPw(String componentClassName, int userId) {
@@ -593,6 +618,9 @@ public abstract class PackageSettingBase extends SettingBase {
boolean changed = state.disabledComponents != null
? state.disabledComponents.remove(componentClassName) : false;
changed |= state.enabledComponents.add(componentClassName);
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -601,6 +629,9 @@ public abstract class PackageSettingBase extends SettingBase {
boolean changed = state.enabledComponents != null
? state.enabledComponents.remove(componentClassName) : false;
changed |= state.disabledComponents.add(componentClassName);
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -610,6 +641,9 @@ public abstract class PackageSettingBase extends SettingBase {
? state.disabledComponents.remove(componentClassName) : false;
changed |= state.enabledComponents != null
? state.enabledComponents.remove(componentClassName) : false;
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -701,6 +735,7 @@ public abstract class PackageSettingBase extends SettingBase {
PackageSettingBase setPath(@NonNull File path) {
this.mPath = path;
this.mPathString = path.toString();
+ onChanged();
return this;
}
@@ -722,7 +757,9 @@ public abstract class PackageSettingBase extends SettingBase {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public boolean overrideNonLocalizedLabelAndIcon(@NonNull ComponentName component,
@Nullable String label, @Nullable Integer icon, @UserIdInt int userId) {
- return modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
+ boolean returnValue = modifyUserState(userId).overrideLabelAndIcon(component, label, icon);
+ onChanged();
+ return returnValue;
}
/**
@@ -732,6 +769,7 @@ public abstract class PackageSettingBase extends SettingBase {
*/
public void resetOverrideComponentLabelIcon(@UserIdInt int userId) {
modifyUserState(userId).resetOverrideComponentLabelIcon();
+ onChanged();
}
/**
@@ -741,6 +779,7 @@ public abstract class PackageSettingBase extends SettingBase {
*/
public void setSplashScreenTheme(@UserIdInt int userId, @Nullable String themeName) {
modifyUserState(userId).splashScreenTheme = themeName;
+ onChanged();
}
/**
@@ -776,6 +815,7 @@ public abstract class PackageSettingBase extends SettingBase {
*/
public void setStatesOnCommit() {
incrementalStates.onCommit(IncrementalManager.isIncrementalPath(getPathString()));
+ onChanged();
}
/**
@@ -783,6 +823,7 @@ public abstract class PackageSettingBase extends SettingBase {
*/
public void setIncrementalStatesCallback(IncrementalStates.Callback callback) {
incrementalStates.setCallback(callback);
+ onChanged();
}
/**
@@ -791,6 +832,7 @@ public abstract class PackageSettingBase extends SettingBase {
*/
public void setLoadingProgress(float progress) {
incrementalStates.setProgress(progress);
+ onChanged();
}
public long getFirstInstallTime() {
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index a1e505199a96..76364fe6e703 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -174,7 +174,16 @@ class PackageSignatures {
if (index >= 0 && index < readSignatures.size()) {
Signature sig = readSignatures.get(index);
if (sig != null) {
- signatures.add(sig);
+ // An app using a shared signature in its signing lineage
+ // can have unique capabilities assigned to this previous
+ // signer; create a new instance of this Signature to ensure
+ // its flags do not overwrite those of the instance from
+ // readSignatures.
+ if (isPastSigs) {
+ signatures.add(new Signature(sig));
+ } else {
+ signatures.add(sig);
+ }
signatureParsed = true;
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java
index 6915a500210c..34f86baf8cb8 100644
--- a/services/core/java/com/android/server/pm/ScanResult.java
+++ b/services/core/java/com/android/server/pm/ScanResult.java
@@ -36,6 +36,11 @@ final class ScanResult {
*/
public final boolean mExistingSettingCopied;
/**
+ * Whether or not the original PackageSetting needs to be updated with
+ * a new uid. Useful when leaving a sharedUserID.
+ */
+ public final boolean mNeedsNewAppId;
+ /**
* The final package settings. This may be the same object passed in
* the {@link ScanRequest}, but, with modified values.
*/
@@ -52,6 +57,7 @@ final class ScanResult {
ScanRequest request, boolean success,
@Nullable PackageSetting pkgSetting,
@Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
+ boolean needsNewAppId,
SharedLibraryInfo staticSharedLibraryInfo,
List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
mRequest = request;
@@ -59,6 +65,7 @@ final class ScanResult {
mPkgSetting = pkgSetting;
mChangedAbiCodePath = changedAbiCodePath;
mExistingSettingCopied = existingSettingCopied;
+ mNeedsNewAppId = needsNewAppId;
mStaticSharedLibraryInfo = staticSharedLibraryInfo;
mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3995cc6fd00d..902263a93833 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1126,9 +1126,9 @@ public final class Settings implements Watchable, Snappable {
* already registered.
* @throws PackageManagerException If a user ID could not be allocated.
*/
- boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+ boolean registerAppIdLPw(PackageSetting p, boolean forceNew) throws PackageManagerException {
final boolean createdNew;
- if (p.appId == 0) {
+ if (p.appId == 0 || forceNew) {
// Assign new user ID
p.appId = acquireAndRegisterNewAppIdLPw(p);
createdNew = true;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0d909a949a14..e8182e07ba4d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -5087,8 +5087,11 @@ public class UserManagerService extends IUserManager.Stub {
Binder.restoreCallingIdentity(ident);
}
}
- pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s%s%s\n", i, user.id,
+ pw.printf("%d: id=%d, name=%s, type=%s, flags=%s%s%s%s%s%s%s%s%s\n",
+ i,
+ user.id,
user.name,
+ user.userType.replace("android.os.usertype.", ""),
UserInfo.flagsToString(user.flags),
hasParent ? " (parentId=" + user.profileGroupId + ")" : "",
running ? " (running)" : "",
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 3eb4bde6c67d..2fcc4b2fae59 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -55,6 +55,7 @@ import java.util.UUID;
*/
public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
+ @NonNull
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
@NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
@@ -70,6 +71,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
* this case only cares about
* volumeUuid, just fake it rather than having separate method paths.
*/
+ @NonNull
public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
return ((ParsedPackage) PackageImpl.forTesting(packageName)
.setVolumeUuid(volumeUuid)
@@ -77,11 +79,13 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
.hideAsFinal();
}
+ @NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName) {
return forTesting(packageName, "");
}
+ @NonNull
@VisibleForTesting
public static ParsingPackage forTesting(String packageName, String baseCodePath) {
return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
@@ -568,6 +572,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
assignDerivedFields();
}
+ @NonNull
public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
@Override
public PackageImpl createFromParcel(Parcel source) {
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 6014d0cee171..2491565dd376 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -255,7 +255,11 @@ public final class HintManagerService extends SystemService {
private boolean checkTidValid(int uid, int tgid, int [] tids) {
// Make sure all tids belongs to the same UID (including isolated UID),
// tids can belong to different application processes.
- List<Integer> eligiblePids = mAmInternal.getIsolatedProcesses(uid);
+ List<Integer> eligiblePids = null;
+ // To avoid deadlock, do not call into AMS if the call is from system.
+ if (uid != Process.SYSTEM_UID) {
+ eligiblePids = mAmInternal.getIsolatedProcesses(uid);
+ }
if (eligiblePids == null) {
eligiblePids = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index c8e36481c738..c7e7784715cd 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -143,10 +143,10 @@ public class AppDataRollbackHelper {
int rollbackId, int appId, String seInfo, int flags) {
if (packageRollbackInfo.isApex()) {
switch (packageRollbackInfo.getRollbackDataPolicy()) {
- case PackageManager.RollbackDataPolicy.WIPE:
+ case PackageManager.ROLLBACK_DATA_POLICY_WIPE:
// TODO: Implement WIPE for apex CE data
break;
- case PackageManager.RollbackDataPolicy.RESTORE:
+ case PackageManager.ROLLBACK_DATA_POLICY_RESTORE:
// For APEX, only restore of CE may be done here.
if ((flags & Installer.FLAG_STORAGE_CE) != 0) {
mApexManager.restoreCeData(
@@ -160,11 +160,11 @@ public class AppDataRollbackHelper {
// APK
try {
switch (packageRollbackInfo.getRollbackDataPolicy()) {
- case PackageManager.RollbackDataPolicy.WIPE:
+ case PackageManager.ROLLBACK_DATA_POLICY_WIPE:
mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(),
userId, flags, 0);
break;
- case PackageManager.RollbackDataPolicy.RESTORE:
+ case PackageManager.ROLLBACK_DATA_POLICY_RESTORE:
mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(),
appId, seInfo, userId, rollbackId, flags);
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 7bf3478ac49e..38e6b2820ad8 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -438,7 +438,7 @@ class Rollback {
for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
if (pkgRollbackInfo.getPackageName().equals(packageName)) {
if (pkgRollbackInfo.getRollbackDataPolicy()
- == PackageManager.RollbackDataPolicy.RESTORE) {
+ == PackageManager.ROLLBACK_DATA_POLICY_RESTORE) {
dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
addAll(pkgRollbackInfo.getSnapshottedUsers(), userIds);
RollbackStore.saveRollback(this);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index f7ed000ac403..a5646247f766 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -800,7 +800,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
// precedence only when it is not the default (i.e. RESTORE). We will remove
// SessionParams#setEnableRollback(boolean, int) and related code when Play has migrated to
// using the manifest to specify the policy.
- if (manifestPolicy != PackageManager.RollbackDataPolicy.RESTORE) {
+ if (manifestPolicy != PackageManager.ROLLBACK_DATA_POLICY_RESTORE) {
return manifestPolicy;
}
return sessionPolicy;
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 6b783f709810..2cfc7856c197 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -447,7 +447,7 @@ class RollbackStore {
// Backward compatibility: no such field for old versions.
final int rollbackDataPolicy = json.optInt("rollbackDataPolicy",
- PackageManager.RollbackDataPolicy.RESTORE);
+ PackageManager.ROLLBACK_DATA_POLICY_RESTORE);
return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
pendingBackups, pendingRestores, isApex, isApkInApex, snapshottedUsers,
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 0c04b075485a..22f0adaee4cf 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -23,7 +23,6 @@ import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.media.IResourceManagerService;
import android.media.tv.TvInputManager;
-import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
@@ -31,6 +30,7 @@ import android.media.tv.tunerresourcemanager.ResourceClientProfile;
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
+import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index e85fa234a4ce..0f4f58b32c1b 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -228,17 +228,20 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
Vibration.Status status = null;
while (!mStepQueue.isEmpty()) {
- long waitTime = mStepQueue.calculateWaitTime();
- if (waitTime <= 0) {
- mStepQueue.consumeNext();
- } else {
- synchronized (mLock) {
+ long waitTime;
+ synchronized (mLock) {
+ waitTime = mStepQueue.calculateWaitTime();
+ if (waitTime > 0) {
try {
mLock.wait(waitTime);
} catch (InterruptedException e) {
}
}
}
+ // If we waited, the queue may have changed, so let the loop run again.
+ if (waitTime <= 0) {
+ mStepQueue.consumeNext();
+ }
Vibration.Status currentStatus = mStop ? Vibration.Status.CANCELLED
: mStepQueue.calculateVibrationStatus(sequentialEffectSize);
if (status == null && currentStatus != Vibration.Status.RUNNING) {
@@ -387,15 +390,13 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
}
/** Returns the time in millis to wait before calling {@link #consumeNext()}. */
+ @GuardedBy("mLock")
public long calculateWaitTime() {
- Step nextStep;
- synchronized (mLock) {
- if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
- // Steps anticipated by vibrator complete callback should be played right away.
- return 0;
- }
- nextStep = mNextSteps.peek();
+ if (!mPendingOnVibratorCompleteSteps.isEmpty()) {
+ // Steps anticipated by vibrator complete callback should be played right away.
+ return 0;
}
+ Step nextStep = mNextSteps.peek();
return nextStep == null ? 0 : nextStep.calculateWaitTime();
}
@@ -603,7 +604,10 @@ final class VibrationThread extends Thread implements IBinder.DeathRecipient {
return false;
}
- /** Returns the time in millis to wait before playing this step. */
+ /**
+ * Returns the time in millis to wait before playing this step. This is performed
+ * while holding the queue lock, so should not rely on potentially slow operations.
+ */
public long calculateWaitTime() {
if (startTime == Long.MAX_VALUE) {
// This step don't have a predefined start time, it's just marked to be executed
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 372d3ecf937a..f1f9e6fc67b8 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -35,6 +35,7 @@ import static com.android.server.accessibility.AccessibilityTraceProto.CALENDAR_
import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_PARAMS;
import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_PKG;
import static com.android.server.accessibility.AccessibilityTraceProto.CALLING_STACKS;
+import static com.android.server.accessibility.AccessibilityTraceProto.CPU_STATS;
import static com.android.server.accessibility.AccessibilityTraceProto.ELAPSED_REALTIME_NANOS;
import static com.android.server.accessibility.AccessibilityTraceProto.LOGGING_TYPE;
import static com.android.server.accessibility.AccessibilityTraceProto.PROCESS_NAME;
@@ -75,6 +76,7 @@ import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -1959,6 +1961,7 @@ final class AccessibilityController {
}
}
+ private static final int CPU_STATS_COUNT = 5;
private static final int BUFFER_CAPACITY = 1024 * 1024 * 12;
private static final String TRACE_FILENAME = "/data/misc/a11ytrace/a11y_trace"
+ WINSCOPE_EXT;
@@ -2230,6 +2233,7 @@ final class AccessibilityController {
mService.dumpDebugLocked(os, WindowTraceLogLevel.ALL);
}
os.end(tokenInner);
+ os.write(CPU_STATS, printCpuStats(reportedTimeStampNanos));
os.end(tokenOuter);
synchronized (mLock) {
@@ -2262,5 +2266,15 @@ final class AccessibilityController {
Slog.e(TAG, "Unable to write buffer to file", e);
}
}
+
+ /**
+ * Returns the string of CPU stats.
+ */
+ private String printCpuStats(long timeStampNanos) {
+ Pair<String, String> stats = mService.mAmInternal.getAppProfileStatsForDebugging(
+ timeStampNanos, CPU_STATS_COUNT);
+
+ return stats.first + stats.second;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 331b8dee4870..675c7eb23f2c 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1197,10 +1197,10 @@ class ActivityClientController extends IActivityClientController.Stub {
final Task task = r.getTask();
isLastRunningActivity = task.topRunningActivity() == r;
- final Intent baseIntent = task.getBaseIntent();
- final boolean activityIsBaseActivity = baseIntent != null
- && r.mActivityComponent.equals(baseIntent.getComponent());
- baseActivityIntent = activityIsBaseActivity ? r.intent : null;
+
+ final boolean isBaseActivity = r.mActivityComponent.equals(task.realActivity);
+ baseActivityIntent = isBaseActivity ? r.intent : null;
+
launchedFromHome = r.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 005a62a208eb..20958aa1c9b1 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -633,6 +633,7 @@ class ActivityMetricsLogger {
if (crossPackage) {
startLaunchTrace(info);
}
+ scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity);
return;
}
@@ -654,13 +655,7 @@ class ActivityMetricsLogger {
// As abort for no process switch.
launchObserverNotifyIntentFailed();
}
- if (launchedActivity.mDisplayContent.isSleeping()) {
- // It is unknown whether the activity can be drawn or not, e.g. it depends on the
- // keyguard states and the attributes or flags set by the activity. If the activity
- // keeps invisible in the grace period, the tracker will be cancelled so it won't get
- // a very long launch time that takes unlocking as the end of launch.
- scheduleCheckActivityToBeDrawn(launchedActivity, UNKNOWN_VISIBILITY_CHECK_DELAY_MS);
- }
+ scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity);
// If the previous transitions are no longer visible, abort them to avoid counting the
// launch time when resuming from back stack. E.g. launch 2 independent tasks in a short
@@ -675,6 +670,16 @@ class ActivityMetricsLogger {
}
}
+ private void scheduleCheckActivityToBeDrawnIfSleeping(@NonNull ActivityRecord r) {
+ if (r.mDisplayContent.isSleeping()) {
+ // It is unknown whether the activity can be drawn or not, e.g. it depends on the
+ // keyguard states and the attributes or flags set by the activity. If the activity
+ // keeps invisible in the grace period, the tracker will be cancelled so it won't get
+ // a very long launch time that takes unlocking as the end of launch.
+ scheduleCheckActivityToBeDrawn(r, UNKNOWN_VISIBILITY_CHECK_DELAY_MS);
+ }
+ }
+
/**
* Notifies the tracker that all windows of the app have been drawn.
*
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 266be6b6bfcf..87b7660508dd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -702,8 +702,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private boolean mInSizeCompatModeForBounds = false;
// Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio().
- // TODO(b/182268157): Aspect ratio can also be applie in resolveFixedOrientationConfiguration
- // but that isn't reflected in this boolean.
private boolean mIsAspectRatioApplied = false;
// Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed
@@ -1181,7 +1179,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
header.run();
}
- String innerPrefix = prefix + " ";
+ String innerPrefix = prefix + " ";
String[] args = new String[0];
if (lastTask != r.getTask()) {
lastTask = r.getTask();
@@ -2446,20 +2444,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- private void removeAppTokenFromDisplay() {
- if (mWmService.mRoot == null) return;
-
- final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
- if (dc == null) {
- Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
- + appToken + " from non-existing displayId=" + getDisplayId());
- return;
- }
- // Resume key dispatching if it is currently paused before we remove the container.
- resumeKeyDispatchingLocked();
- dc.removeAppToken(appToken.asBinder());
- }
-
/**
* Reparents this activity into {@param newTaskFrag} at the provided {@param position}. The
* caller should ensure that the {@param newTaskFrag} is not already the parent of this
@@ -3010,7 +2994,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@interface FinishRequest {}
/**
- * See {@link #finishIfPossible(int, Intent, String, boolean)}
+ * See {@link #finishIfPossible(int, Intent, NeededUriGrants, String, boolean)}
*/
@FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
return finishIfPossible(Activity.RESULT_CANCELED,
@@ -3472,7 +3456,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
setState(DESTROYED, "removeFromHistory");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
detachFromProcess();
- removeAppTokenFromDisplay();
+ // Resume key dispatching if it is currently paused before we remove the container.
+ resumeKeyDispatchingLocked();
+ mDisplayContent.removeAppToken(appToken);
cleanUpActivityServices();
removeUriPermissionsLocked();
@@ -3689,12 +3675,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
void removeImmediately() {
- if (!finishing) {
+ if (mState != DESTROYED) {
+ Slog.w(TAG, "Force remove immediately " + this + " state=" + mState);
// If Task#removeImmediately is called directly with alive activities, ensure that the
// activities are destroyed and detached from process.
destroyImmediately("removeImmediately");
+ // Complete the destruction immediately because this activity will not be found in
+ // hierarchy, it is unable to report completion.
+ destroyed("removeImmediately");
+ } else {
+ onRemovedFromDisplay();
}
- onRemovedFromDisplay();
super.removeImmediately();
}
@@ -6628,17 +6619,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- boolean hasWindowsAlive() {
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- // No need to loop through child windows as the answer should be the same as that of the
- // parent window.
- if (!(mChildren.get(i)).mAppDied) {
- return true;
- }
- }
- return false;
- }
-
void setWillReplaceWindows(boolean animate) {
ProtoLog.d(WM_DEBUG_ADD_REMOVE,
"Marking app token %s with replacing windows.", this);
@@ -7506,11 +7486,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* requested orientation. If not, it may be necessary to letterbox the window.
* @param parentBounds are the new parent bounds passed down to the activity and should be used
* to compute the stable bounds.
- * @param outBounds will store the stable bounds, which are the bounds with insets applied.
- * These should be used to compute letterboxed bounds if orientation is not
- * respected when insets are applied.
+ * @param outStableBounds will store the stable bounds, which are the bounds with insets
+ * applied, if orientation is not respected when insets are applied.
+ * Otherwise outStableBounds will be empty. Stable bounds should be used
+ * to compute letterboxed bounds if orientation is not respected when
+ * insets are applied.
*/
- private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outBounds) {
+ private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outStableBounds) {
+ outStableBounds.setEmpty();
if (mDisplayContent == null) {
return true;
}
@@ -7525,17 +7508,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Compute orientation from stable parent bounds (= parent bounds with insets applied)
final Task task = getTask();
task.calculateInsetFrames(mTmpOutNonDecorBounds /* outNonDecorBounds */,
- outBounds /* outStableBounds */, parentBounds /* bounds */,
+ outStableBounds /* outStableBounds */, parentBounds /* bounds */,
mDisplayContent.getDisplayInfo());
- final int orientationWithInsets = outBounds.height() >= outBounds.width()
+ final int orientationWithInsets = outStableBounds.height() >= outStableBounds.width()
? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
// If orientation does not match the orientation with insets applied, then a
// display rotation will not be enough to respect orientation. However, even if they do
// not match but the orientation with insets applied matches the requested orientation, then
// there is no need to modify the bounds because when insets are applied, the activity will
// have the desired orientation.
- return orientation == orientationWithInsets
+ final boolean orientationRespectedWithInsets = orientation == orientationWithInsets
|| orientationWithInsets == requestedOrientation;
+ if (orientationRespectedWithInsets) {
+ outStableBounds.setEmpty();
+ }
+ return orientationRespectedWithInsets;
}
/**
@@ -7553,9 +7540,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
int windowingMode) {
mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
- final Rect containerBounds = new Rect(parentBounds);
+ final Rect stableBounds = new Rect();
+ // If orientation is respected when insets are applied, then stableBounds will be empty.
boolean orientationRespectedWithInsets =
- orientationRespectedWithInsets(parentBounds, containerBounds);
+ orientationRespectedWithInsets(parentBounds, stableBounds);
if (handlesOrientationChangeFromDescendant() && orientationRespectedWithInsets) {
// No need to letterbox because of fixed orientation. Display will handle
// fixed-orientation requests and a display rotation is enough to respect requested
@@ -7592,71 +7580,68 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
- // TODO(b/182268157) merge aspect ratio logic here and in
- // {@link ActivityRecord#applyAspectRatio}
- // if no aspect ratio constraints are provided, parent aspect ratio is used
- float aspectRatio = computeAspectRatio(parentBounds);
-
- // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
- // set-fixed-orientation-letterbox-aspect-ratio.
- final float letterboxAspectRatioOverride =
- mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
- aspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
- ? letterboxAspectRatioOverride : aspectRatio;
-
- // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in
- // order to use the extra available space.
- final float maxAspectRatio = info.getMaxAspectRatio();
- final float minAspectRatio = info.getMinAspectRatio();
- if (aspectRatio > maxAspectRatio && maxAspectRatio != 0) {
- aspectRatio = maxAspectRatio;
- } else if (aspectRatio < minAspectRatio) {
- aspectRatio = minAspectRatio;
+ // TODO(b/182268157): Explore using only one type of parentBoundsWithInsets, either app
+ // bounds or stable bounds to unify aspect ratio logic.
+ final Rect parentBoundsWithInsets = orientationRespectedWithInsets
+ ? newParentConfig.windowConfiguration.getAppBounds() : stableBounds;
+ final Rect containingBounds = new Rect();
+ final Rect containingBoundsWithInsets = new Rect();
+ // Need to shrink the containing bounds into a square because the parent orientation
+ // does not match the activity requested orientation.
+ if (forcedOrientation == ORIENTATION_LANDSCAPE) {
+ // Landscape is defined as width > height. Make the container respect landscape
+ // orientation by shrinking height to one less than width. Landscape activity will be
+ // vertically centered within parent bounds with insets, so position vertical bounds
+ // within parent bounds with insets to prevent insets from unnecessarily trimming
+ // vertical bounds.
+ final int bottom = Math.min(parentBoundsWithInsets.top + parentBounds.width() - 1,
+ parentBoundsWithInsets.bottom);
+ containingBounds.set(parentBounds.left, parentBoundsWithInsets.top, parentBounds.right,
+ bottom);
+ containingBoundsWithInsets.set(parentBoundsWithInsets.left, parentBoundsWithInsets.top,
+ parentBoundsWithInsets.right, bottom);
+ } else {
+ // Portrait is defined as width <= height. Make the container respect portrait
+ // orientation by shrinking width to match height. Portrait activity will be
+ // horizontally centered within parent bounds with insets, so position horizontal bounds
+ // within parent bounds with insets to prevent insets from unnecessarily trimming
+ // horizontal bounds.
+ final int right = Math.min(parentBoundsWithInsets.left + parentBounds.height(),
+ parentBoundsWithInsets.right);
+ containingBounds.set(parentBoundsWithInsets.left, parentBounds.top, right,
+ parentBounds.bottom);
+ containingBoundsWithInsets.set(parentBoundsWithInsets.left, parentBoundsWithInsets.top,
+ right, parentBoundsWithInsets.bottom);
}
// Store the current bounds to be able to revert to size compat mode values below if needed.
final Rect prevResolvedBounds = new Rect(resolvedBounds);
+ resolvedBounds.set(containingBounds);
- // Compute other dimension based on aspect ratio. Use bounds intersected with insets, stored
- // in containerBounds after calling {@link ActivityRecord#orientationRespectedWithInsets()},
- // to ensure that aspect ratio is respected after insets are applied.
- int activityWidth;
- int activityHeight;
+ // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
+ // set-fixed-orientation-letterbox-aspect-ratio.
+ final float letterboxAspectRatioOverride =
+ mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ final float desiredAspectRatio =
+ letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
+ ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
+ // Apply aspect ratio to resolved bounds
+ mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
+ containingBounds, desiredAspectRatio, true);
+
+ // Vertically center if orientation is landscape. Center within parent bounds with insets
+ // to ensure that insets do not trim height. Bounds will later be horizontally centered in
+ // {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation.
if (forcedOrientation == ORIENTATION_LANDSCAPE) {
- activityWidth = parentBounds.width();
- // Compute height from stable bounds width to ensure orientation respected after insets.
- activityHeight = (int) Math.rint(containerBounds.width() / aspectRatio);
- // Landscape is defined as width > height. To ensure activity is landscape when aspect
- // ratio is close to 1, reduce the height by one pixel.
- if (activityWidth == activityHeight) {
- activityHeight -= 1;
- }
- // Center vertically within stable bounds in landscape to ensure insets do not trim
- // height.
- final int top = containerBounds.centerY() - activityHeight / 2;
- resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + activityHeight);
- } else {
- activityHeight = parentBounds.height();
- // Compute width from stable bounds height to ensure orientation respected after insets.
- activityWidth = (int) Math.rint(containerBounds.height() / aspectRatio);
- // Center horizontally in portrait. For now, align to left and allow
- // {@link ActivityRecord#updateResolvedBoundsHorizontalPosition()} to center
- // horizontally. Exclude left insets from parent to ensure cutout does not trim width.
- final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
- resolvedBounds.set(parentAppBounds.left, parentBounds.top,
- parentAppBounds.left + activityWidth, parentBounds.bottom);
+ final int offsetY = parentBoundsWithInsets.centerY() - resolvedBounds.centerY();
+ resolvedBounds.offset(0, offsetY);
}
if (mCompatDisplayInsets != null) {
mCompatDisplayInsets.getBoundsByRotation(
mTmpBounds, newParentConfig.windowConfiguration.getRotation());
- // Insets may differ between different rotations, for example in the case of a display
- // cutout. To ensure consistent bounds across rotations, compare the activity dimensions
- // minus insets from the rotation the compat bounds were computed in.
- Task.intersectWithInsetsIfFits(mTmpBounds, parentBounds,
- mCompatDisplayInsets.mStableInsets[mCompatDisplayInsets.mOriginalRotation]);
- if (activityWidth != mTmpBounds.width()
- || activityHeight != mTmpBounds.height()) {
+ if (resolvedBounds.width() != mTmpBounds.width()
+ || resolvedBounds.height() != mTmpBounds.height()) {
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
// compat bounds are also from the same fixed orientation letterbox. Otherwise,
// clear the fixed orientation bounds to show app in size compat mode.
@@ -7692,8 +7677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// then they should be aligned later in #updateResolvedBoundsHorizontalPosition().
if (!mTmpBounds.isEmpty()) {
resolvedBounds.set(mTmpBounds);
- // Exclude the horizontal decor area.
- resolvedBounds.left = parentAppBounds.left;
}
if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
// Compute the configuration based on the resolved bounds. If aspect ratio doesn't
@@ -7754,13 +7737,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
- // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in
- // the container app bounds. Otherwise the entire container bounds are available.
- final boolean fillContainer = resolvedBounds.equals(containingBounds);
- if (!fillContainer) {
- // The horizontal position should not cover insets.
- resolvedBounds.left = containingAppBounds.left;
- }
// Use resolvedBounds to compute other override configurations such as appBounds. The bounds
// are calculated in compat container space. The actual position on screen will be applied
@@ -7827,6 +7803,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor
// if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition.
// Above coordinates are in "@" space, now place "*" and "#" to screen space.
+ final boolean fillContainer = resolvedBounds.equals(containingBounds);
final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left;
final int screenPosY = containerBounds.top;
if (screenPosX != 0 || screenPosY != 0) {
@@ -8068,6 +8045,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return true;
}
+ private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
+ Rect containingBounds) {
+ return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
+ 0 /* desiredAspectRatio */, false /* fixedOrientationLetterboxed */);
+ }
+
/**
* Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
* made to outBounds.
@@ -8076,17 +8059,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
*/
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
- Rect containingBounds) {
+ Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
final float maxAspectRatio = info.getMaxAspectRatio();
final Task rootTask = getRootTask();
final float minAspectRatio = info.getMinAspectRatio();
if (task == null || rootTask == null
- || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
- || (maxAspectRatio == 0 && minAspectRatio == 0)
+ || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
+ && !fixedOrientationLetterboxed)
+ || (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
|| isInVrUiMode(getConfiguration())) {
- // We don't enforce aspect ratio if the activity task is in multiwindow unless it
- // is in size-compat mode. We also don't set it if we are in VR mode.
+ // We don't enforce aspect ratio if the activity task is in multiwindow unless it is in
+ // size-compat mode or is letterboxed from fixed orientation. We also don't set it if we
+ // are in VR mode.
return false;
}
@@ -8094,20 +8079,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int containingAppHeight = containingAppBounds.height();
final float containingRatio = computeAspectRatio(containingAppBounds);
+ if (desiredAspectRatio < 1) {
+ desiredAspectRatio = containingRatio;
+ }
+
+ if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) {
+ desiredAspectRatio = maxAspectRatio;
+ } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) {
+ desiredAspectRatio = minAspectRatio;
+ }
+
int activityWidth = containingAppWidth;
int activityHeight = containingAppHeight;
- if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
+ if (containingRatio > desiredAspectRatio) {
if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height
// should be given the aspect ratio.
- activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
+ activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f);
} else {
// Height is the shorter side, so we use that to figure-out what the max. width
// should be given the aspect ratio.
- activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
+ activityWidth = (int) ((activityHeight * desiredAspectRatio) + 0.5f);
}
- } else if (containingRatio < minAspectRatio) {
+ } else if (containingRatio < desiredAspectRatio) {
boolean adjustWidth;
switch (getRequestedConfigurationOrientation()) {
case ORIENTATION_LANDSCAPE:
@@ -8135,9 +8130,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
break;
}
if (adjustWidth) {
- activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
+ activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f);
} else {
- activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
+ activityHeight = (int) ((activityWidth / desiredAspectRatio) + 0.5f);
}
}
@@ -8161,6 +8156,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
outBounds.set(containingBounds.left, containingBounds.top, right, bottom);
+ // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the
+ // container app bounds. Otherwise the entire container bounds are available.
+ if (!outBounds.equals(containingBounds)) {
+ // The horizontal position should not cover insets (e.g. display cutout).
+ outBounds.left = containingAppBounds.left;
+ }
+
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 395b25d7e6ad..3bc6435ae017 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2384,6 +2384,11 @@ class ActivityStarter {
}
mTransientLaunch = mOptions.getTransientLaunch();
mTargetRootTask = Task.fromWindowContainerToken(mOptions.getLaunchRootTask());
+
+ if (inTaskFragment == null) {
+ inTaskFragment = TaskFragment.fromTaskFragmentToken(
+ mOptions.getLaunchTaskFragmentToken(), mService);
+ }
}
mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? sourceRecord : null;
@@ -2677,7 +2682,7 @@ class ActivityStarter {
&& mTargetRootTask != intentTask.getParent().asTask()) {
intentTask.getParent().positionChildAt(POSITION_TOP, intentTask,
false /* includingParents */);
- intentTask = intentTask.getParent().asTask();
+ intentTask = intentTask.getParent().asTaskFragment().getTask();
}
// If the task is in multi-windowing mode, the activity may already be on
// the top (visible to user but not the global top), then the result code
@@ -2779,7 +2784,8 @@ class ActivityStarter {
}
} else {
// Use the child TaskFragment (if any) as the new parent if the activity can be embedded
- final ActivityRecord top = task.topRunningActivity();
+ final ActivityRecord top = task.topRunningActivity(false /* focusableOnly */,
+ false /* includingEmbeddedTask */);
newParent = top != null ? top.getTaskFragment() : task;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 25827cfe6b03..19cf14f70e0a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1908,15 +1908,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r.moveFocusableActivityToTop("setFocusedTask")) {
mRootWindowContainer.resumeFocusedTasksTopActivities();
- } else if (touchedActivity != null && touchedActivity != r
- && touchedActivity.getTask() == r.getTask()
- && touchedActivity.getTaskFragment() != r.getTaskFragment()) {
- // Set the focused app directly since the focused window is not on the
- // top-most TaskFragment of the top-most Task
- final DisplayContent displayContent = touchedActivity.getDisplayContent();
- displayContent.setFocusedApp(touchedActivity);
- mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
- true /* updateInputWindows */);
+ } else if (touchedActivity != null && touchedActivity.isFocusable()) {
+ final TaskFragment parent = touchedActivity.getTaskFragment();
+ if (parent != null && parent.isEmbedded()) {
+ // Set the focused app directly if the focused window is currently embedded
+ final DisplayContent displayContent = touchedActivity.getDisplayContent();
+ displayContent.setFocusedApp(touchedActivity);
+ mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+ true /* updateInputWindows */);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index fd64cf828f15..50ac4330facd 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -352,6 +352,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
*/
private int mVisibilityTransactionDepth;
+ /**
+ * Whether to the visibility updates that started from {@code RootWindowContainer} should be
+ * deferred.
+ */
+ private boolean mDeferRootVisibilityUpdate;
+
private ActivityMetricsLogger mActivityMetricsLogger;
/** Check if placing task or activity on specified display is allowed. */
@@ -2297,6 +2303,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
return mVisibilityTransactionDepth > 0;
}
+ void setDeferRootVisibilityUpdate(boolean deferUpdate) {
+ mDeferRootVisibilityUpdate = deferUpdate;
+ }
+
+ boolean isRootVisibilityUpdateDeferred() {
+ return mDeferRootVisibilityUpdate;
+ }
+
/**
* Called when the state or visibility of an attached activity is changed.
*
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index c869ec67776d..d6b0086d8dd9 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -464,7 +464,8 @@ public class AppTransitionController {
}
final RemoteAnimationAdapter adapter =
getRemoteAnimationOverride(animLpActivity, transit, activityTypes);
- if (adapter != null) {
+ if (adapter != null
+ && mDisplayContent.mAppTransition.getRemoteAnimationController() == null) {
mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(adapter);
}
}
diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java
index 03639449c3df..41d9dbf894f4 100644
--- a/services/core/java/com/android/server/wm/BlurController.java
+++ b/services/core/java/com/android/server/wm/BlurController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.os.PowerManager.THERMAL_STATUS_CRITICAL;
import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
import android.content.BroadcastReceiver;
@@ -45,6 +46,7 @@ final class BlurController {
private final Object mLock = new Object();
private volatile boolean mBlurEnabled;
private boolean mInPowerSaveMode;
+ private boolean mCriticalThermalStatus;
private boolean mBlurDisabledSetting;
private boolean mTunnelModeEnabled = false;
@@ -89,6 +91,12 @@ final class BlurController {
});
mBlurDisabledSetting = getBlurDisabledSetting();
+ powerManager.addThermalStatusListener((status) -> {
+ mCriticalThermalStatus = status >= THERMAL_STATUS_CRITICAL;
+ updateBlurEnabled();
+ });
+ mCriticalThermalStatus = powerManager.getCurrentThermalStatus() >= THERMAL_STATUS_CRITICAL;
+
TunnelModeEnabledListener.register(mTunnelModeListener);
updateBlurEnabled();
@@ -112,7 +120,7 @@ final class BlurController {
private void updateBlurEnabled() {
synchronized (mLock) {
final boolean newEnabled = CROSS_WINDOW_BLUR_SUPPORTED && !mBlurDisabledSetting
- && !mInPowerSaveMode && !mTunnelModeEnabled;
+ && !mInPowerSaveMode && !mTunnelModeEnabled && !mCriticalThermalStatus;
if (mBlurEnabled == newEnabled) {
return;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b2e7b8f8b298..2bdd34fe15e6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -294,6 +294,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
private final SurfaceControl mWindowingLayer;
+ /**
+ * The window token of the layer of the hierarchy to mirror, or null if this DisplayContent
+ * is not being used for layer mirroring.
+ */
+ @VisibleForTesting IBinder mTokenToMirror = null;
+
+ /**
+ * The surface for mirroring the contents of this hierarchy.
+ */
+ private SurfaceControl mMirroredSurface = null;
+
+ /**
+ * The last bounds of the DisplayArea to mirror.
+ */
+ private Rect mLastMirroredDisplayAreaBounds = null;
+
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
// window containers together and move them in-sync if/when needed. We use a subclass of
@@ -771,10 +787,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return true;
}
- if (focusedApp.getTask() == activity.getTask()
- && focusedApp.getTaskFragment() != activity.getTaskFragment()) {
- // Do not use the activity window of another TaskFragment in the same leaf Task
- return false;
+ // If the candidate activity is currently being embedded in the focused task, the
+ // activity cannot be focused unless it is on the same TaskFragment as the focusedApp's.
+ TaskFragment parent = activity.getTaskFragment();
+ if (parent != null && parent.isEmbedded()) {
+ Task hostTask = focusedApp.getTask();
+ if (hostTask.isEmbedded()) {
+ // Use the hosting task if the current task is embedded.
+ hostTask = hostTask.getParent().asTaskFragment().getTask();
+ }
+ if (activity.isDescendantOf(hostTask)
+ && activity.getTaskFragment() != focusedApp.getTaskFragment()) {
+ return false;
+ }
}
}
@@ -1111,6 +1136,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display);
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
+
+ // Check if this DisplayContent is for a new VirtualDisplay, that should use layer mirroring
+ // to capture the contents of a DisplayArea.
+ startMirrorIfNeeded();
}
boolean isReady() {
@@ -1594,8 +1623,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// If the transition has not started yet, the activity must be the top.
return false;
}
- if (mLastWallpaperVisible && r.windowsCanBeWallpaperTarget()) {
- // Use normal rotation animation for orientation change of visible wallpaper.
+ if (mLastWallpaperVisible && r.windowsCanBeWallpaperTarget()
+ && mFixedRotationTransitionListener.mAnimatingRecents == null) {
+ // Use normal rotation animation for orientation change of visible wallpaper if recents
+ // animation is not running (it may be swiping to home).
return false;
}
final int rotation = rotationForActivityInDifferentOrientation(r);
@@ -2465,6 +2496,25 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// Update IME parent if needed.
updateImeParent();
+ // Update mirroring surface for MediaProjection, if this DisplayContent is being used
+ // for layer mirroring.
+ if (mMirroredSurface != null) {
+ // Retrieve the size of the DisplayArea to mirror, and continue with the update if the
+ // bounds have changed.
+ final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
+ mTokenToMirror);
+ if (wc != null && mLastMirroredDisplayAreaBounds != null) {
+ // Retrieve the size of the DisplayArea to mirror, and continue with the update
+ // if the bounds or orientation has changed.
+ final Rect displayAreaBounds = wc.getDisplayContent().getBounds();
+ int displayAreaOrientation = wc.getDisplayContent().getOrientation();
+ if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds)
+ || lastOrientation != displayAreaOrientation) {
+ updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds);
+ }
+ }
+ }
+
if (lastOrientation != getConfiguration().orientation) {
getMetricsLogger().write(
new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED)
@@ -4323,6 +4373,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
true /* inTraversal, must call performTraversalInTrans... below */);
}
+ updateMirroring();
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
if (wallpaperVisible != mLastWallpaperVisible) {
@@ -4577,7 +4628,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return true;
}
- if (task.isOrganized()) {
+ // TODO(b/165794880): Freeform task organizer doesn't support drag-resize yet. Remove
+ // the special case when it does.
+ if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
return true;
}
@@ -5851,6 +5904,133 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mSandboxDisplayApis;
}
+ /**
+ * Start mirroring to this DisplayContent if it does not have its own content. Captures the
+ * content of a WindowContainer indicated by a WindowToken. If unable to start mirroring, falls
+ * back to original MediaProjection approach.
+ */
+ private void startMirrorIfNeeded() {
+ // Only mirror if this display does not have its own content.
+ if (mLastHasContent) {
+ return;
+ }
+ // Given the WindowToken of the DisplayArea to mirror, retrieve the associated
+ // SurfaceControl.
+ IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror(
+ mDisplayId);
+
+ if (tokenToMirror == null) {
+ // This DisplayContent instance is not involved in layer mirroring. If the display
+ // has been created for capturing, fall back to prior MediaProjection approach.
+ return;
+ }
+ final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
+ tokenToMirror);
+ if (wc == null) {
+ // Un-set the window token to mirror for this VirtualDisplay, to fall back to the
+ // original MediaProjection approach.
+ mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null);
+ return;
+ }
+ SurfaceControl sc = wc.getDisplayContent().getSurfaceControl();
+
+ // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture.
+ mMirroredSurface = SurfaceControl.mirrorSurface(sc);
+ SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get()
+ // Set the mMirroredSurface's parent to the root SurfaceControl for this
+ // DisplayContent. This brings the new mirrored hierarchy under this DisplayContent,
+ // so SurfaceControl will write the layers of this hierarchy to the output surface
+ // provided by the app.
+ .reparent(mMirroredSurface, mSurfaceControl)
+ // Reparent the SurfaceControl of this DisplayContent to null, to prevent content
+ // being added to it. This ensures that no app launched explicitly on the
+ // VirtualDisplay will show up as part of the mirrored content.
+ .reparent(mWindowingLayer, null);
+ // Retrieve the size of the DisplayArea to mirror.
+ updateMirroredSurface(transaction, wc.getDisplayContent().getBounds());
+ mTokenToMirror = tokenToMirror;
+
+ // No need to clean up. In SurfaceFlinger, parents hold references to their children. The
+ // mirrored SurfaceControl is alive since the parent DisplayContent SurfaceControl is
+ // holding a reference to it. Therefore, the mirrored SurfaceControl will be cleaned up
+ // when the VirtualDisplay is destroyed - which will clean up this DisplayContent.
+ }
+
+ /**
+ * Start or stop mirroring if this DisplayContent now has content, or no longer has content.
+ */
+ private void updateMirroring() {
+ if (mLastHasContent && mMirroredSurface != null) {
+ // Display now has content, so stop mirroring to it.
+ mWmService.mTransactionFactory.get()
+ // Remove the reference to mMirroredSurface, to clean up associated memory.
+ .remove(mMirroredSurface)
+ // Reparent the SurfaceControl of this DisplayContent back to mSurfaceControl,
+ // to allow content to be added to it. This allows this DisplayContent to stop
+ // mirroring and show content normally.
+ .reparent(mWindowingLayer, mSurfaceControl).apply();
+ // Stop mirroring by destroying the reference to the mirrored layer.
+ mMirroredSurface = null;
+ // Do not un-set the token, in case content is removed and mirroring should begin again.
+ } else if (!mLastHasContent && mMirroredSurface == null) {
+ // Display no longer has content, so start mirroring to it.
+ startMirrorIfNeeded();
+ }
+ }
+
+ /**
+ * Apply transformations to the mirrored surface to ensure the captured contents are scaled to
+ * fit and centred in the output surface.
+ *
+ * @param transaction the transaction to include transformations of mMirroredSurface
+ * to. Transaction is not applied before returning.
+ * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by
+ * the app.
+ */
+ @VisibleForTesting
+ void updateMirroredSurface(SurfaceControl.Transaction transaction,
+ Rect displayAreaBounds) {
+ // Retrieve the default size of the surface the app provided to
+ // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface,
+ // since it reads out buffers from the surface, and SurfaceFlinger is the producer since
+ // it writes the mirrored layers to the buffers.
+ final Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize(
+ mDisplayId);
+
+ // Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the
+ // output surface.
+ float scaleX = surfaceSize.x / (float) displayAreaBounds.width();
+ float scaleY = surfaceSize.y / (float) displayAreaBounds.height();
+ float scale = Math.min(scaleX, scaleY);
+ int scaledWidth = Math.round(scale * (float) displayAreaBounds.width());
+ int scaledHeight = Math.round(scale * (float) displayAreaBounds.height());
+
+ // Calculate the shift to apply to the root mirror SurfaceControl to centre the mirrored
+ // contents in the output surface.
+ int shiftedX = 0;
+ if (scaledWidth != surfaceSize.x) {
+ shiftedX = (surfaceSize.x - scaledWidth) / 2;
+ }
+ int shiftedY = 0;
+ if (scaledHeight != surfaceSize.y) {
+ shiftedY = (surfaceSize.y - scaledHeight) / 2;
+ }
+
+ transaction
+ // Crop the area to capture to exclude the 'extra' wallpaper that is used
+ // for parallax (b/189930234).
+ .setWindowCrop(mMirroredSurface, displayAreaBounds.width(),
+ displayAreaBounds.height())
+ // Scale the root mirror SurfaceControl, based upon the size difference between the
+ // source (DisplayArea to capture) and output (surface the app reads images from).
+ .setMatrix(mMirroredSurface, scale, 0 /* dtdx */, 0 /* dtdy */, scale)
+ // Position needs to be updated when the mirrored DisplayArea has changed, since
+ // the content will no longer be centered in the output surface.
+ .setPosition(mMirroredSurface, shiftedX /* x */, shiftedY /* y */)
+ .apply();
+ mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds);
+ }
+
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index eb5ab83756ef..42c536b6d5c3 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -38,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -306,7 +307,10 @@ final class InputMonitor {
boolean useSurfaceCrop = false;
final Task task = w.getTask();
if (task != null) {
- if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ // TODO(b/165794636): Remove the special case for freeform window once drag resizing is
+ // handled by WM shell.
+ if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN
+ && !task.inFreeformWindowingMode()) {
// If the window is in a TaskManaged by a TaskOrganizer then most cropping will
// be applied using the SurfaceControl hierarchy from the Organizer. This means
// we need to make sure that these changes in crop are reflected in the input
@@ -538,7 +542,8 @@ final class InputMonitor {
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
if (recentsAnimationController.updateInputConsumerForApp(
mRecentsAnimationInputConsumer.mWindowHandle)) {
- mRecentsAnimationInputConsumer.show(mInputTransaction, w.mActivityRecord);
+ mRecentsAnimationInputConsumer.show(mInputTransaction,
+ recentsAnimationController.getHighestLayerTask());
mAddRecentsAnimationInputConsumerHandle = false;
}
}
@@ -648,6 +653,7 @@ final class InputMonitor {
|| type == TYPE_DOCK_DIVIDER
|| type == TYPE_ACCESSIBILITY_OVERLAY
|| type == TYPE_INPUT_CONSUMER
- || type == TYPE_VOICE_INTERACTION;
+ || type == TYPE_VOICE_INTERACTION
+ || type == TYPE_STATUS_BAR_ADDITIONAL;
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 895a82b21072..53af563ac0c4 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -30,10 +30,6 @@ import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_B
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
@@ -222,7 +218,7 @@ class InsetsPolicy {
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
- return adjustVisibilityForIme(target, state, state == originalState);
+ return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
}
/**
@@ -252,38 +248,16 @@ class InsetsPolicy {
return state;
}
- private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
+ // Navigation bar insets is always visible to IME.
+ private static InsetsState adjustVisibilityForIme(InsetsState originalState,
boolean copyState) {
- if (w.mIsImWindow) {
- // Navigation bar insets is always visible to IME.
- final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
- if (originalNavSource != null && !originalNavSource.isVisible()) {
- final InsetsState state = copyState ? new InsetsState(originalState)
- : originalState;
- final InsetsSource navSource = new InsetsSource(originalNavSource);
- navSource.setVisible(true);
- state.addSource(navSource);
- return state;
- }
- } else if (w.mActivityRecord != null && !w.mActivityRecord.mLastImeShown) {
- // During switching tasks with gestural navigation, if the IME is attached to
- // one app window on that time, even the next app window is behind the IME window,
- // conceptually the window should not receive the IME insets if the next window is
- // not eligible IME requester and ready to show IME on top of it.
- final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
- final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
-
- if (originalImeSource != null && shouldImeAttachedToApp
- && (w.isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS)
- || !w.getRequestedVisibility(ITYPE_IME))) {
- final InsetsState state = copyState ? new InsetsState(originalState)
- : originalState;
-
- final InsetsSource imeSource = new InsetsSource(originalImeSource);
- imeSource.setVisible(false);
- state.addSource(imeSource);
- return state;
- }
+ final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+ if (originalNavSource != null && !originalNavSource.isVisible()) {
+ final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+ final InsetsSource navSource = new InsetsSource(originalNavSource);
+ navSource.setVisible(true);
+ state.addSource(navSource);
+ return state;
}
return originalState;
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 750de3b388dd..d67d5fa7db4f 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -386,7 +386,9 @@ class KeyguardController {
// can be committed before KEYGUARD_OCCLUDE transition is handled.
// Set mRequestForceTransition flag to make sure that the app transition animation
// is applied for such case.
- if (topActivity != null) {
+ // TODO(b/194243906): Fix this before enabling the remote keyguard animation.
+ if (WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
+ && topActivity != null) {
topActivity.mRequestForceTransition = true;
}
updateKeyguardSleepToken(DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index ede4c2ef7835..dca0bbda78cf 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1346,7 +1346,8 @@ class RecentTasks {
+ " activityType=" + task.getActivityType()
+ " windowingMode=" + task.getWindowingMode()
+ " isAlwaysOnTopWhenVisible=" + task.isAlwaysOnTopWhenVisible()
- + " intentFlags=" + task.getBaseIntent().getFlags());
+ + " intentFlags=" + task.getBaseIntent().getFlags()
+ + " isEmbedded=" + task.isEmbedded());
}
switch (task.getActivityType()) {
@@ -1392,6 +1393,11 @@ class RecentTasks {
return false;
}
+ // Ignore the task if it is a embedded task
+ if (task.isEmbedded()) {
+ return false;
+ }
+
return true;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4f93c7ad6ed9..c457df9f6e86 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -1102,6 +1102,23 @@ public class RecentsAnimationController implements DeathRecipient {
return mTargetActivityRecord.findMainWindow();
}
+ /**
+ * Returns the task with the highest layer, or null if none is found.
+ */
+ public Task getHighestLayerTask() {
+ int highestLayer = Integer.MIN_VALUE;
+ Task highestLayerTask = null;
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+ int layer = adapter.mTask.getPrefixOrderIndex();
+ if (layer > highestLayer) {
+ highestLayer = layer;
+ highestLayerTask = adapter.mTask;
+ }
+ }
+ return highestLayerTask;
+ }
+
boolean isAnimatingTask(Task task) {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
if (task == mPendingAnimations.get(i).mTask) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3516c75493e2..079868d0dec1 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -365,8 +365,26 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return false;
}
+ if (matchingCandidate(task)) {
+ return true;
+ }
+
+ // Looking for the embedded tasks (if any)
+ return !task.isLeafTaskFragment() && task.forAllLeafTaskFragments(
+ this::matchingCandidate);
+ }
+
+ boolean matchingCandidate(TaskFragment taskFragment) {
+ final Task task = taskFragment.asTask();
+ if (task == null) {
+ return false;
+ }
+
// Overlays should not be considered as the task's logical top activity.
- final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
+ // Activities of the tasks that embedded from this one should not be used.
+ final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */,
+ false /* includingEmbeddedTask */);
+
if (r == null || r.finishing || r.mUserId != userId
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
@@ -1980,7 +1998,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
*/
void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients) {
- if (mTaskSupervisor.inActivityVisibilityUpdate()) {
+ if (mTaskSupervisor.inActivityVisibilityUpdate()
+ || mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
// Don't do recursive work.
return;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7cb8109f432b..04b6d470467a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -125,7 +125,6 @@ import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
import static com.android.server.wm.TaskProto.TASK_FRAGMENT;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
@@ -723,7 +722,7 @@ class Task extends TaskFragment {
} catch (RemoteException e) {
}
}
- if (autoRemoveFromRecents() || isVoiceSession) {
+ if (autoRemoveFromRecents(oldParent.asTaskFragment()) || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
mTaskSupervisor.mRecentTasks.remove(this);
@@ -1394,14 +1393,6 @@ class Task extends TaskFragment {
return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
}
- ActivityRecord getTopNonFinishingActivity() {
- return getTopNonFinishingActivity(true /* includeOverlays */);
- }
-
- ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
- return getTopActivity(false /*includeFinishing*/, includeOverlays);
- }
-
ActivityRecord topRunningActivityLocked() {
if (getParent() == null) {
return null;
@@ -1521,7 +1512,7 @@ class Task extends TaskFragment {
if (DEBUG_TASK_MOVEMENT) {
Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
}
- super.removeChild(r);
+ super.removeChild(r, false /* removeSelfIfPossible */);
if (inPinnedWindowingMode()) {
// We normally notify listeners of task stack changes on pause, however root pinned task
@@ -1551,7 +1542,10 @@ class Task extends TaskFragment {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
// or created by task organizer.
if (!isRootTask()) {
- getRootTask().removeChild(this, reason);
+ final WindowContainer<?> parent = getParent();
+ if (parent != null) {
+ parent.asTaskFragment().removeChild(this);
+ }
}
EventLogTags.writeWmTaskRemoved(mTaskId,
"removeChild:" + reason + " last r=" + r + " in t=" + this);
@@ -1583,11 +1577,12 @@ class Task extends TaskFragment {
return count > 0;
}
- private boolean autoRemoveFromRecents() {
+ private boolean autoRemoveFromRecents(TaskFragment oldParentFragment) {
// We will automatically remove the task either if it has explicitly asked for
// this, or it is empty and has never contained an activity that got shown to
- // the user.
- return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
+ // the user, or it was being embedded in another Task.
+ return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()
+ || (oldParentFragment != null && oldParentFragment.isEmbedded()));
}
private void clearPinnedTaskIfNeed() {
@@ -2602,25 +2597,12 @@ class Task extends TaskFragment {
}
}
- @VisibleForTesting
- boolean hasWindowsAlive() {
- return getActivity(ActivityRecord::hasWindowsAlive) != null;
- }
-
- @VisibleForTesting
- boolean shouldDeferRemoval() {
- if (mChildren.isEmpty()) {
- // No reason to defer removal of a Task that doesn't have any child.
- return false;
- }
- return hasWindowsAlive() && getRootTask().isAnimating(TRANSITION | CHILDREN);
- }
-
@Override
void removeImmediately() {
removeImmediately("removeTask");
}
+ @Override
void removeImmediately(String reason) {
if (DEBUG_ROOT_TASK) Slog.i(TAG, "removeTask:" + reason + " removing taskId=" + mTaskId);
if (mRemoving) {
@@ -2976,11 +2958,54 @@ class Task extends TaskFragment {
/** Returns the top-most activity that occludes the given one, or {@code null} if none. */
@Nullable
ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
- final ActivityRecord top = getActivity(ActivityRecord::occludesParent,
- true /* traverseTopToBottom */, activity);
+ final ActivityRecord top = getActivity(r -> {
+ if (r == activity) {
+ // Reached the given activity, return the activity to stop searching.
+ return true;
+ }
+
+ if (!r.occludesParent()) {
+ return false;
+ }
+
+ TaskFragment parent = r.getTaskFragment();
+ if (parent == activity.getTaskFragment()) {
+ // Found it. This activity on top of the given activity on the same TaskFragment.
+ return true;
+ }
+ if (isSelfOrNonEmbeddedTask(parent.asTask())) {
+ // Found it. This activity is the direct child of a leaf Task without being
+ // embedded.
+ return true;
+ }
+ // The candidate activity is being embedded. Checking if the bounds of the containing
+ // TaskFragment equals to the outer TaskFragment.
+ TaskFragment grandParent = parent.getParent().asTaskFragment();
+ while (grandParent != null) {
+ if (!parent.getBounds().equals(grandParent.getBounds())) {
+ // Not occluding the grandparent.
+ break;
+ }
+ if (isSelfOrNonEmbeddedTask(grandParent.asTask())) {
+ // Found it. The activity occludes its parent TaskFragment and the parent
+ // TaskFragment also occludes its parent all the way up.
+ return true;
+ }
+ parent = grandParent;
+ grandParent = parent.getParent().asTaskFragment();
+ }
+ return false;
+ });
return top != activity ? top : null;
}
+ private boolean isSelfOrNonEmbeddedTask(Task task) {
+ if (task == this) {
+ return true;
+ }
+ return task != null && !task.isEmbedded();
+ }
+
@Override
public SurfaceControl.Builder makeAnimationLeash() {
return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
@@ -3217,7 +3242,7 @@ class Task extends TaskFragment {
boolean consumed = false;
if (traverseTopToBottom) {
for (int i = task.mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer child = mChildren.get(i);
+ final WindowContainer child = task.mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
@@ -3227,7 +3252,7 @@ class Task extends TaskFragment {
}
} else {
for (int i = 0; i < task.mChildren.size(); i++) {
- final WindowContainer child = mChildren.get(i);
+ final WindowContainer child = task.mChildren.get(i);
if (child.asTaskFragment() != null) {
child.forAllLeafTaskFragments(callback, traverseTopToBottom);
} else if (child.asActivityRecord() != null && !consumed) {
@@ -3358,19 +3383,9 @@ class Task extends TaskFragment {
@Override
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
super.dump(pw, prefix, dumpAll);
- pw.println(prefix + "bounds=" + getBounds().toShortString());
- final String doublePrefix = prefix + " ";
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- final WindowContainer<?> child = mChildren.get(i);
- pw.println(prefix + "* " + child);
- // Only dump non-activity because full activity info is already printed by
- // RootWindowContainer#dumpActivities.
- if (child.asActivityRecord() == null) {
- child.dump(pw, doublePrefix, dumpAll);
- }
- }
if (!mExitingActivities.isEmpty()) {
+ final String doublePrefix = prefix + " ";
pw.println();
pw.println(prefix + "Exiting application tokens:");
for (int i = mExitingActivities.size() - 1; i >= 0; i--) {
@@ -4139,8 +4154,7 @@ class Task extends TaskFragment {
}
private boolean canBeOrganized() {
- if (mForceNotOrganized || !mAtmService.mTaskOrganizerController
- .isSupportedWindowingMode(getWindowingMode())) {
+ if (mForceNotOrganized) {
return false;
}
// All root tasks can be organized
@@ -4297,7 +4311,7 @@ class Task extends TaskFragment {
final int windowingMode = getWindowingMode();
final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
- final ITaskOrganizer organizer = controller.getTaskOrganizer(windowingMode);
+ final ITaskOrganizer organizer = controller.getTaskOrganizer();
if (!forceUpdate && mTaskOrganizer == organizer) {
return false;
}
@@ -4631,8 +4645,10 @@ class Task extends TaskFragment {
mAtmService.continueWindowLayout();
}
- mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
- mRootWindowContainer.resumeFocusedTasksTopActivities();
+ if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootWindowContainer.resumeFocusedTasksTopActivities();
+ }
}
void resumeNextFocusAfterReparent() {
@@ -5323,18 +5339,6 @@ class Task extends TaskFragment {
return true;
}
- /** Finish all activities in the root task without waiting. */
- void finishAllActivitiesImmediately() {
- if (!hasChild()) {
- removeIfPossible("finishAllActivitiesImmediately");
- return;
- }
- forAllActivities((r) -> {
- Slog.d(TAG, "finishAllActivitiesImmediatelyLocked: finishing " + r);
- r.destroyIfPossible("finishAllActivitiesImmediately");
- });
- }
-
/** @return true if the root task behind this one is a standard activity type. */
private boolean inFrontOfStandardRootTask() {
final TaskDisplayArea taskDisplayArea = getDisplayArea();
@@ -5730,17 +5734,14 @@ class Task extends TaskFragment {
@Override
void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
- pw.print(prefix); pw.print("* "); pw.println(this);
- pw.println(prefix + " mBounds=" + getRequestedOverrideBounds());
- pw.println(prefix + " mCreatedByOrganizer=" + mCreatedByOrganizer);
+ super.dumpInner(prefix, pw, dumpAll, dumpPackage);
+ if (mCreatedByOrganizer) {
+ pw.println(prefix + " mCreatedByOrganizer=true");
+ }
if (mLastNonFullscreenBounds != null) {
pw.print(prefix); pw.print(" mLastNonFullscreenBounds=");
pw.println(mLastNonFullscreenBounds);
}
- if (dumpAll) {
- printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
- prefix + " mLastPausedActivity: ", null);
- }
if (isLeafTask()) {
pw.println(prefix + " isSleeping=" + shouldSleepActivities());
printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
@@ -6137,16 +6138,6 @@ class Task extends TaskFragment {
getDisplayContent().getPinnedTaskController().setActions(actions);
}
- /** Returns true if a removal action is still being deferred. */
- boolean handleCompleteDeferredRemoval() {
- if (isAnimating(TRANSITION | CHILDREN)
- || mAtmService.getTransitionController().inTransition(this)) {
- return true;
- }
-
- return super.handleCompleteDeferredRemoval();
- }
-
public DisplayInfo getDisplayInfo() {
return mDisplayContent.getDisplayInfo();
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 6c8cde433481..cfad93692f09 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -2104,7 +2104,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
if (destroyContentOnRemoval
|| !task.isActivityTypeStandardOrUndefined()
|| task.mCreatedByOrganizer) {
- task.finishAllActivitiesImmediately();
+ task.remove(false /* withTransition */, "removeTaskDisplayArea");
} else {
// Reparent task to corresponding launch root or display area.
final WindowContainer launchRoot =
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 255e4432753e..6c31716f8634 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -61,6 +61,8 @@ import static com.android.server.wm.TaskFragmentProto.DISPLAY_ID;
import static com.android.server.wm.TaskFragmentProto.MIN_HEIGHT;
import static com.android.server.wm.TaskFragmentProto.MIN_WIDTH;
import static com.android.server.wm.TaskFragmentProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.TASK_FRAGMENT;
import android.annotation.IntDef;
@@ -158,8 +160,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
*/
int mMinHeight;
- /** Avoid reentrant of {@link #removeImmediately()}. */
- private boolean mRemoving;
+ /** This task fragment will be removed when the cleanup of its children are done. */
+ private boolean mIsRemovalRequested;
/** The TaskFragment that is adjacent to this one. */
@Nullable
@@ -293,6 +295,13 @@ class TaskFragment extends WindowContainer<WindowContainer> {
mRemoteToken = new RemoteToken(this);
}
+ @NonNull
+ static TaskFragment fromTaskFragmentToken(@Nullable IBinder token,
+ @NonNull ActivityTaskManagerService service) {
+ if (token == null) return null;
+ return service.mWindowOrganizerController.getTaskFragment(token);
+ }
+
void setAdjacentTaskFragment(@Nullable TaskFragment taskFragment) {
if (mAdjacentTaskFragment == taskFragment) {
return;
@@ -607,17 +616,68 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return false;
}
+ ActivityRecord getTopNonFinishingActivity() {
+ return getTopNonFinishingActivity(true /* includeOverlays */);
+ }
+
+ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
+ return getTopNonFinishingActivity(includeOverlays, true /* includingEmbeddedTask */);
+ }
+
+ /**
+ * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to
+ * the current user.
+ * @param includeOverlays whether the task overlay activity should be included.
+ * @param includingEmbeddedTask whether the activity in a task that being embedded from this
+ * one should be included.
+ * @see #topRunningActivity(boolean, boolean)
+ * @see ActivityRecord#okToShowLocked()
+ */
+ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays,
+ boolean includingEmbeddedTask) {
+ // Split into 4 to avoid object creation due to variable capture.
+ if (includeOverlays) {
+ if (includingEmbeddedTask) {
+ return getActivity((r) -> !r.finishing);
+ }
+ return getActivity((r) -> !r.finishing && r.getTask() == this.getTask());
+ }
+
+ if (includingEmbeddedTask) {
+ return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
+ }
+ return getActivity(
+ (r) -> !r.finishing && !r.isTaskOverlay() && r.getTask() == this.getTask());
+ }
+
ActivityRecord topRunningActivity() {
return topRunningActivity(false /* focusableOnly */);
}
ActivityRecord topRunningActivity(boolean focusableOnly) {
- // Split into 2 to avoid object creation due to variable capture.
+ return topRunningActivity(focusableOnly, true /* includingEmbeddedTask */);
+ }
+
+ /**
+ * Returns the top-most running activity, which the activity is non-finishing and ok to show
+ * to the current user.
+ *
+ * @see ActivityRecord#canBeTopRunning()
+ */
+ ActivityRecord topRunningActivity(boolean focusableOnly, boolean includingEmbeddedTask) {
+ // Split into 4 to avoid object creation due to variable capture.
if (focusableOnly) {
- return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
- } else {
+ if (includingEmbeddedTask) {
+ return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
+ }
+ return getActivity(
+ (r) -> r.canBeTopRunning() && r.isFocusable() && r.getTask() == this.getTask());
+ }
+
+ if (includingEmbeddedTask) {
return getActivity(ActivityRecord::canBeTopRunning);
}
+ return getActivity((r) -> r.canBeTopRunning() && r.getTask() == this.getTask());
}
boolean isTopActivityFocusable() {
@@ -1340,6 +1400,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
} else {
prev.schedulePauseTimeout();
+ // Unset readiness since we now need to wait until this pause is complete.
+ mAtmService.getTransitionController().setReady(this, false /* ready */);
return true;
}
@@ -1987,15 +2049,67 @@ class TaskFragment extends WindowContainer<WindowContainer> {
}
@Override
- void removeImmediately() {
- if (mRemoving) {
+ void removeChild(WindowContainer child) {
+ removeChild(child, true /* removeSelfIfPossible */);
+ }
+
+ void removeChild(WindowContainer child, boolean removeSelfIfPossible) {
+ super.removeChild(child);
+ if (removeSelfIfPossible && (!mCreatedByOrganizer || mIsRemovalRequested) && !hasChild()) {
+ removeImmediately("removeLastChild " + child);
+ }
+ }
+
+ /**
+ * Requests to remove this task fragment. If it doesn't have children, it is removed
+ * immediately. Otherwise it will be removed until all activities are destroyed.
+ *
+ * @param withTransition Whether to use transition animation when removing activities. Set to
+ * {@code false} if this is invisible to user, e.g. display removal.
+ */
+ void remove(boolean withTransition, String reason) {
+ if (!hasChild()) {
+ removeImmediately(reason);
return;
}
- mRemoving = true;
+ mIsRemovalRequested = true;
+ forAllActivities(r -> {
+ if (withTransition) {
+ r.finishIfPossible(reason, false /* oomAdj */);
+ } else {
+ r.destroyIfPossible(reason);
+ }
+ });
+ }
+
+ boolean shouldDeferRemoval() {
+ if (!hasChild()) {
+ return false;
+ }
+ return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES)
+ || mAtmService.getTransitionController().inTransition(this);
+ }
+
+ @Override
+ boolean handleCompleteDeferredRemoval() {
+ if (shouldDeferRemoval()) {
+ return true;
+ }
+ return super.handleCompleteDeferredRemoval();
+ }
+
+ /** The overridden method must call {@link #removeImmediately()} instead of super. */
+ void removeImmediately(String reason) {
+ Slog.d(TAG, "Remove task fragment: " + reason);
+ removeImmediately();
+ }
+
+ @Override
+ void removeImmediately() {
+ mIsRemovalRequested = false;
resetAdjacentTaskFragment();
super.removeImmediately();
sendTaskFragmentVanished();
- mRemoving = false;
}
boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
@@ -2023,10 +2137,10 @@ class TaskFragment extends WindowContainer<WindowContainer> {
for (int i = mChildren.size() - 1; i >= 0; --i) {
WindowContainer child = mChildren.get(i);
if (child.asTaskFragment() != null) {
- printed |= child.asTaskFragment().dump(prefix + " ", fd, pw, dumpAll,
+ printed |= child.asTaskFragment().dump(prefix + " ", fd, pw, dumpAll,
dumpClient, dumpPackage, needSep, headerPrinter);
} else if (child.asActivityRecord() != null) {
- ActivityRecord.dumpActivity(fd, pw, i, child.asActivityRecord(), prefix + " ",
+ ActivityRecord.dumpActivity(fd, pw, i, child.asActivityRecord(), prefix + " ",
"Hist ", true, !dumpAll, dumpClient, dumpPackage, false, headerPrinter,
getTask());
}
@@ -2037,7 +2151,13 @@ class TaskFragment extends WindowContainer<WindowContainer> {
void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
pw.print(prefix); pw.print("* "); pw.println(this);
- pw.println(prefix + " mBounds=" + getRequestedOverrideBounds());
+ final Rect bounds = getRequestedOverrideBounds();
+ if (!bounds.isEmpty()) {
+ pw.println(prefix + " mBounds=" + bounds);
+ }
+ if (mIsRemovalRequested) {
+ pw.println(prefix + " mIsRemovalRequested=true");
+ }
if (dumpAll) {
printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
prefix + " mLastPausedActivity: ", null);
@@ -2045,6 +2165,22 @@ class TaskFragment extends WindowContainer<WindowContainer> {
}
@Override
+ void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ super.dump(pw, prefix, dumpAll);
+ pw.println(prefix + "bounds=" + getBounds().toShortString());
+ final String doublePrefix = prefix + " ";
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowContainer<?> child = mChildren.get(i);
+ pw.println(prefix + "* " + child);
+ // Only dump non-activity because full activity info is already printed by
+ // RootWindowContainer#dumpActivities.
+ if (child.asActivityRecord() == null) {
+ child.dump(pw, doublePrefix, dumpAll);
+ }
+ }
+ }
+
+ @Override
void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(HASH_CODE, System.identityHashCode(this));
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index a32238434101..96860a23d3cf 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -230,11 +230,16 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
validateAndGetState(organizer);
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
- synchronized (mGlobalLock) {
- ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
- "Unregister task fragment organizer=%s uid=%d pid=%d",
- organizer.asBinder(), uid, pid);
- removeOrganizer(organizer);
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
+ "Unregister task fragment organizer=%s uid=%d pid=%d",
+ organizer.asBinder(), uid, pid);
+ removeOrganizer(organizer);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 99f31ade2be7..fa7b276bc418 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
@@ -67,14 +64,6 @@ import java.util.function.Consumer;
class TaskOrganizerController extends ITaskOrganizerController.Stub {
private static final String TAG = "TaskOrganizerController";
- // The set of modes that are currently supports
- // TODO: Remove once the task organizer can support all modes
- @VisibleForTesting
- static final int[] UNSUPPORTED_WINDOWING_MODES = {
- WINDOWING_MODE_UNDEFINED,
- WINDOWING_MODE_FREEFORM
- };
-
private class DeathRecipient implements IBinder.DeathRecipient {
ITaskOrganizer mTaskOrganizer;
@@ -373,11 +362,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
mService.mRootWindowContainer.forAllTasks((task) -> {
- if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES,
- task.getWindowingMode())) {
- return;
- }
-
boolean returnTask = !task.mCreatedByOrganizer;
task.updateTaskOrganizerState(true /* forceUpdate */,
returnTask /* skipTaskAppeared */);
@@ -433,14 +417,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
/**
* @return the task organizer key for a given windowing mode.
*/
- ITaskOrganizer getTaskOrganizer(int windowingMode) {
- return isSupportedWindowingMode(windowingMode)
- ? mTaskOrganizers.peekLast()
- : null;
- }
-
- boolean isSupportedWindowingMode(int winMode) {
- return !ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, winMode);
+ ITaskOrganizer getTaskOrganizer() {
+ return mTaskOrganizers.peekLast();
}
// Capture the animation surface control for activity's main window
@@ -680,7 +658,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Delete root task display=%d winMode=%d",
task.getDisplayId(), task.getWindowingMode());
- task.removeImmediately("deleteRootTask");
+ task.remove(true /* withTransition */, "deleteRootTask");
return true;
}
} finally {
@@ -993,9 +971,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
for (int k = 0; k < tasks.size(); k++) {
final Task task = tasks.get(k);
final int mode = task.getWindowingMode();
- if (ArrayUtils.contains(UNSUPPORTED_WINDOWING_MODES, mode)) {
- continue;
- }
pw.println(innerPrefix + " ("
+ WindowConfiguration.windowingModeToString(mode) + ") " + task);
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 6bfa611d7a98..5366bd42fa1a 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -20,6 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
@@ -36,6 +38,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.TransitionFlags;
import static android.view.WindowManager.TransitionType;
import static android.view.WindowManager.transitTypeToString;
+import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -657,7 +660,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>();
for (int i = mParticipants.size() - 1; i >= 0; --i) {
ActivityRecord r = mParticipants.valueAt(i).asActivityRecord();
- if (r == null) continue;
+ if (r == null || !r.mVisibleRequested) continue;
// At this point, r is "ready", but if it's not "ALL ready" then it is probably only
// ready due to starting-window.
reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData
@@ -1066,6 +1069,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
final ActivityManager.RunningTaskInfo tinfo = new ActivityManager.RunningTaskInfo();
task.fillTaskInfo(tinfo);
change.setTaskInfo(tinfo);
+ change.setRotationAnimation(getTaskRotationAnimation(task));
+ final ActivityRecord topMostActivity = task.getTopMostActivity();
+ change.setAllowEnterPip(topMostActivity != null
+ && topMostActivity.checkEnterPictureInPictureAppOpsState());
}
out.addChange(change);
}
@@ -1073,6 +1080,23 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
return out;
}
+ private static int getTaskRotationAnimation(@NonNull Task task) {
+ final ActivityRecord top = task.getTopVisibleActivity();
+ if (top == null) return ROTATION_ANIMATION_UNSPECIFIED;
+ final WindowState mainWin = top.findMainWindow(false);
+ if (mainWin == null) return ROTATION_ANIMATION_UNSPECIFIED;
+ int anim = mainWin.getRotationAnimationHint();
+ if (anim >= 0) return anim;
+ anim = mainWin.getAttrs().rotationAnimation;
+ if (anim != ROTATION_ANIMATION_SEAMLESS) return anim;
+ if (mainWin != task.mDisplayContent.getDisplayPolicy().getTopFullscreenOpaqueWindow()
+ || !top.matchParentBounds()) {
+ // At the moment, we only support seamless rotation if there is only one window showing.
+ return ROTATION_ANIMATION_UNSPECIFIED;
+ }
+ return mainWin.getAttrs().rotationAnimation;
+ }
+
boolean getLegacyIsReady() {
return mState == STATE_STARTED && mSyncId >= 0 && mSyncEngine.isReady(mSyncId);
}
@@ -1166,6 +1190,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
final DisplayContent dc = wc.asDisplayContent();
if (dc != null) {
flags |= FLAG_IS_DISPLAY;
+ if (dc.hasAlertWindowSurfaces()) {
+ flags |= FLAG_DISPLAY_HAS_ALERT_WINDOWS;
+ }
}
if (isWallpaper(wc)) {
flags |= FLAG_IS_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 0f61f1af98bd..7893612b5725 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -559,6 +559,9 @@ class WallpaperController {
final WindowState prevWallpaperTarget = mWallpaperTarget;
mWallpaperTarget = wallpaperTarget;
+ if (prevWallpaperTarget == null && wallpaperTarget != null) {
+ updateWallpaperOffsetLocked(mWallpaperTarget, false);
+ }
if (wallpaperTarget == null || prevWallpaperTarget == null) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index e62a6e4e0ef9..aa147c4c8712 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -322,6 +322,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
int effects = 0;
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
mService.deferWindowLayout();
+ mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
try {
if (transition != null) {
// First check if we have a display rotation transition and if so, update it.
@@ -411,6 +412,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
task.setMainWindowSizeChangeTransaction(sft);
}
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
+ mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
// Already calls ensureActivityConfig
mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
@@ -432,6 +434,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
}
} finally {
+ mService.mTaskSupervisor.setDeferRootVisibilityUpdate(false /* deferUpdate */);
mService.continueWindowLayout();
}
}
@@ -472,7 +475,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
throw new UnsupportedOperationException("Not supported to set multi-window"
+ " windowing mode during locked task mode.");
}
+
+ final int prevMode = container.getWindowingMode();
container.setWindowingMode(windowingMode);
+ if (prevMode != container.getWindowingMode()) {
+ // The activity in the container may become focusable or non-focusable due to
+ // windowing modes changes (such as entering or leaving pinned windowing mode),
+ // so also apply the lifecycle effects to this transaction.
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
+ }
}
return effects;
}
@@ -1171,7 +1182,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return;
}
mLaunchTaskFragments.removeAt(index);
- taskFragment.removeImmediately();
+ taskFragment.remove(true /* withTransition */, "deleteTaskFragment");
+ }
+
+ @Nullable
+ TaskFragment getTaskFragment(IBinder tfToken) {
+ return mLaunchTaskFragments.get(tfToken);
}
static class CallerInfo {
diff --git a/services/core/java/com/android/server/wm/WindowOrientationListener.java b/services/core/java/com/android/server/wm/WindowOrientationListener.java
index 0ded8fb313cd..a967ea8fbf8c 100644
--- a/services/core/java/com/android/server/wm/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/wm/WindowOrientationListener.java
@@ -68,7 +68,7 @@ public abstract class WindowOrientationListener {
private static final String KEY_ROTATION_MEMORIZATION_TIMEOUT =
"rotation_memorization_timeout_millis";
private static final long DEFAULT_ROTATION_RESOLVER_TIMEOUT_MILLIS = 700L;
- private static final long DEFAULT_ROTATION_MEMORIZATION_TIMEOUT_MILLIS = 10_000L; // 10 seconds
+ private static final long DEFAULT_ROTATION_MEMORIZATION_TIMEOUT_MILLIS = 3_000L; // 3 seconds
private Handler mHandler;
private SensorManager mSensorManager;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bee8bda16008..0091b618696e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5974,7 +5974,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// since a generic WindowContainer only needs to wait for its
// children to finish and is immediately ready from its own
// perspective but at the WindowState level we need to wait for ourselves
- // to draw even if the children draw first our don't need to sync, so we start
+ // to draw even if the children draw first or don't need to sync, so we start
// in WAITING state rather than READY.
mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
requestRedrawForSync();
@@ -5985,6 +5985,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return true;
}
+ @Override
+ boolean isSyncFinished() {
+ if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mViewVisibility == View.GONE) {
+ // Don't wait for GONE windows. However, we don't alter the state in case the window
+ // becomes un-gone while the syncset is still active.
+ return true;
+ }
+ return super.isSyncFinished();
+ }
+
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
if (mOrientationChangeRedrawRequestTime > 0) {
final long duration =
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index ab4f1f6fee2f..8c933773f1fd 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -157,12 +157,12 @@ cc_defaults {
"android.hardware.input.classifier@1.0",
"android.hardware.ir@1.0",
"android.hardware.light@2.0",
- "android.hardware.memtrack-V1-ndk_platform",
+ "android.hardware.memtrack-V1-ndk",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power-V2-cpp",
"android.hardware.power.stats@1.0",
- "android.hardware.power.stats-V1-ndk_platform",
+ "android.hardware.power.stats-V1-ndk",
"android.hardware.thermal@1.0",
"android.hardware.tv.input@1.0",
"android.hardware.vibrator-V2-cpp",
@@ -175,7 +175,7 @@ cc_defaults {
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
"android.frameworks.stats@1.0",
- "android.frameworks.stats-V1-ndk_platform",
+ "android.frameworks.stats-V1-ndk",
"android.system.suspend.control-V1-cpp",
"android.system.suspend.control.internal-cpp",
"android.system.suspend@1.0",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3bcf527bc796..6a259657cca6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -327,7 +327,6 @@ import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.devicepolicy.ActiveAdmin.TrustAgentInfo;
-import com.android.server.devicepolicy.Owners.OwnerDto;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.pm.RestrictionsSet;
@@ -649,7 +648,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
private final DeviceStateCacheImpl mStateCache = new DeviceStateCacheImpl();
- private EnterpriseSpecificIdCalculator mEsidCalculator;
/**
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@@ -1260,17 +1258,37 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
// Used by DevicePolicyManagerServiceShellCommand
- List<OwnerDto> listAllOwners() {
+ List<OwnerShellData> listAllOwners() {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
return mInjector.binderWithCleanCallingIdentity(() -> {
- List<OwnerDto> owners = mOwners.listAllOwners();
+ SparseArray<DevicePolicyData> userData;
+
+ // Gets the owners of "full users" first (device owner and profile owners)
+ List<OwnerShellData> owners = mOwners.listAllOwners();
synchronized (getLockObject()) {
for (int i = 0; i < owners.size(); i++) {
- OwnerDto owner = owners.get(i);
+ OwnerShellData owner = owners.get(i);
owner.isAffiliated = isUserAffiliatedWithDeviceLocked(owner.userId);
}
+ userData = mUserData;
+ }
+
+ // Then the owners of profile users (managed profiles)
+ for (int i = 0; i < userData.size(); i++) {
+ DevicePolicyData policyData = mUserData.valueAt(i);
+ int userId = userData.keyAt(i);
+ int parentUserId = mUserManagerInternal.getProfileParentId(userId);
+ boolean isProfile = parentUserId != userId;
+ if (!isProfile) continue;
+ for (int j = 0; j < policyData.mAdminList.size(); j++) {
+ ActiveAdmin admin = policyData.mAdminList.get(j);
+ OwnerShellData owner = OwnerShellData.forManagedProfileOwner(userId,
+ parentUserId, admin.info.getComponent());
+ owners.add(owner);
+ }
}
+
return owners;
});
}
@@ -1455,10 +1473,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return new LockPatternUtils(mContext);
}
- EnterpriseSpecificIdCalculator newEnterpriseSpecificIdCalculator() {
- return new EnterpriseSpecificIdCalculator(mContext);
- }
-
boolean storageManagerIsFileBasedEncryptionEnabled() {
return StorageManager.isFileEncryptedNativeOnly();
}
@@ -3107,10 +3121,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
factoryResetIfDelayedEarlier();
ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
-
- // This is constructed here as EnterpriseSpecificIdCalculator depends on telephony
- // and wifi service and these services are only fully available at this stage.
- mEsidCalculator = mInjector.newEnterpriseSpecificIdCalculator();
break;
}
}
@@ -11586,14 +11596,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(
isProfileOwner(caller) || isDeviceOwner(caller));
}
- long id = mInjector.binderClearCallingIdentity();
try {
return mIPackageManager.getBlockUninstallForUser(packageName, userId);
} catch (RemoteException re) {
// Shouldn't happen.
Slogf.e(LOG_TAG, "Failed to getBlockUninstallForUser", re);
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
}
}
return false;
@@ -16908,8 +16915,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setOrganizationIdForUser(
@NonNull String callerPackage, @NonNull String organizationId, int userId) {
- Preconditions.checkState(mEsidCalculator != null,
- "setOrganizationIdForUser can't be called before boot phase completion");
if (!mHasFeature) {
return;
}
@@ -16943,7 +16948,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ "be changed");
final String dpcPackage = owner.info.getPackageName();
mInjector.binderWithCleanCallingIdentity(() -> {
- final String esid = mEsidCalculator.calculateEnterpriseId(dpcPackage,
+ EnterpriseSpecificIdCalculator esidCalculator =
+ new EnterpriseSpecificIdCalculator(mContext);
+
+ final String esid = esidCalculator.calculateEnterpriseId(dpcPackage,
organizationId);
owner.mOrganizationId = organizationId;
owner.mEnrollmentSpecificId = esid;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
index a2db6aaca3df..85fe65ca5563 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java
@@ -22,8 +22,6 @@ import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
-import com.android.server.devicepolicy.Owners.OwnerDto;
-
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
@@ -205,12 +203,12 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
}
private int runListOwners(PrintWriter pw) {
- List<OwnerDto> owners = mService.listAllOwners();
+ List<OwnerShellData> owners = mService.listAllOwners();
int size = printAndGetSize(pw, owners, "owner");
if (size == 0) return 0;
for (int i = 0; i < size; i++) {
- OwnerDto owner = owners.get(i);
+ OwnerShellData owner = owners.get(i);
pw.printf("User %2d: admin=%s", owner.userId, owner.admin.flattenToShortString());
if (owner.isDeviceOwner) {
pw.print(",DeviceOwner");
@@ -218,6 +216,9 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
if (owner.isProfileOwner) {
pw.print(",ProfileOwner");
}
+ if (owner.isManagedProfileOwner) {
+ pw.printf(",ManagedProfileOwner(parentUserId=%d)", owner.parentUserId);
+ }
if (owner.isAffiliated) {
pw.print(",Affiliated");
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
index 29091cea1b62..df7f3084aeb3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
@@ -51,19 +51,13 @@ class EnterpriseSpecificIdCalculator {
EnterpriseSpecificIdCalculator(Context context) {
TelephonyManager telephonyService = context.getSystemService(TelephonyManager.class);
- if (telephonyService != null) {
- mImei = telephonyService.getImei(0);
- mMeid = telephonyService.getMeid(0);
- } else {
- mImei = "";
- mMeid = "";
- }
+ Preconditions.checkState(telephonyService != null, "Unable to access telephony service");
+ mImei = telephonyService.getImei(0);
+ mMeid = telephonyService.getMeid(0);
mSerialNumber = Build.getSerial();
WifiManager wifiManager = context.getSystemService(WifiManager.class);
- String[] macAddresses = null;
- if (wifiManager != null) {
- macAddresses = wifiManager.getFactoryMacAddresses();
- }
+ Preconditions.checkState(wifiManager != null, "Unable to access WiFi service");
+ final String[] macAddresses = wifiManager.getFactoryMacAddresses();
if (macAddresses == null || macAddresses.length == 0) {
mMacAddress = "";
} else {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnerShellData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnerShellData.java
new file mode 100644
index 000000000000..b98c3dc2ac07
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnerShellData.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 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.os.UserHandle.USER_NULL;
+
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * Data-transfer object used by {@link DevicePolicyManagerServiceShellCommand}.
+ */
+final class OwnerShellData {
+
+ public final @UserIdInt int userId;
+ public final @UserIdInt int parentUserId;
+ public final ComponentName admin;
+ public final boolean isDeviceOwner;
+ public final boolean isProfileOwner;
+ public final boolean isManagedProfileOwner;
+ public boolean isAffiliated;
+
+ // NOTE: class is too simple to require a Builder (not to mention isAffiliated is mutable)
+ private OwnerShellData(@UserIdInt int userId, @UserIdInt int parentUserId, ComponentName admin,
+ boolean isDeviceOwner, boolean isProfileOwner, boolean isManagedProfileOwner) {
+ Preconditions.checkArgument(userId != USER_NULL, "userId cannot be USER_NULL");
+ this.userId = userId;
+ this.parentUserId = parentUserId;
+ this.admin = Objects.requireNonNull(admin, "admin must not be null");
+ this.isDeviceOwner = isDeviceOwner;
+ this.isProfileOwner = isProfileOwner;
+ this.isManagedProfileOwner = isManagedProfileOwner;
+ if (isManagedProfileOwner) {
+ Preconditions.checkArgument(parentUserId != USER_NULL,
+ "parentUserId cannot be USER_NULL for managed profile owner");
+ Preconditions.checkArgument(parentUserId != userId,
+ "cannot be parent of itself (%d)", userId);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(getClass().getSimpleName())
+ .append("[userId=").append(userId)
+ .append(",admin=").append(admin.flattenToShortString());
+ if (isDeviceOwner) {
+ sb.append(",deviceOwner");
+ }
+ if (isProfileOwner) {
+ sb.append(",isProfileOwner");
+ }
+ if (isManagedProfileOwner) {
+ sb.append(",isManagedProfileOwner");
+ }
+ if (parentUserId != USER_NULL) {
+ sb.append(",parentUserId=").append(parentUserId);
+ }
+ if (isAffiliated) {
+ sb.append(",isAffiliated");
+ }
+ return sb.append(']').toString();
+ }
+
+ static OwnerShellData forDeviceOwner(@UserIdInt int userId, ComponentName admin) {
+ return new OwnerShellData(userId, /* parentUserId= */ USER_NULL, admin,
+ /* isDeviceOwner= */ true, /* isProfileOwner= */ false,
+ /* isManagedProfileOwner= */ false);
+ }
+
+ static OwnerShellData forUserProfileOwner(@UserIdInt int userId, ComponentName admin) {
+ return new OwnerShellData(userId, /* parentUserId= */ USER_NULL, admin,
+ /* isDeviceOwner= */ false, /* isProfileOwner= */ true,
+ /* isManagedProfileOwner= */ false);
+ }
+
+ static OwnerShellData forManagedProfileOwner(@UserIdInt int userId, @UserIdInt int parentUserId,
+ ComponentName admin) {
+ return new OwnerShellData(userId, parentUserId, admin, /* isDeviceOwner= */ false,
+ /* isProfileOwner= */ false, /* isManagedProfileOwner= */ true);
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index fd09e3f9cfd0..3584728a2e62 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -19,7 +19,6 @@ package com.android.server.devicepolicy;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManagerInternal;
import android.app.admin.DevicePolicyManager.DeviceOwnerType;
@@ -476,17 +475,16 @@ class Owners {
}
}
- List<OwnerDto> listAllOwners() {
- List<OwnerDto> owners = new ArrayList<>();
+ List<OwnerShellData> listAllOwners() {
+ List<OwnerShellData> owners = new ArrayList<>();
synchronized (mLock) {
if (mDeviceOwner != null) {
- owners.add(new OwnerDto(mDeviceOwnerUserId, mDeviceOwner.admin,
- /* isDeviceOwner= */ true));
+ owners.add(OwnerShellData.forDeviceOwner(mDeviceOwnerUserId, mDeviceOwner.admin));
}
for (int i = 0; i < mProfileOwners.size(); i++) {
int userId = mProfileOwners.keyAt(i);
OwnerInfo info = mProfileOwners.valueAt(i);
- owners.add(new OwnerDto(userId, info.admin, /* isDeviceOwner= */ false));
+ owners.add(OwnerShellData.forUserProfileOwner(userId, info.admin));
}
}
return owners;
@@ -1236,24 +1234,6 @@ class Owners {
}
}
- /**
- * Data-transfer object used by {@link DevicePolicyManagerServiceShellCommand}.
- */
- static final class OwnerDto {
- public final @UserIdInt int userId;
- public final ComponentName admin;
- public final boolean isDeviceOwner;
- public final boolean isProfileOwner;
- public boolean isAffiliated;
-
- private OwnerDto(@UserIdInt int userId, ComponentName admin, boolean isDeviceOwner) {
- this.userId = userId;
- this.admin = Objects.requireNonNull(admin, "admin must not be null");
- this.isDeviceOwner = isDeviceOwner;
- this.isProfileOwner = !isDeviceOwner;
- }
- }
-
public void dump(IndentingPrintWriter pw) {
boolean needBlank = false;
if (mDeviceOwner != null) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 00100158e7ed..46adb32ff103 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -384,6 +384,8 @@ public final class SystemServer implements Dumpable {
private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService";
private static final String GAME_MANAGER_SERVICE_CLASS =
"com.android.server.app.GameManagerService$Lifecycle";
+ private static final String UWB_APEX_SERVICE_JAR_PATH =
+ "/apex/com.android.uwb/javalib/service-uwb.jar";
private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
@@ -2651,7 +2653,7 @@ public final class SystemServer implements Dumpable {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
t.traceBegin("UwbService");
- mSystemServiceManager.startService(UWB_SERVICE_CLASS);
+ mSystemServiceManager.startServiceFromJar(UWB_SERVICE_CLASS, UWB_APEX_SERVICE_JAR_PATH);
t.traceEnd();
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 21964dd2a068..09a831e2b8c4 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -51,7 +51,6 @@ java_library {
// classes generated by netd_aidl_interfaces-platform-java above.
"netd_aidl_interface-V3-java",
"networkstack-client",
- "modules-utils-build_system",
],
apex_available: [
"com.android.wifi",
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 988c02bfb3db..1bcc3d1f70ad 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -32,6 +32,7 @@ android_test {
"androidx.test.runner",
"junit",
"kotlin-test",
+ "kotlin-reflect",
"services.core",
"servicestests-utils",
"truth-prebuilt",
diff --git a/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
new file mode 100644
index 000000000000..cacfcf0dbebc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "PackageManagerServiceUnitTests"
+ }
+ ]
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
new file mode 100644
index 000000000000..a7644ec439da
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.ConfigurationInfo
+import android.content.pm.FeatureGroupInfo
+import android.content.pm.FeatureInfo
+import android.content.pm.PackageManager
+import android.content.pm.SigningDetails
+import android.content.pm.parsing.ParsingPackage
+import android.content.pm.parsing.component.ParsedActivity
+import android.content.pm.parsing.component.ParsedAttribution
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedInstrumentation
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import android.content.pm.parsing.component.ParsedProcess
+import android.content.pm.parsing.component.ParsedProvider
+import android.content.pm.parsing.component.ParsedService
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.net.Uri
+import android.os.Bundle
+import android.os.Parcelable
+import android.util.ArraySet
+import android.util.SparseArray
+import android.util.SparseIntArray
+import com.android.internal.R
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.whenever
+import java.security.KeyPairGenerator
+import java.security.PublicKey
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
+
+ override val defaultImpl = PackageImpl.forTesting("com.example.test")
+ override val creator = PackageImpl.CREATOR
+
+ override val excludedMethods = listOf(
+ // Internal methods
+ "toAppInfoToString",
+ "toAppInfoWithoutState",
+ "toAppInfoWithoutStateWithoutFlags",
+ "assignDerivedFields",
+ "buildFakeForDeletion",
+ "capPermissionPriorities",
+ "forParsing",
+ "forTesting",
+ "getBaseAppDataCredentialProtectedDirForSystemUser",
+ "getBaseAppDataDeviceProtectedDirForSystemUser",
+ "getBoolean",
+ "setBoolean",
+ "hideAsFinal",
+ "hideAsParsed",
+ "markNotActivitiesAsNotExportedIfSingleUser",
+ "sortActivities",
+ "sortReceivers",
+ "sortServices",
+ "setAllComponentsDirectBootAware",
+ // Tested through setting minor/major manually
+ "setLongVersionCode",
+ "getLongVersionCode",
+ // Tested through constructor
+ "getManifestPackageName",
+ "setManifestPackageName",
+ // Utility methods
+ "getStorageUuid",
+ // Removal not tested, irrelevant for parcelling concerns
+ "removeUsesOptionalLibrary",
+ "clearAdoptPermissions",
+ "clearOriginalPackages",
+ "clearProtectedBroadcasts",
+ "removePermission",
+ "removeUsesLibrary",
+ "removeUsesOptionalNativeLibrary",
+ // Tested manually
+ "getMimeGroups",
+ "getRequestedPermissions",
+ // Tested through asSplit
+ "asSplit",
+ "getSplitNames",
+ "getSplitCodePaths",
+ "getSplitRevisionCodes",
+ "getSplitFlags",
+ "getSplitClassLoaderNames",
+ "getSplitDependencies",
+ "setSplitCodePaths",
+ "setSplitClassLoaderName",
+ "setSplitHasCode",
+ )
+
+ override val baseParams = listOf(
+ AndroidPackage::getAppComponentFactory,
+ AndroidPackage::getAutoRevokePermissions,
+ AndroidPackage::getBackupAgentName,
+ AndroidPackage::getBanner,
+ AndroidPackage::getBaseApkPath,
+ AndroidPackage::getBaseRevisionCode,
+ AndroidPackage::getCategory,
+ AndroidPackage::getClassLoaderName,
+ AndroidPackage::getClassName,
+ AndroidPackage::getCompatibleWidthLimitDp,
+ AndroidPackage::getCompileSdkVersion,
+ AndroidPackage::getCompileSdkVersionCodeName,
+ AndroidPackage::getDataExtractionRules,
+ AndroidPackage::getDescriptionRes,
+ AndroidPackage::getFullBackupContent,
+ AndroidPackage::getGwpAsanMode,
+ AndroidPackage::getIconRes,
+ AndroidPackage::getInstallLocation,
+ AndroidPackage::getLabelRes,
+ AndroidPackage::getLargestWidthLimitDp,
+ AndroidPackage::getLogo,
+ AndroidPackage::getManageSpaceActivityName,
+ AndroidPackage::getMemtagMode,
+ AndroidPackage::getMinSdkVersion,
+ AndroidPackage::getNativeHeapZeroInitialized,
+ AndroidPackage::getNativeLibraryDir,
+ AndroidPackage::getNativeLibraryRootDir,
+ AndroidPackage::getNetworkSecurityConfigRes,
+ AndroidPackage::getNonLocalizedLabel,
+ AndroidPackage::getOverlayCategory,
+ AndroidPackage::getOverlayPriority,
+ AndroidPackage::getOverlayTarget,
+ AndroidPackage::getOverlayTargetName,
+ AndroidPackage::getPackageName,
+ AndroidPackage::getPath,
+ AndroidPackage::getPermission,
+ AndroidPackage::getPrimaryCpuAbi,
+ AndroidPackage::getProcessName,
+ AndroidPackage::getRealPackage,
+ AndroidPackage::getRequiredAccountType,
+ AndroidPackage::getRequiresSmallestWidthDp,
+ AndroidPackage::getResizeableActivity,
+ AndroidPackage::getRestrictedAccountType,
+ AndroidPackage::getRoundIconRes,
+ AndroidPackage::getSeInfo,
+ AndroidPackage::getSeInfoUser,
+ AndroidPackage::getSecondaryCpuAbi,
+ AndroidPackage::getSecondaryNativeLibraryDir,
+ AndroidPackage::getSharedUserId,
+ AndroidPackage::getSharedUserLabel,
+ AndroidPackage::getStaticSharedLibName,
+ AndroidPackage::getStaticSharedLibVersion,
+ AndroidPackage::getTargetSandboxVersion,
+ AndroidPackage::getTargetSdkVersion,
+ AndroidPackage::getTaskAffinity,
+ AndroidPackage::getTheme,
+ AndroidPackage::getUiOptions,
+ AndroidPackage::getUid,
+ AndroidPackage::getVersionName,
+ AndroidPackage::getZygotePreloadName,
+ AndroidPackage::isAllowAudioPlaybackCapture,
+ AndroidPackage::isAllowBackup,
+ AndroidPackage::isAllowClearUserData,
+ AndroidPackage::isAllowClearUserDataOnFailedRestore,
+ AndroidPackage::isAllowNativeHeapPointerTagging,
+ AndroidPackage::isAllowTaskReparenting,
+ AndroidPackage::isBackupInForeground,
+ AndroidPackage::isBaseHardwareAccelerated,
+ AndroidPackage::isCantSaveState,
+ AndroidPackage::isCoreApp,
+ AndroidPackage::isCrossProfile,
+ AndroidPackage::isDebuggable,
+ AndroidPackage::isDefaultToDeviceProtectedStorage,
+ AndroidPackage::isDirectBootAware,
+ AndroidPackage::isEnabled,
+ AndroidPackage::isExternalStorage,
+ AndroidPackage::isExtractNativeLibs,
+ AndroidPackage::isFactoryTest,
+ AndroidPackage::isForceQueryable,
+ AndroidPackage::isFullBackupOnly,
+ AndroidPackage::isGame,
+ AndroidPackage::isHasCode,
+ AndroidPackage::isHasDomainUrls,
+ AndroidPackage::isHasFragileUserData,
+ AndroidPackage::isIsolatedSplitLoading,
+ AndroidPackage::isKillAfterRestore,
+ AndroidPackage::isLargeHeap,
+ AndroidPackage::isMultiArch,
+ AndroidPackage::isNativeLibraryRootRequiresIsa,
+ AndroidPackage::isOdm,
+ AndroidPackage::isOem,
+ AndroidPackage::isOverlay,
+ AndroidPackage::isOverlayIsStatic,
+ AndroidPackage::isPartiallyDirectBootAware,
+ AndroidPackage::isPersistent,
+ AndroidPackage::isPrivileged,
+ AndroidPackage::isProduct,
+ AndroidPackage::isProfileableByShell,
+ AndroidPackage::isRequestLegacyExternalStorage,
+ AndroidPackage::isRequiredForAllUsers,
+ AndroidPackage::isResizeableActivityViaSdkVersion,
+ AndroidPackage::isRestoreAnyVersion,
+ AndroidPackage::isSignedWithPlatformKey,
+ AndroidPackage::isStaticSharedLibrary,
+ AndroidPackage::isStub,
+ AndroidPackage::isSupportsRtl,
+ AndroidPackage::isSystem,
+ AndroidPackage::isSystemExt,
+ AndroidPackage::isTestOnly,
+ AndroidPackage::isUse32BitAbi,
+ AndroidPackage::isUseEmbeddedDex,
+ AndroidPackage::isUsesCleartextTraffic,
+ AndroidPackage::isUsesNonSdkApi,
+ AndroidPackage::isVendor,
+ AndroidPackage::isVisibleToInstantApps,
+ AndroidPackage::isVmSafeMode,
+ AndroidPackage::getMaxAspectRatio,
+ AndroidPackage::getMinAspectRatio,
+ AndroidPackage::hasPreserveLegacyExternalStorage,
+ AndroidPackage::hasRequestForegroundServiceExemption,
+ AndroidPackage::hasRequestRawExternalStorageAccess,
+ )
+
+ override fun extraParams() = listOf(
+ getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
+ getter(AndroidPackage::isProfileable, true),
+ getter(AndroidPackage::getVersionCode, 3),
+ getter(AndroidPackage::getVersionCodeMajor, 9),
+ getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
+ getter(AndroidPackage::isAnyDensity, false, 0),
+ getter(AndroidPackage::isResizeable, false, 0),
+ getter(AndroidPackage::isSupportsSmallScreens, false, 0),
+ getter(AndroidPackage::isSupportsNormalScreens, false, 0),
+ getter(AndroidPackage::isSupportsLargeScreens, false, 0),
+ getter(AndroidPackage::isSupportsExtraLargeScreens, false, 0),
+ adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
+ adder(AndroidPackage::getOriginalPackages, "com.test.original"),
+ adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
+ adder(AndroidPackage::getLibraryNames, "testLibraryName"),
+ adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
+ adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
+ adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
+ adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
+ adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
+ adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
+ adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
+ adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
+ getSetByValue(
+ AndroidPackage::getUsesStaticLibrariesVersions,
+ PackageImpl::addUsesStaticLibraryVersion,
+ (testCounter++).toLong(),
+ transformGet = { it?.singleOrNull() }
+ ),
+ getSetByValue(
+ AndroidPackage::areAttributionsUserVisible,
+ ParsingPackage::setAttributionsAreUserVisible,
+ true
+ ),
+ getSetByValue2(
+ AndroidPackage::getOverlayables,
+ PackageImpl::addOverlayable,
+ "testOverlayableName" to "testActorName",
+ transformGet = { "testOverlayableName" to it["testOverlayableName"] }
+ ),
+ getSetByValue(
+ AndroidPackage::getMetaData,
+ PackageImpl::setMetaData,
+ "testBundleKey" to "testBundleValue",
+ transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+ transformSet = { Bundle().apply { putString(it.first, it.second) } }
+ ),
+ getSetByValue(
+ AndroidPackage::getAttributions,
+ PackageImpl::addAttribution,
+ Triple("testTag", 13, listOf("testInherit")),
+ transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
+ transformSet = { it?.let { ParsedAttribution(it.first, it.second, it.third) } }
+ ),
+ getSetByValue2(
+ AndroidPackage::getKeySetMapping,
+ PackageImpl::addKeySet,
+ "testKeySetName" to testKey(),
+ transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
+ ),
+ getSetByValue(
+ AndroidPackage::getPermissionGroups,
+ PackageImpl::addPermissionGroup,
+ "test.permission.GROUP",
+ transformGet = { it.singleOrNull()?.name },
+ transformSet = { ParsedPermissionGroup().apply { setName(it) } }
+ ),
+ getSetByValue2(
+ AndroidPackage::getPreferredActivityFilters,
+ PackageImpl::addPreferredActivityFilter,
+ "TestClassName" to ParsedIntentInfo().apply {
+ addDataScheme("http")
+ addDataAuthority("test.pm.server.android.com", null)
+ },
+ transformGet = { it.singleOrNull()?.let { it.first to it.second } },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it.first },
+ { it.second.schemesIterator().asSequence().singleOrNull() },
+ { it.second.authoritiesIterator().asSequence().singleOrNull()?.host },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getQueriesIntents,
+ PackageImpl::addQueriesIntent,
+ Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
+ transformGet = { it.singleOrNull() },
+ compare = { first, second -> first?.filterEquals(second) },
+ ),
+ getSetByValue(
+ AndroidPackage::getRestrictUpdateHash,
+ PackageImpl::setRestrictUpdateHash,
+ byteArrayOf(0, 1, 2, 3, 4),
+ compare = ByteArray::contentEquals
+ ),
+ getSetByValue(
+ AndroidPackage::getSigningDetails,
+ PackageImpl::setSigningDetails,
+ testKey(),
+ transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
+ transformSet = {
+ SigningDetails(
+ null,
+ SigningDetails.SignatureSchemeVersion.UNKNOWN,
+ ArraySet<PublicKey>().apply { add(it) },
+ null
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getUsesStaticLibrariesCertDigests,
+ PackageImpl::addUsesStaticLibraryCertDigests,
+ arrayOf("testCertDigest"),
+ transformGet = { it?.singleOrNull() },
+ compare = Array<String?>?::contentEquals
+ ),
+ getSetByValue(
+ AndroidPackage::getActivities,
+ PackageImpl::addActivity,
+ "TestActivityName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getReceivers,
+ PackageImpl::addReceiver,
+ "TestReceiverName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getServices,
+ PackageImpl::addService,
+ "TestServiceName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedService().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getProviders,
+ PackageImpl::addProvider,
+ "TestProviderName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedProvider().apply { name = it }.withMimeGroups() }
+ ),
+ getSetByValue(
+ AndroidPackage::getInstrumentations,
+ PackageImpl::addInstrumentation,
+ "TestInstrumentationName",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedInstrumentation().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getConfigPreferences,
+ PackageImpl::addConfigPreference,
+ testCounter++,
+ transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
+ transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getFeatureGroups,
+ PackageImpl::addFeatureGroup,
+ "test.feature.GROUP",
+ transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
+ transformSet = {
+ FeatureGroupInfo().apply {
+ features = arrayOf(FeatureInfo().apply { name = it })
+ }
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getPermissions,
+ PackageImpl::addPermission,
+ "test.PERMISSION",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { ParsedPermission().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getUsesPermissions,
+ PackageImpl::addUsesPermission,
+ "test.USES_PERMISSION",
+ transformGet = {
+ // Need to strip implicit permission, which calls addUsesPermission when added
+ it.filterNot { it.name == "test.implicit.PERMISSION" }
+ .singleOrNull()?.name.orEmpty()
+ },
+ transformSet = { ParsedUsesPermission(it, 0) }
+ ),
+ getSetByValue(
+ AndroidPackage::getReqFeatures,
+ PackageImpl::addReqFeature,
+ "test.feature.INFO",
+ transformGet = { it.singleOrNull()?.name.orEmpty() },
+ transformSet = { FeatureInfo().apply { name = it } }
+ ),
+ getSetByValue(
+ AndroidPackage::getMinExtensionVersions,
+ PackageImpl::setMinExtensionVersions,
+ SparseIntArray().apply { put(testCounter++, testCounter++) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it.size() },
+ { it.keyAt(0) },
+ { it.valueAt(0) },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getProcesses,
+ PackageImpl::setProcesses,
+ mapOf("testProcess" to ParsedProcess().apply { name = "testProcessName" }),
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ { it["testProcess"]?.name },
+ )
+ }
+ ),
+ getSetByValue(
+ AndroidPackage::getProperties,
+ PackageImpl::addProperty,
+ PackageManager.Property(
+ "testPropertyName",
+ "testPropertyValue",
+ "testPropertyClassName",
+ "testPropertyPackageName"
+ ),
+ transformGet = { it["testPropertyName"] },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PackageManager.Property::getName,
+ PackageManager.Property::getClassName,
+ PackageManager.Property::getPackageName,
+ PackageManager.Property::getString,
+ )
+ }
+ ),
+ )
+
+ override fun initialObject() = PackageImpl.forParsing(
+ "com.example.test",
+ "/test/test/base.apk",
+ "/test/test",
+ mockThrowOnUnmocked {
+ whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
+ whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
+
+ // Return invalid values here so that the getter/setter is tested properly
+ whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
+ whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
+ whenever(
+ getNonConfigurationString(
+ R.styleable.AndroidManifest_versionName,
+ 0
+ )
+ ) { "" }
+ whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
+ whenever(
+ getNonConfigurationString(
+ R.styleable.AndroidManifest_compileSdkVersionCodename,
+ 0
+ )
+ ) { "" }
+ },
+ true
+ )
+ .asSplit(
+ arrayOf("testSplitNameZero", "testSplitNameOne"),
+ arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
+ intArrayOf(10, 11),
+ SparseArray<IntArray>().apply {
+ put(0, intArrayOf(-1))
+ put(1, intArrayOf(0))
+ }
+ )
+ .setSplitHasCode(0, true)
+ .setSplitHasCode(1, false)
+ .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
+ .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
+
+ override fun extraAssertions(before: Parcelable, after: Parcelable) {
+ super.extraAssertions(before, after)
+ after as PackageImpl
+ expect.that(after.manifestPackageName).isEqualTo("com.example.test")
+ expect.that(after.isCoreApp).isTrue()
+ expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
+ expect.that(after.longVersionCode).isEqualTo(38654705667)
+ expect.that(after.requestedPermissions)
+ .containsExactlyElementsIn(after.usesPermissions.map { it.name })
+ .inOrder()
+
+ expect.that(after.mimeGroups).containsExactly(
+ "TestActivityName/mimeGroup",
+ "TestReceiverName/mimeGroup",
+ "TestServiceName/mimeGroup",
+ "TestProviderName/mimeGroup"
+ )
+
+ expect.that(after.splitNames).asList()
+ .containsExactly("testSplitNameZero", "testSplitNameOne")
+ .inOrder()
+ expect.that(after.splitCodePaths).asList()
+ .containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
+ .inOrder()
+ expect.that(after.splitRevisionCodes).asList()
+ .containsExactly(10, 11)
+ .inOrder()
+ expect.that(after.splitFlags).asList()
+ .containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
+ .inOrder()
+ expect.that(after.splitClassLoaderNames).asList()
+ .containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
+ .inOrder()
+
+ expect.that(after.splitDependencies).isNotNull()
+ after.splitDependencies?.let {
+ expect.that(it.size()).isEqualTo(2)
+ expect.that(it.get(0)).asList().containsExactly(-1)
+ expect.that(it.get(1)).asList().containsExactly(0)
+ }
+ }
+
+ private fun testKey() = KeyPairGenerator.getInstance("RSA")
+ .generateKeyPair()
+ .public
+
+ private fun <T : ParsedComponent> T.withMimeGroups() = apply {
+ val componentName = name
+ addIntent(ParsedIntentInfo().apply {
+ addMimeGroup("$componentName/mimeGroup")
+ })
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
new file mode 100644
index 000000000000..e16a1871f8b8
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.util.IgnoreableExpect
+import com.google.common.truth.Expect
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import java.util.Objects
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction
+import kotlin.reflect.KFunction1
+import kotlin.reflect.KFunction2
+import kotlin.reflect.KFunction3
+import kotlin.reflect.KVisibility
+import kotlin.reflect.full.allSuperclasses
+import kotlin.reflect.full.createInstance
+import kotlin.reflect.full.isSubclassOf
+import kotlin.reflect.full.memberFunctions
+import kotlin.reflect.full.memberProperties
+import kotlin.reflect.full.staticProperties
+import kotlin.reflect.jvm.jvmErasure
+
+
+@ExperimentalContracts
+abstract class ParcelableComponentTest(
+ private val getterType: KClass<*>,
+ private val setterType: KClass<out Parcelable>
+) {
+
+ companion object {
+ private val DEFAULT_EXCLUDED = listOf(
+ // Java
+ "toString",
+ "equals",
+ "hashCode",
+ // Parcelable
+ "getStability",
+ "describeContents",
+ "writeToParcel",
+ // @DataClass
+ "__metadata"
+ )
+ }
+
+ internal val ignoreableExpect = IgnoreableExpect()
+
+ // Hides internal type
+ @get:Rule
+ val ignoreableAsTestRule: TestRule = ignoreableExpect
+
+ val expect: Expect
+ get() = ignoreableExpect.expect
+
+ protected var testCounter = 1
+
+ protected abstract val defaultImpl: Any
+ protected abstract val creator: Parcelable.Creator<out Parcelable>
+
+ protected open val excludedMethods: Collection<String> = emptyList()
+
+ protected abstract val baseParams: Collection<KFunction1<*, Any?>>
+
+ private val getters = getterType.memberFunctions
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+ private val setters = setterType.memberFunctions
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) }
+
+ constructor(kClass: KClass<out Parcelable>) : this(kClass, kClass)
+
+ @Before
+ fun checkNoPublicFields() {
+ // Fields are not currently testable, and the idea is to enforce interface access for
+ // immutability purposes, so disallow any public fields from existing.
+ expect.that(getterType.memberProperties.filter { it.visibility == KVisibility.PUBLIC }
+ .filterNot { DEFAULT_EXCLUDED.contains(it.name) })
+ .isEmpty()
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType> buildParams(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ ): Param? {
+ return buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(
+ getFunction,
+ autoValue(getFunction) as ReturnType ?: return null
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> buildParams(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ value: SetType,
+ ): Param? {
+ return getSetByValue<ObjectType, ReturnType, SetType, Any?>(
+ getFunction,
+ findSetFunction(getFunction) ?: return null,
+ value
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType> findSetFunction(
+ getFunction: KFunction1<ObjectType, ReturnType>
+ ): KFunction2<ObjectType, ReturnType, Any?>? {
+ val getFunctionName = getFunction.name
+ val prefix = when {
+ getFunctionName.startsWith("get") -> "get"
+ getFunctionName.startsWith("is") -> "is"
+ getFunctionName.startsWith("has") -> "has"
+ else -> throw IllegalArgumentException("Unsupported method name $getFunctionName")
+ }
+ val setFunctionName = "set" + getFunctionName.removePrefix(prefix)
+ val setFunction = setters.filter { it.name == setFunctionName }
+ .minByOrNull { it.parameters.size }
+
+ if (setFunction == null) {
+ expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+ .fail()
+ return null
+ }
+
+ return setFunction as KFunction2<ObjectType, ReturnType, Any?>
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <ObjectType, ReturnType, SetType> findAddFunction(
+ getFunction: KFunction1<ObjectType, ReturnType>
+ ): KFunction2<ObjectType, SetType, Any?>? {
+ val getFunctionName = getFunction.name
+ if (!getFunctionName.startsWith("get")) {
+ throw IllegalArgumentException("Unsupported method name $getFunctionName")
+ }
+
+ val setFunctionName = "add" + getFunctionName.removePrefix("get").run {
+ // Remove plurality
+ when {
+ endsWith("ies") -> "${removeSuffix("ies")}y"
+ endsWith("s") -> removeSuffix("s")
+ else -> this
+ }
+ }
+
+ val setFunction = setters.filter { it.name == setFunctionName }
+ .minByOrNull { it.parameters.size }
+
+ if (setFunction == null) {
+ expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
+ .fail()
+ return null
+ }
+
+ return setFunction as KFunction2<ObjectType, SetType, Any?>
+ }
+
+ protected fun <ObjectType, ReturnType> getter(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ valueToSet: ReturnType
+ ) = buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(getFunction, valueToSet)
+
+ protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getter(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ expectedValue: CompareType,
+ valueToSet: SetType
+ ): Param? {
+ return getSetByValue(
+ getFunction,
+ findSetFunction(getFunction) ?: return null,
+ value = expectedValue,
+ transformSet = { valueToSet }
+ )
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType> adder(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ value: ReturnType,
+ ): Param? {
+ return getSetByValue(
+ getFunction,
+ findAddFunction<ObjectType, Any?, ReturnType>(getFunction) ?: return null,
+ value,
+ transformGet = {
+ // Primitive arrays don't implement Iterable, so cast manually
+ when (it) {
+ is BooleanArray -> it.singleOrNull()
+ is IntArray -> it.singleOrNull()
+ is LongArray -> it.singleOrNull()
+ is Iterable<*> -> it.singleOrNull()
+ else -> null
+ }
+ },
+ )
+ }
+
+ /**
+ * Method to provide custom getter and setter logic for values which are not simple primitives
+ * or cannot be directly compared using [Objects.equals].
+ *
+ * @param getFunction the getter function which will be called and marked as tested
+ * @param setFunction the setter function which will be called and marked as tested
+ * @param value the value for comparison through the parcel-unparcel cycle, which can be
+ * anything, like the [String] ID of an inner object
+ * @param transformGet the function to transform the result of [getFunction] into [value]
+ * @param transformSet the function to transform [value] into an input for [setFunction]
+ * @param compare the function that compares the pre/post-parcel [value] objects
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getSetByValue(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ setFunction: KFunction2<ObjectType, SetType, Any?>,
+ value: CompareType,
+ transformGet: (ReturnType) -> CompareType = { it as CompareType },
+ transformSet: (CompareType) -> SetType = { it as SetType },
+ compare: (CompareType, CompareType) -> Boolean? = Objects::equals
+ ) = Param(
+ getFunction.name,
+ { transformGet(getFunction.call(it as ObjectType)) },
+ setFunction.name,
+ { setFunction.call(it.first() as ObjectType, transformSet(it[1] as CompareType)) },
+ { value },
+ { first, second -> compare(first as CompareType, second as CompareType) == true }
+ )
+
+ /**
+ * Variant of [getSetByValue] that allows specifying a [setFunction] with 2 inputs.
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <ObjectType, ReturnType, SetType1 : Any?, SetType2 : Any?, CompareType : Any?>
+ getSetByValue2(
+ getFunction: KFunction1<ObjectType, ReturnType>,
+ setFunction: KFunction3<ObjectType, SetType1, SetType2, Any>,
+ value: CompareType,
+ transformGet: (ReturnType) -> CompareType = { it as CompareType },
+ transformSet: (CompareType) -> Pair<SetType1, SetType2> =
+ { it as Pair<SetType1, SetType2> },
+ compare: (CompareType, CompareType) -> Boolean = Objects::equals
+ ) = Param(
+ getFunction.name,
+ { transformGet(getFunction.call(it as ObjectType)) },
+ setFunction.name,
+ {
+ val pair = transformSet(it[1] as CompareType)
+ setFunction.call(it.first() as ObjectType, pair.first, pair.second)
+ },
+ { value },
+ { first, second -> compare(first as CompareType, second as CompareType) }
+ )
+
+ protected fun autoValue(getFunction: KFunction<*>) = when (getFunction.returnType.jvmErasure) {
+ Boolean::class -> (getFunction.call(defaultImpl) as Boolean?)?.not() ?: true
+ CharSequence::class,
+ String::class -> getFunction.name + "TEST"
+ Int::class -> testCounter++
+ Long::class -> (testCounter++).toLong()
+ Float::class -> (testCounter++).toFloat()
+ else -> {
+ expect.withMessage("${getFunction.name} needs to provide value").fail()
+ null
+ }
+ }
+
+ /**
+ * Verifies two instances are equivalent via a series of properties. For use when a public API
+ * class has not implemented equals.
+ */
+ @Suppress("UNCHECKED_CAST")
+ protected fun <T : Any> equalBy(
+ first: T?,
+ second: T?,
+ vararg properties: (T) -> Any?
+ ) = properties.all { property ->
+ first?.let { property(it) } == second?.let { property(it) }
+ }
+
+ @Test
+ fun valueComparison() {
+ val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull()
+ val before = initialObject()
+
+ params.forEach { it.setFunction(arrayOf(before, it.value())) }
+
+ val parcel = Parcel.obtain()
+ writeToParcel(parcel, before)
+
+ val dataSize = parcel.dataSize()
+
+ parcel.setDataPosition(0)
+
+ val after = creator.createFromParcel(parcel)
+
+ expect.withMessage("Mismatched write and read data sizes")
+ .that(parcel.dataPosition())
+ .isEqualTo(dataSize)
+
+ parcel.recycle()
+
+ runAssertions(params, before, after)
+ }
+
+ @Test
+ open fun parcellingSize() {
+ val parcelOne = Parcel.obtain()
+ writeToParcel(parcelOne, initialObject())
+
+ val parcelTwo = Parcel.obtain()
+ initialObject().writeToParcel(parcelTwo, 0)
+
+ val superDataSizes = setterType.allSuperclasses
+ .filter { it.isSubclassOf(Parcelable::class) }
+ .mapNotNull { it.memberFunctions.find { it.name == "writeToParcel" } }
+ .filter { it.isFinal }
+ .map {
+ val parcel = Parcel.obtain()
+ initialObject().writeToParcel(parcel, 0)
+ parcel.dataSize().also { parcel.recycle() }
+ }
+
+ if ((superDataSizes + parcelOne.dataSize() + parcelTwo.dataSize()).distinct().size != 1) {
+ listOf(getterType, setterType).distinct().forEach {
+ val creatorProperties = it.staticProperties.filter { it.name == "CREATOR" }
+ if (creatorProperties.size > 1) {
+ expect.withMessage(
+ "Multiple matching CREATOR fields found for" +
+ it.qualifiedName
+ )
+ .that(creatorProperties)
+ .hasSize(1)
+ } else {
+ val creator = creatorProperties.single().get()
+ if (creator !is Parcelable.Creator<*>) {
+ expect.that(creator).isInstanceOf(Parcelable.Creator::class.java)
+ return
+ }
+
+ parcelTwo.setDataPosition(0)
+ val parcelable = creator.createFromParcel(parcelTwo)
+ if (parcelable::class.isSubclassOf(setterType)) {
+ expect.withMessage(
+ "${it.qualifiedName} which does not safely override writeToParcel " +
+ "cannot contain a subclass CREATOR field"
+ )
+ .fail()
+ }
+ }
+ }
+ }
+
+ parcelOne.recycle()
+ parcelTwo.recycle()
+ }
+
+ private fun runAssertions(params: List<Param>, before: Parcelable, after: Parcelable) {
+ params.forEach {
+ val actual = it.getFunction(after)
+ val expected = it.value()
+ val equal = it.compare(actual, expected)
+ expect.withMessage("${it.getFunctionName} was $actual, expected $expected")
+ .that(equal)
+ .isTrue()
+ }
+
+ extraAssertions(before, after)
+
+ // TODO: Handle method overloads?
+ val expectedFunctions = (getters.map { it.name }
+ + setters.map { it.name }
+ - excludedMethods)
+ .distinct()
+
+ val allTestedFunctions = params.flatMap {
+ listOfNotNull(it.getFunctionName, it.setFunctionName)
+ }
+ expect.that(allTestedFunctions).containsExactlyElementsIn(expectedFunctions)
+ }
+
+ open fun extraParams(): Collection<Param?> = emptyList()
+
+ open fun initialObject(): Parcelable = setterType.createInstance()
+
+ open fun extraAssertions(before: Parcelable, after: Parcelable) {}
+
+ open fun writeToParcel(parcel: Parcel, value: Parcelable) = value.writeToParcel(parcel, 0)
+
+ data class Param(
+ val getFunctionName: String,
+ val getFunction: (Any?) -> Any?,
+ val setFunctionName: String?,
+ val setFunction: (Array<Any?>) -> Unit,
+ val value: () -> Any?,
+ val compare: (Any?, Any?) -> Boolean = Objects::equals
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
new file mode 100644
index 000000000000..d506190b8b09
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorInvalidTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import org.junit.Test
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Verifies the failing side of [ParcelableCreatorValidTest]. The sole difference is the addition
+ * of [TestSubWithCreator.CREATOR].
+ */
+@ExperimentalContracts
+class ParcelableCreatorInvalidTest :
+ ParcelableComponentTest(TestSuperClass::class, TestSubWithCreator::class) {
+
+ override val defaultImpl = TestSubWithCreator()
+
+ override val creator = object : Parcelable.Creator<Parcelable> {
+ override fun createFromParcel(source: Parcel) = TestSubWithCreator(source)
+ override fun newArray(size: Int) = Array<TestSubWithCreator?>(size) { null }
+ }
+
+ override val excludedMethods = listOf("writeSubToParcel")
+
+ override val baseParams = listOf(TestSuperClass::getSuperString)
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+ (value as TestSubWithCreator).writeSubToParcel(parcel, 0)
+ }
+
+ @Test
+ override fun parcellingSize() {
+ super.parcellingSize()
+ if (expect.hasFailures()) {
+ // This is a hack to ignore an expected failure result. Doing it this way, rather than
+ // adding a switch in the test itself, prevents it from accidentally passing through a
+ // programming error.
+ ignoreableExpect.ignore()
+ }
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
new file mode 100644
index 000000000000..f1bc7b5a07f4
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableCreatorValidTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.os.Parcel
+import android.os.Parcelable
+import com.android.server.pm.test.parsing.parcelling.java.TestSubWithoutCreator
+import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
+import kotlin.contracts.ExperimentalContracts
+
+/**
+ * Tests the [Parcelable] CREATOR verification by using a mock object with known differences to
+ * ensure that the method succeeds/fails.
+ */
+@ExperimentalContracts
+class ParcelableCreatorValidTest :
+ ParcelableComponentTest(TestSuperClass::class, TestSubWithoutCreator::class) {
+
+ override val defaultImpl = TestSubWithoutCreator()
+
+ override val creator = object : Parcelable.Creator<Parcelable> {
+ override fun createFromParcel(source: Parcel) = TestSubWithoutCreator(source)
+ override fun newArray(size: Int) = Array<TestSubWithoutCreator?>(size) { null }
+ }
+
+ override val excludedMethods = listOf("writeSubToParcel")
+
+ override val baseParams = listOf(TestSuperClass::getSuperString)
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) {
+ (value as TestSubWithoutCreator).writeSubToParcel(parcel, 0)
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
new file mode 100644
index 000000000000..ece600bc446e
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.ActivityInfo
+import android.content.pm.parsing.component.ParsedActivity
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedActivityTest : ParsedMainComponentTest(ParsedActivity::class) {
+
+ override val defaultImpl = ParsedActivity()
+ override val creator = ParsedActivity.CREATOR
+
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedActivity::getPermission,
+ ParsedActivity::getColorMode,
+ ParsedActivity::getConfigChanges,
+ ParsedActivity::getDocumentLaunchMode,
+ ParsedActivity::getLaunchMode,
+ ParsedActivity::getLockTaskLaunchMode,
+ ParsedActivity::getMaxAspectRatio,
+ ParsedActivity::getMaxRecents,
+ ParsedActivity::getMinAspectRatio,
+ ParsedActivity::getParentActivityName,
+ ParsedActivity::getPersistableMode,
+ ParsedActivity::getPrivateFlags,
+ ParsedActivity::getRequestedVrComponent,
+ ParsedActivity::getResizeMode,
+ ParsedActivity::getRotationAnimation,
+ ParsedActivity::getScreenOrientation,
+ ParsedActivity::getSoftInputMode,
+ ParsedActivity::getTargetActivity,
+ ParsedActivity::getTaskAffinity,
+ ParsedActivity::getTheme,
+ ParsedActivity::getUiOptions,
+ ParsedActivity::isSupportsSizeChanges,
+ )
+
+ override fun mainComponentSubclassExtraParams() = listOf(
+ getSetByValue(
+ ParsedActivity::getWindowLayout,
+ ParsedActivity::setWindowLayout,
+ ActivityInfo.WindowLayout(1, 1f, 2, 1f, 3, 4, 5),
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ ActivityInfo.WindowLayout::width,
+ ActivityInfo.WindowLayout::widthFraction,
+ ActivityInfo.WindowLayout::height,
+ ActivityInfo.WindowLayout::heightFraction,
+ ActivityInfo.WindowLayout::gravity,
+ ActivityInfo.WindowLayout::minWidth,
+ ActivityInfo.WindowLayout::minHeight
+ )
+ }
+ )
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
new file mode 100644
index 000000000000..e739dc70cdbb
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedAttribution
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedAttributionTest : ParcelableComponentTest(ParsedAttribution::class) {
+
+ override val defaultImpl = ParsedAttribution("", 0, emptyList())
+ override val creator = ParsedAttribution.CREATOR
+
+ override val baseParams = listOf(
+ ParsedAttribution::getTag,
+ ParsedAttribution::getLabel,
+ )
+
+ override fun extraParams() = listOf(
+ getter(ParsedAttribution::getInheritFrom, listOf("testInheritFrom"))
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
new file mode 100644
index 000000000000..0a22f6d301a9
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.PackageManager
+import android.content.pm.parsing.component.ParsedComponent
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Bundle
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedComponentTest(kClass: KClass<out Parcelable>) :
+ ParcelableComponentTest(kClass) {
+
+ final override val excludedMethods
+ get() = subclassExcludedMethods + listOf(
+ // Method aliases/utilities
+ "getClassName",
+ "getComponentName",
+ "setProperties" // Tested though addProperty
+ )
+
+ open val subclassExcludedMethods: Collection<String> = emptyList()
+
+ final override val baseParams
+ get() = subclassBaseParams + listOf(
+ ParsedComponent::getBanner,
+ ParsedComponent::getDescriptionRes,
+ ParsedComponent::getFlags,
+ ParsedComponent::getIcon,
+ ParsedComponent::getLabelRes,
+ ParsedComponent::getLogo,
+ ParsedComponent::getName,
+ ParsedComponent::getNonLocalizedLabel,
+ ParsedComponent::getPackageName,
+ )
+
+ abstract val subclassBaseParams: Collection<KFunction1<*, Any?>>
+
+ final override fun extraParams() = subclassExtraParams() + listOf(
+ getSetByValue(
+ ParsedComponent::getIntents,
+ ParsedComponent::addIntent,
+ "TestLabel",
+ transformGet = { it.singleOrNull()?.nonLocalizedLabel },
+ transformSet = { ParsedIntentInfo().setNonLocalizedLabel(it) },
+ ),
+ getSetByValue(
+ ParsedComponent::getProperties,
+ ParsedComponent::addProperty,
+ PackageManager.Property(
+ "testPropertyName",
+ "testPropertyValue",
+ "testPropertyClassName",
+ "testPropertyPackageName"
+ ),
+ transformGet = { it["testPropertyName"] },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PackageManager.Property::getName,
+ PackageManager.Property::getClassName,
+ PackageManager.Property::getPackageName,
+ PackageManager.Property::getString,
+ )
+ }
+ ),
+ getSetByValue(
+ ParsedComponent::getMetaData,
+ ParsedComponent::setMetaData,
+ "testBundleKey" to "testBundleValue",
+ transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
+ transformSet = { Bundle().apply { putString(it.first, it.second) } }
+ ),
+ )
+
+ open fun subclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
new file mode 100644
index 000000000000..b7a85cc3d186
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedInstrumentation
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedInstrumentationTest : ParsedComponentTest(ParsedInstrumentation::class) {
+
+ override val defaultImpl = ParsedInstrumentation()
+ override val creator = ParsedInstrumentation.CREATOR
+
+ override val subclassBaseParams = listOf(
+ ParsedInstrumentation::getTargetPackage,
+ ParsedInstrumentation::getTargetProcesses,
+ ParsedInstrumentation::isFunctionalTest,
+ ParsedInstrumentation::isHandleProfiling,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
new file mode 100644
index 000000000000..e27bdf23cfc6
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Parcel
+import android.os.Parcelable
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedIntentInfoTest : ParcelableComponentTest(ParsedIntentInfo::class) {
+
+ override val defaultImpl = ParsedIntentInfo()
+
+ override val creator = object : Parcelable.Creator<ParsedIntentInfo> {
+ override fun createFromParcel(source: Parcel) = ParsedIntentInfo(source)
+ override fun newArray(size: Int) = Array<ParsedIntentInfo?>(size) { null }
+ }
+
+ override val excludedMethods = listOf(
+ // Used to parcel
+ "writeIntentInfoToParcel",
+ // All remaining IntentFilter methods, which are out of scope
+ "hasDataPath",
+ "hasDataSchemeSpecificPart",
+ "matchAction",
+ "matchData",
+ "actionsIterator",
+ "addAction",
+ "addCategory",
+ "addDataAuthority",
+ "addDataPath",
+ "addDataScheme",
+ "addDataSchemeSpecificPart",
+ "addDataType",
+ "addDynamicDataType",
+ "addMimeGroup",
+ "asPredicate",
+ "asPredicateWithTypeResolution",
+ "authoritiesIterator",
+ "categoriesIterator",
+ "clearDynamicDataTypes",
+ "countActions",
+ "countCategories",
+ "countDataAuthorities",
+ "countDataPaths",
+ "countDataSchemeSpecificParts",
+ "countDataSchemes",
+ "countDataTypes",
+ "countMimeGroups",
+ "countStaticDataTypes",
+ "dataTypes",
+ "debugCheck",
+ "dump",
+ "dumpDebug",
+ "getAction",
+ "getAutoVerify",
+ "getCategory",
+ "getDataAuthority",
+ "getDataPath",
+ "getDataScheme",
+ "getDataSchemeSpecificPart",
+ "getDataType",
+ "getHosts",
+ "getHostsList",
+ "getMimeGroup",
+ "getOrder",
+ "getPriority",
+ "getVisibilityToInstantApp",
+ "handleAllWebDataURI",
+ "handlesWebUris",
+ "hasAction",
+ "hasCategory",
+ "hasDataAuthority",
+ "hasDataScheme",
+ "hasDataType",
+ "hasExactDataType",
+ "hasExactDynamicDataType",
+ "hasExactStaticDataType",
+ "hasMimeGroup",
+ "isExplicitlyVisibleToInstantApp",
+ "isImplicitlyVisibleToInstantApp",
+ "isVerified",
+ "isVisibleToInstantApp",
+ "match",
+ "matchCategories",
+ "matchDataAuthority",
+ "mimeGroupsIterator",
+ "needsVerification",
+ "pathsIterator",
+ "readFromXml",
+ "schemeSpecificPartsIterator",
+ "schemesIterator",
+ "setAutoVerify",
+ "setOrder",
+ "setPriority",
+ "setVerified",
+ "setVisibilityToInstantApp",
+ "typesIterator",
+ "writeToXml",
+ )
+
+ override val baseParams = listOf(
+ ParsedIntentInfo::getIcon,
+ ParsedIntentInfo::getLabelRes,
+ ParsedIntentInfo::isHasDefault,
+ ParsedIntentInfo::getNonLocalizedLabel,
+ )
+
+ override fun initialObject() = ParsedIntentInfo().apply {
+ addAction("test.ACTION")
+ addDataAuthority("testAuthority", "404")
+ addCategory("test.CATEGORY")
+ addMimeGroup("testMime")
+ addDataPath("testPath", PatternMatcher.PATTERN_LITERAL)
+ }
+
+ override fun extraAssertions(before: Parcelable, after: Parcelable) {
+ super.extraAssertions(before, after)
+ after as ParsedIntentInfo
+ expect.that(after.actionsIterator().asSequence().singleOrNull())
+ .isEqualTo("test.ACTION")
+
+ val authority = after.authoritiesIterator().asSequence().singleOrNull()
+ expect.that(authority?.host).isEqualTo("testAuthority")
+ expect.that(authority?.port).isEqualTo(404)
+
+ expect.that(after.categoriesIterator().asSequence().singleOrNull())
+ .isEqualTo("test.CATEGORY")
+ expect.that(after.mimeGroupsIterator().asSequence().singleOrNull())
+ .isEqualTo("testMime")
+ expect.that(after.hasDataPath("testPath")).isTrue()
+ }
+
+ override fun writeToParcel(parcel: Parcel, value: Parcelable) =
+ ParsedIntentInfo.PARCELER.parcel(value as ParsedIntentInfo, parcel, 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
new file mode 100644
index 000000000000..411cb0950d18
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedMainComponent
+import android.content.pm.parsing.component.ParsedService
+import android.os.Parcelable
+import java.util.Arrays
+import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KClass
+import kotlin.reflect.KFunction1
+
+@ExperimentalContracts
+abstract class ParsedMainComponentTest(kClass: KClass<out Parcelable>) :
+ ParsedComponentTest(kClass) {
+
+ final override val subclassBaseParams
+ get() = mainComponentSubclassBaseParams + listOf(
+ ParsedMainComponent::getOrder,
+ ParsedMainComponent::getProcessName,
+ ParsedMainComponent::getSplitName,
+ ParsedMainComponent::isDirectBootAware,
+ ParsedMainComponent::isEnabled,
+ ParsedMainComponent::isExported,
+ )
+
+ abstract val mainComponentSubclassBaseParams: Collection<KFunction1<*, Any?>>
+
+ final override fun subclassExtraParams() = mainComponentSubclassExtraParams() + listOf(
+ getSetByValue(
+ ParsedService::getAttributionTags,
+ ParsedService::setAttributionTags,
+ arrayOf("testAttributionTag"),
+ compare = Arrays::equals
+ ),
+ )
+
+ open fun mainComponentSubclassExtraParams(): Collection<Param?> = emptyList()
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
new file mode 100644
index 000000000000..53c862a519b1
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionGroupTest : ParsedComponentTest(ParsedPermissionGroup::class) {
+
+ override val defaultImpl = ParsedPermissionGroup()
+ override val creator = ParsedPermissionGroup.CREATOR
+
+ override val subclassBaseParams = listOf(
+ ParsedPermissionGroup::getRequestDetailResourceId,
+ ParsedPermissionGroup::getBackgroundRequestDetailResourceId,
+ ParsedPermissionGroup::getBackgroundRequestResourceId,
+ ParsedPermissionGroup::getRequestRes,
+ ParsedPermissionGroup::getPriority,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
new file mode 100644
index 000000000000..bb63e2e2a61d
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedPermission
+import android.content.pm.parsing.component.ParsedPermissionGroup
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedPermissionTest : ParsedComponentTest(ParsedPermission::class) {
+
+ override val defaultImpl = ParsedPermission()
+ override val creator = ParsedPermission.CREATOR
+
+ override val subclassExcludedMethods = listOf(
+ // Utility methods
+ "isAppOp",
+ "isRuntime",
+ "getProtection",
+ "getProtectionFlags",
+ "calculateFootprint",
+ "setKnownCert", // Tested through setKnownCerts
+ )
+ override val subclassBaseParams = listOf(
+ ParsedPermission::getBackgroundPermission,
+ ParsedPermission::getGroup,
+ ParsedPermission::getRequestRes,
+ ParsedPermission::getProtectionLevel,
+ ParsedPermission::isTree,
+ )
+
+ override fun subclassExtraParams() = listOf(
+ getter(ParsedPermission::getKnownCerts, setOf("testCert")),
+ getSetByValue(
+ ParsedPermission::getParsedPermissionGroup,
+ ParsedPermission::setParsedPermissionGroup,
+ ParsedPermissionGroup().apply { name = "test.permission.group" },
+ compare = { first, second -> equalBy(first, second, ParsedPermissionGroup::getName) }
+ ),
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
new file mode 100644
index 000000000000..34f46f2c0adb
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedProcess
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProcessTest : ParcelableComponentTest(ParsedProcess::class) {
+
+ override val defaultImpl = ParsedProcess()
+ override val creator = ParsedProcess.CREATOR
+
+ override val excludedMethods = listOf(
+ // Copying method
+ "addStateFrom",
+ )
+
+ override val baseParams = listOf(
+ ParsedProcess::getName,
+ ParsedProcess::getGwpAsanMode,
+ ParsedProcess::getMemtagMode,
+ ParsedProcess::getNativeHeapZeroInitialized,
+ )
+
+ override fun extraParams() = listOf(
+ getter(ParsedProcess::getDeniedPermissions, setOf("testDeniedPermission"))
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
new file mode 100644
index 000000000000..e6d5c0fd258f
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.PathPermission
+import android.content.pm.parsing.component.ParsedProvider
+import android.os.PatternMatcher
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedProviderTest : ParsedMainComponentTest(ParsedProvider::class) {
+
+ override val defaultImpl = ParsedProvider()
+ override val creator = ParsedProvider.CREATOR
+
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedProvider::getAuthority,
+ ParsedProvider::isSyncable,
+ ParsedProvider::getReadPermission,
+ ParsedProvider::getWritePermission,
+ ParsedProvider::isGrantUriPermissions,
+ ParsedProvider::isForceUriPermissions,
+ ParsedProvider::isMultiProcess,
+ ParsedProvider::getInitOrder,
+ )
+
+ override fun mainComponentSubclassExtraParams() = listOf(
+ getSetByValue(
+ ParsedProvider::getUriPermissionPatterns,
+ ParsedProvider::setUriPermissionPatterns,
+ PatternMatcher("testPattern", PatternMatcher.PATTERN_LITERAL),
+ transformGet = { it?.singleOrNull() },
+ transformSet = { arrayOf(it) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PatternMatcher::getPath,
+ PatternMatcher::getType
+ )
+ }
+ ),
+ getSetByValue(
+ ParsedProvider::getPathPermissions,
+ ParsedProvider::setPathPermissions,
+ PathPermission(
+ "testPermissionPattern",
+ PatternMatcher.PATTERN_LITERAL,
+ "test.READ_PERMISSION",
+ "test.WRITE_PERMISSION"
+ ),
+ transformGet = { it?.singleOrNull() },
+ transformSet = { arrayOf(it) },
+ compare = { first, second ->
+ equalBy(
+ first, second,
+ PatternMatcher::getPath,
+ PatternMatcher::getType,
+ PathPermission::getReadPermission,
+ PathPermission::getWritePermission,
+ )
+ }
+ )
+ )
+}
diff --git a/core/java/android/uwb/AdapterState.aidl b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
index 991f64a0c0ae..553018493f8b 100644
--- a/core/java/android/uwb/AdapterState.aidl
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 The Android Open Source Project
+ * Copyright (C) 2021 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,25 +14,19 @@
* limitations under the License.
*/
-package android.uwb;
+package com.android.server.pm.test.parsing.parcelling
-/**
- * @hide
- */
-@Backing(type="int")
-enum AdapterState {
- /**
- * The state when UWB is disabled.
- */
- STATE_DISABLED,
+import android.content.pm.parsing.component.ParsedService
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedServiceTest : ParsedMainComponentTest(ParsedService::class) {
- /**
- * The state when UWB is enabled but has no active sessions.
- */
- STATE_ENABLED_INACTIVE,
+ override val defaultImpl = ParsedService()
+ override val creator = ParsedService.CREATOR
- /**
- * The state when UWB is enabled and has active sessions.
- */
- STATE_ENABLED_ACTIVE,
-} \ No newline at end of file
+ override val mainComponentSubclassBaseParams = listOf(
+ ParsedService::getForegroundServiceType,
+ ParsedService::getPermission,
+ )
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
new file mode 100644
index 000000000000..1131c72152ad
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling
+
+import android.content.pm.parsing.component.ParsedUsesPermission
+import android.os.Parcelable
+import kotlin.contracts.ExperimentalContracts
+
+@ExperimentalContracts
+class ParsedUsesPermissionTest : ParcelableComponentTest(ParsedUsesPermission::class) {
+
+ override val defaultImpl = ParsedUsesPermission("", 0)
+ override val creator = ParsedUsesPermission.CREATOR
+
+ override val baseParams = listOf(
+ ParsedUsesPermission::getName,
+ ParsedUsesPermission::getUsesPermissionFlags
+ )
+
+ override fun initialObject() = ParsedUsesPermission("", 0)
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
new file mode 100644
index 000000000000..581d2b2d72b8
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithCreator.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithCreator extends TestSuperClass {
+
+ @NonNull
+ public static final Parcelable.Creator<TestSubWithCreator> CREATOR =
+ new Parcelable.Creator<TestSubWithCreator>() {
+ @Override
+ public TestSubWithCreator createFromParcel(Parcel source) {
+ return new TestSubWithCreator(source);
+ }
+
+ @Override
+ public TestSubWithCreator[] newArray(int size) {
+ return new TestSubWithCreator[size];
+ }
+ };
+
+ @Nullable
+ private String subString;
+
+ public TestSubWithCreator() {
+ }
+
+ public TestSubWithCreator(@NonNull Parcel in) {
+ super(in);
+ subString = in.readString();
+ }
+
+ public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeString(subString);
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
new file mode 100644
index 000000000000..4264a11c03e3
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSubWithoutCreator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import androidx.annotation.NonNull;
+
+public class TestSubWithoutCreator extends TestSuperClass {
+
+ @Nullable
+ private String subString;
+
+ public TestSubWithoutCreator() {
+ }
+
+ public TestSubWithoutCreator(@NonNull Parcel in) {
+ super(in);
+ subString = in.readString();
+ }
+
+ public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeString(subString);
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
new file mode 100644
index 000000000000..a009786de352
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 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.pm.test.parsing.parcelling.java;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+@DataClass(genGetters = true, genSetters = true, genBuilder = false, genAidl = false,
+ genParcelable = true, genConstructor = false)
+public class TestSuperClass implements Parcelable {
+
+ @Nullable
+ private String superString;
+
+ public TestSuperClass() {
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public @Nullable String getSuperString() {
+ return superString;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull TestSuperClass setSuperString(@NonNull String value) {
+ superString = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (superString != null) flg |= 0x1;
+ dest.writeByte(flg);
+ if (superString != null) dest.writeString(superString);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected TestSuperClass(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ String _superString = (flg & 0x1) == 0 ? null : in.readString();
+
+ this.superString = _superString;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<TestSuperClass> CREATOR
+ = new Parcelable.Creator<TestSuperClass>() {
+ @Override
+ public TestSuperClass[] newArray(int size) {
+ return new TestSuperClass[size];
+ }
+
+ @Override
+ public TestSuperClass createFromParcel(@NonNull android.os.Parcel in) {
+ return new TestSuperClass(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1624381019144L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java",
+ inputSignatures = "private @android.annotation.Nullable java.lang.String superString\nclass TestSuperClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genAidl=false, genParcelable=true, genConstructor=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
new file mode 100644
index 000000000000..afb18f5be669
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/util/IgnoreableExpect.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.pm.test.util
+
+import com.google.common.truth.Expect
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * Wrapper for [Expect] which supports ignoring any failures. This should be used with caution, but
+ * it allows a base test to be written which doesn't switch success/failure in the test itself,
+ * preventing any logic errors from causing the test to accidentally succeed.
+ */
+internal class IgnoreableExpect : TestRule {
+
+ val expect = Expect.create()
+
+ private var ignore = false
+
+ override fun apply(base: Statement?, description: Description?): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ ignore = false
+ try {
+ expect.apply(base, description).evaluate()
+ } catch (t: Throwable) {
+ if (!ignore) {
+ throw t
+ }
+ }
+ }
+ }
+ }
+
+ fun ignore() {
+ ignore = true
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java
new file mode 100644
index 000000000000..b3dc3eda362c
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2021 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.am;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+
+import android.app.compat.CompatChanges;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ServiceInfo;
+import android.os.SystemClock;
+import android.util.ArraySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class ActiveServicesTest {
+
+ private static final long DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN = 10 * 1000;
+ private static final long[] DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE = {
+ 0,
+ DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN,
+ DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN * 2,
+ DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN * 3
+ };
+
+ private MockitoSession mMockingSession;
+ private ActivityManagerService mService;
+ private ActiveServices mActiveServices;
+ private AppProfiler mProfiler;
+
+ @Before
+ public void setUp() {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .mockStatic(CompatChanges.class)
+ .startMocking();
+ prepareTestRescheduleServiceRestarts();
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testRescheduleServiceRestartsOnChanges() throws Exception {
+ final long now = SystemClock.uptimeMillis();
+ final long btwn = mService.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
+ final long rd0 = 0;
+ final long rd1 = 1000;
+ final long rd2 = rd1 + btwn;
+ final long rd3 = rd2 + btwn;
+ final long rd4 = rd3 + btwn * 10;
+ final long rd5 = rd4 + btwn;
+ int memFactor = ADJ_MEM_FACTOR_MODERATE;
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+ fillInRestartingServices(now, new long[] {rd0, rd1, rd2, rd3, rd4, rd5});
+
+ // Test enable/disable.
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(false, true, now);
+ long extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ verifyDelays(now, new long[] {rd0, extra, btwn + extra * 2, btwn * 2 + extra * 3, rd4,
+ rd5 + extra});
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(true, false, now);
+ verifyDelays(now, new long[] {rd0, rd1, rd2, rd3, rd4, rd5});
+
+ final long elapsed = 10;
+ final long now2 = now + elapsed;
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(false, true, now2);
+ verifyDelays(now2, new long[] {rd0 - elapsed, extra - elapsed,
+ btwn + extra * 2 - elapsed, btwn * 2 + extra * 3 - elapsed, rd4 - elapsed,
+ rd5 + extra - elapsed});
+
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(true, false, now2);
+ verifyDelays(now2, new long[] {rd0 - elapsed, rd1 - elapsed, rd2 - elapsed, rd3 - elapsed,
+ rd4 - elapsed, rd5 - elapsed});
+
+ // Test memory level changes.
+ memFactor = ADJ_MEM_FACTOR_LOW;
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+ extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ final long elapsed3 = elapsed * 2;
+ final long now3 = now + elapsed3;
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ ADJ_MEM_FACTOR_MODERATE, memFactor, "test", now3);
+ verifyDelays(now3, new long[] {rd0 - elapsed3, extra - elapsed3,
+ btwn + extra * 2 - elapsed3, btwn * 2 + extra * 3 - elapsed3, rd4 - elapsed3,
+ rd5 + extra - elapsed3});
+
+ memFactor = ADJ_MEM_FACTOR_CRITICAL;
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+ extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ final long elapsed4 = elapsed * 3;
+ final long now4 = now + elapsed4;
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ ADJ_MEM_FACTOR_LOW, memFactor, "test", now4);
+ verifyDelays(now4, new long[] {rd0 - elapsed4, extra - elapsed4,
+ btwn + extra * 2 - elapsed4, btwn * 2 + extra * 3 - elapsed4,
+ btwn * 3 + extra * 4 - elapsed4, btwn * 4 + extra * 5 - elapsed4});
+
+ memFactor = ADJ_MEM_FACTOR_MODERATE;
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+ extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ final long elapsed5 = elapsed * 4;
+ final long now5 = now + elapsed5;
+ mActiveServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ ADJ_MEM_FACTOR_CRITICAL, memFactor, "test", now5);
+ verifyDelays(now5, new long[] {rd0 - elapsed5, extra - elapsed5,
+ btwn + extra * 2 - elapsed5, btwn * 2 + extra * 3 - elapsed5,
+ rd4 - elapsed5, rd5 + extra - elapsed5});
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testRescheduleServiceRestartsOnOtherChanges() throws Exception {
+ final long now = SystemClock.uptimeMillis();
+ final long btwn = mService.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
+ final long rd0 = 1000;
+ final long rd1 = 2000;
+ final long rd2 = btwn * 10;
+ final long rd3 = 5000;
+ final long rd4 = btwn * 11 + 5000;
+ final long rd5 = 3000;
+ int memFactor = ADJ_MEM_FACTOR_CRITICAL;
+ long extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+
+ fillInRestartingServices(now, new long[] {rd0, rd1, rd2, rd3, rd4, rd5});
+ setNextRestarts(now, new long[] {extra, btwn + extra * 2, btwn * 2 + extra * 3,
+ btwn * 3 + extra * 4, btwn * 4 + extra * 5, btwn * 5 + extra * 6});
+ mActiveServices.mRestartingServices.remove(1);
+ mActiveServices.rescheduleServiceRestartIfPossibleLocked(extra, btwn, "test", now);
+ verifyDelays(now, new long[] {extra, rd2, rd2 + btwn + extra,
+ rd2 + (btwn + extra) * 2, rd2 + (btwn + extra) * 3});
+ mActiveServices.mRestartingServices.remove(0);
+ mActiveServices.rescheduleServiceRestartIfPossibleLocked(extra, btwn, "test", now);
+ verifyDelays(now, new long[] {extra, rd2, rd2 + btwn + extra, rd2 + (btwn + extra) * 2});
+ mActiveServices.mRestartingServices.remove(1);
+ mActiveServices.rescheduleServiceRestartIfPossibleLocked(extra, btwn, "test", now);
+ verifyDelays(now, new long[] {extra, btwn + extra * 2, rd4});
+
+ fillInRestartingServices(now, new long[] {rd0, rd1, rd2, rd3, rd4, rd5});
+ setNextRestarts(now, new long[] {extra, btwn + extra * 2, btwn * 2 + extra * 3,
+ btwn * 3 + extra * 4, btwn * 4 + extra * 5, btwn * 5 + extra * 6});
+ mActiveServices.mRestartingServices.remove(1);
+ mActiveServices.rescheduleServiceRestartIfPossibleLocked(extra, btwn, "test", now);
+ memFactor = ADJ_MEM_FACTOR_LOW;
+ extra = mService.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
+ when(mService.mAppProfiler.getLastMemoryLevelLocked()).thenReturn(memFactor);
+ mActiveServices.rescheduleServiceRestartIfPossibleLocked(extra, btwn, "test", now);
+ verifyDelays(now, new long[] {extra, btwn + extra * 2, rd2,
+ rd2 + btwn + extra, rd2 + (btwn + extra) * 2});
+ }
+
+ private void prepareTestRescheduleServiceRestarts() {
+ mService = mock(ActivityManagerService.class);
+ mService.mConstants = mock(ActivityManagerConstants.class);
+ mService.mConstants.mEnableExtraServiceRestartDelayOnMemPressure = true;
+ mService.mConstants.mExtraServiceRestartDelayOnMemPressure =
+ DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;
+ mService.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN =
+ DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN;
+ mProfiler = mock(AppProfiler.class);
+ setFieldValue(ActivityManagerService.class, mService, "mAppProfiler", mProfiler);
+ when(mProfiler.getLastMemoryLevelLocked()).thenReturn(ADJ_MEM_FACTOR_NORMAL);
+ mActiveServices = mock(ActiveServices.class);
+ setFieldValue(ActiveServices.class, mActiveServices, "mAm", mService);
+ setFieldValue(ActiveServices.class, mActiveServices, "mRestartingServices",
+ new ArrayList<>());
+ setFieldValue(ActiveServices.class, mActiveServices, "mRestartBackoffDisabledPackages",
+ new ArraySet<>());
+ doNothing().when(mActiveServices).performScheduleRestartLocked(any(ServiceRecord.class),
+ any(String.class), any(String.class), anyLong());
+ doCallRealMethod().when(mActiveServices)
+ .rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ anyBoolean(), anyBoolean(), anyLong());
+ doCallRealMethod().when(mActiveServices)
+ .rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
+ anyInt(), anyInt(), any(String.class), anyLong());
+ doCallRealMethod().when(mActiveServices)
+ .rescheduleServiceRestartIfPossibleLocked(
+ anyLong(), anyLong(), any(String.class), anyLong());
+ doCallRealMethod().when(mActiveServices)
+ .performRescheduleServiceRestartOnMemoryPressureLocked(
+ anyLong(), anyLong(), any(String.class), anyLong());
+ doCallRealMethod().when(mActiveServices).getExtraRestartTimeInBetweenLocked();
+ doCallRealMethod().when(mActiveServices)
+ .isServiceRestartBackoffEnabledLocked(any(String.class));
+ }
+
+ private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ Field mfield = Field.class.getDeclaredField("accessFlags");
+ mfield.setAccessible(true);
+ mfield.setInt(field, mfield.getInt(field) & ~(Modifier.FINAL | Modifier.PRIVATE));
+ field.set(obj, val);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ }
+ }
+
+ private void fillInRestartingServices(long now, long[] delays) {
+ mActiveServices.mRestartingServices.clear();
+ for (int i = 0; i < delays.length; i++) {
+ mActiveServices.mRestartingServices.add(
+ createRestartingService("testpackage" + i, now, delays[i]));
+ }
+ }
+
+ private void setNextRestarts(long now, long[] nextRestartDelays) {
+ for (int i = 0; i < nextRestartDelays.length; i++) {
+ final ServiceRecord r = mActiveServices.mRestartingServices.get(i);
+ r.restartDelay = nextRestartDelays[i];
+ r.nextRestartTime = now + r.restartDelay;
+ }
+ }
+
+ private ServiceRecord createRestartingService(String packageName, long now, long delay) {
+ final ServiceRecord r = mock(ServiceRecord.class);
+ r.appInfo = new ApplicationInfo();
+ r.appInfo.flags = delay == 0 ? ApplicationInfo.FLAG_PERSISTENT : 0;
+ final ServiceInfo si = new ServiceInfo();
+ setFieldValue(ServiceRecord.class, r, "serviceInfo", si);
+ setFieldValue(ServiceRecord.class, r, "packageName", packageName);
+ si.applicationInfo = r.appInfo;
+ r.nextRestartTime = r.mEarliestRestartTime = now + delay;
+ r.mRestartSchedulingTime = now;
+ r.restartDelay = delay;
+ return r;
+ }
+
+ private void verifyDelays(long now, long[] delays) throws Exception {
+ for (int i = 0; i < delays.length; i++) {
+ final ServiceRecord r = mActiveServices.mRestartingServices.get(i);
+ assertEquals("Expected restart delay=" + delays[i],
+ Math.max(0, delays[i]), r.restartDelay);
+ assertEquals("Expected next restart time=" + (now + delays[i]),
+ now + delays[i], r.nextRestartTime);
+ }
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 20a58426f1eb..a883293b13b9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -173,8 +173,6 @@ public final class CachedAppOptimizerTest {
CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
- assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_FREEZER);
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
@@ -188,6 +186,10 @@ public final class CachedAppOptimizerTest {
}
assertThat(mCachedAppOptimizerUnderTest.mProcStateThrottle)
.containsExactlyElementsIn(expected);
+
+ Assume.assumeTrue(mCachedAppOptimizerUnderTest.isFreezerSupported());
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
+ CachedAppOptimizer.DEFAULT_USE_FREEZER);
}
@Test
@@ -244,9 +246,8 @@ public final class CachedAppOptimizerTest {
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ - 10), false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
CachedAppOptimizer.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false);
- assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_FREEZER);
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
CachedAppOptimizer.KEY_USE_FREEZER, CachedAppOptimizer.DEFAULT_USE_FREEZER
? "false" : "true", false);
@@ -291,7 +292,8 @@ public final class CachedAppOptimizerTest {
CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1);
assertThat(mCachedAppOptimizerUnderTest.mProcStateThrottle).containsExactly(1, 2, 3);
- if (mCachedAppOptimizerUnderTest.isFreezerSupported()) {
+ Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
+ if (CachedAppOptimizer.isFreezerSupported()) {
if (CachedAppOptimizer.DEFAULT_USE_FREEZER) {
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
} else {
@@ -325,15 +327,15 @@ public final class CachedAppOptimizerTest {
@Test
public void useFreeze_doesNotListenToDeviceConfigChanges() throws InterruptedException {
- Assume.assumeTrue(mCachedAppOptimizerUnderTest.isFreezerSupported());
+ Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
- assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_FREEZER);
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
// The freezer DeviceConfig property is read at boot only
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
CachedAppOptimizer.KEY_USE_FREEZER, "true", false);
mCachedAppOptimizerUnderTest.init();
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isTrue();
mCountDown = new CountDownLatch(1);
// No notifications should get to the cached app optimizer.
@@ -346,14 +348,13 @@ public final class CachedAppOptimizerTest {
// Set the flag the other way without rebooting. It shall not change.
mCountDown = new CountDownLatch(1);
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
CachedAppOptimizer.KEY_USE_FREEZER, "false", false);
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isTrue();
-
// Now, set the flag to false and restart the cached app optimizer
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
CachedAppOptimizer.KEY_USE_FREEZER, "false", false);
mCachedAppOptimizerUnderTest.init();
@@ -380,18 +381,17 @@ public final class CachedAppOptimizerTest {
@Test
public void useFreeze_listensToDeviceConfigChangesBadValues() throws InterruptedException {
- assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_FREEZER);
+ Assume.assumeTrue(CachedAppOptimizer.isFreezerSupported());
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
// When we push an invalid flag value...
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
CachedAppOptimizer.KEY_USE_FREEZER, "foobar", false);
mCachedAppOptimizerUnderTest.init();
- // Then we set the default.
- assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_FREEZER);
+ // DeviceConfig treats invalid value as false
+ assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isFalse();
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
index 589a3497435e..457c8db9fdf3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
@@ -48,7 +48,7 @@ import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
/**
- * Run it as {@code atest FrameworksMockingCoreTests:FactoryResetterTest}
+ * Run it as {@code atest FrameworksMockingServicesTests:FactoryResetterTest}
*/
@Presubmit
public final class FactoryResetterTest {
diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OwnerShellDataTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OwnerShellDataTest.java
new file mode 100644
index 000000000000..dd67d7208034
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OwnerShellDataTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 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.os.UserHandle.USER_NULL;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.testng.Assert.expectThrows;
+
+import android.content.ComponentName;
+
+import org.junit.Test;
+
+/**
+ * Run it as {@code atest FrameworksMockingServicesTests:OwnerShellDataTest}
+ */
+public final class OwnerShellDataTest {
+
+ private static final int USER_ID = 007;
+ private static final int PARENT_USER_ID = 'M' + 'I' + 6;
+ private static final ComponentName ADMIN = new ComponentName("Bond", "James");
+
+ @Test
+ public void testForDeviceOwner_noAdmin() {
+ expectThrows(NullPointerException.class,
+ () -> OwnerShellData.forDeviceOwner(USER_ID, /* admin= */ null));
+ }
+
+ @Test
+ public void testForDeviceOwner_invalidUser() {
+ expectThrows(IllegalArgumentException.class,
+ () -> OwnerShellData.forDeviceOwner(USER_NULL, ADMIN));
+ }
+
+ @Test
+ public void testForDeviceOwner() {
+ OwnerShellData dto = OwnerShellData.forDeviceOwner(USER_ID, ADMIN);
+
+ assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
+ assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
+ .isEqualTo(USER_NULL);
+ assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
+ assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isTrue();
+ assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isFalse();
+ assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
+ .isFalse();
+ assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
+ }
+
+ @Test
+ public void testForUserProfileOwner_noAdmin() {
+ expectThrows(NullPointerException.class,
+ () -> OwnerShellData.forUserProfileOwner(USER_ID, /* admin= */ null));
+ }
+
+ @Test
+ public void testForUserProfileOwner_invalidUser() {
+ expectThrows(IllegalArgumentException.class,
+ () -> OwnerShellData.forUserProfileOwner(USER_NULL, ADMIN));
+ }
+
+ @Test
+ public void testForUserProfileOwner() {
+ OwnerShellData dto = OwnerShellData.forUserProfileOwner(USER_ID, ADMIN);
+
+ assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
+ assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
+ .isEqualTo(USER_NULL);
+ assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
+ assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isFalse();
+ assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isTrue();
+ assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
+ .isFalse();
+ assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
+ }
+
+ @Test
+ public void testForManagedProfileOwner_noAdmin() {
+ expectThrows(NullPointerException.class,
+ () -> OwnerShellData.forManagedProfileOwner(USER_ID, PARENT_USER_ID, null));
+ }
+
+ @Test
+ public void testForManagedProfileOwner_invalidUser() {
+ expectThrows(IllegalArgumentException.class,
+ () -> OwnerShellData.forManagedProfileOwner(USER_NULL, PARENT_USER_ID, ADMIN));
+ }
+
+ @Test
+ public void testForManagedProfileOwner_invalidParent() {
+ expectThrows(IllegalArgumentException.class,
+ () -> OwnerShellData.forManagedProfileOwner(USER_ID, USER_NULL, ADMIN));
+ }
+
+ @Test
+ public void testForManagedProfileOwner_parentOfItself() {
+ expectThrows(IllegalArgumentException.class,
+ () -> OwnerShellData.forManagedProfileOwner(USER_ID, USER_ID, ADMIN));
+ }
+
+ @Test
+ public void testForManagedProfileOwner() {
+ OwnerShellData dto = OwnerShellData.forManagedProfileOwner(USER_ID, PARENT_USER_ID, ADMIN);
+
+ assertWithMessage("dto(%s).userId", dto).that(dto.userId).isEqualTo(USER_ID);
+ assertWithMessage("dto(%s).parentUserId", dto).that(dto.parentUserId)
+ .isEqualTo(PARENT_USER_ID);
+ assertWithMessage("dto(%s).admin", dto).that(dto.admin).isSameInstanceAs(ADMIN);
+ assertWithMessage("dto(%s).isDeviceOwner", dto).that(dto.isDeviceOwner).isFalse();
+ assertWithMessage("dto(%s).isProfileOwner", dto).that(dto.isProfileOwner).isFalse();
+ assertWithMessage("dto(%s).isManagedProfileOwner", dto).that(dto.isManagedProfileOwner)
+ .isTrue();
+ assertWithMessage("dto(%s).isAffiliated", dto).that(dto.isAffiliated).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index d1afa1a997bf..c19155f51743 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -37,7 +37,6 @@ android_test {
"services.net",
"services.people",
"services.usage",
- "services.uwb",
"guava",
"guava-android-testlib",
"androidx.test.core",
diff --git a/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
index 10f4c05eb6d8..9dd413bcdbab 100644
--- a/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
@@ -16,6 +16,10 @@
package com.android.server.am;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -28,6 +32,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.server.wm.settings.SettingsSession;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -36,6 +43,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.SystemUtil;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,6 +67,12 @@ public final class ServiceRestarterTest {
"com.android.servicestests.apps.simpleservicetestapp3";
private static final String TEST_SERVICE_NAME =
"com.android.servicestests.apps.simpleservicetestapp.SimpleService";
+ private static final String[] MEMORY_PRESSURE_MAP = {
+ "NORMAL", "MODERATE", "LOW", "CRITICAL"};
+ private static final String EXTRA_DELAY = "0,2000,4000,8000";
+ private static final int SERVICE_RESTART_DURATION_FACTOR = 2;
+ private static final long BOUND_SERVICE_CRASH_RESTART_DURATION = 1000;
+ private static final long SERVICE_MIN_RESTART_TIME_BETWEEN = 1000;
private static final long WAIT_MS = 5 * 1000;
private static final long WAIT_LONG_MS = 30 * 1000;
@@ -69,6 +83,10 @@ public final class ServiceRestarterTest {
private static final int ACTION_STOPPKG = 8;
private static final int ACTION_ALL = ACTION_START | ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG;
+ private SettingsSession<String> mAMConstantsSettings;
+ private DeviceConfigSession<String> mExtraDelaysDeviceConfig;
+ private DeviceConfigSession<Boolean> mEnableExtraDelaysDeviceConfig;
+
private Context mContext;
private Instrumentation mInstrumentation;
private int mTestPackage1Uid;
@@ -85,6 +103,40 @@ public final class ServiceRestarterTest {
mTestPackage2Uid = ai.uid;
ai = mContext.getPackageManager().getApplicationInfo(TEST_PACKAGE3_NAME, 0);
mTestPackage3Uid = ai.uid;
+ final String activityManagerConstants = Settings.Global.ACTIVITY_MANAGER_CONSTANTS;
+ mAMConstantsSettings = new SettingsSession<>(
+ Settings.Global.getUriFor(activityManagerConstants),
+ Settings.Global::getString, Settings.Global::putString);
+ mAMConstantsSettings.set(
+ ActivityManagerConstants.KEY_SERVICE_RESTART_DURATION_FACTOR + "="
+ + SERVICE_RESTART_DURATION_FACTOR + ","
+ + ActivityManagerConstants.KEY_BOUND_SERVICE_CRASH_RESTART_DURATION + "="
+ + BOUND_SERVICE_CRASH_RESTART_DURATION + ","
+ + ActivityManagerConstants.KEY_SERVICE_MIN_RESTART_TIME_BETWEEN + "="
+ + SERVICE_MIN_RESTART_TIME_BETWEEN);
+ mExtraDelaysDeviceConfig = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ActivityManagerConstants.KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
+ DeviceConfig::getString, null);
+ mExtraDelaysDeviceConfig.set(EXTRA_DELAY);
+ mEnableExtraDelaysDeviceConfig = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ActivityManagerConstants.KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
+ DeviceConfig::getBoolean, false);
+ mEnableExtraDelaysDeviceConfig.set(true);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mAMConstantsSettings != null) {
+ mAMConstantsSettings.close();
+ }
+ if (mExtraDelaysDeviceConfig != null) {
+ mExtraDelaysDeviceConfig.close();
+ }
+ if (mEnableExtraDelaysDeviceConfig != null) {
+ mEnableExtraDelaysDeviceConfig.close();
+ }
}
@LargeTest
@@ -113,7 +165,7 @@ public final class ServiceRestarterTest {
// Test restarts in normal case
final long[] ts1 = startKillAndRestart(am, ACTION_START | ACTION_KILL | ACTION_WAIT,
uid1Listener1, uid1Listener2, uid2Listener1, uid2Listener2,
- uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ uid3Listener1, uid3Listener2, Long.MAX_VALUE, false);
assertTrue("app1 restart should be before app2", ts1[1] < ts1[2]);
assertTrue("app2 restart should be before app3", ts1[2] < ts1[3]);
@@ -122,7 +174,7 @@ public final class ServiceRestarterTest {
// Test restarts again.
final long[] ts2 = startKillAndRestart(am, ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG,
uid1Listener1, uid1Listener2, uid2Listener1,
- uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE, false);
assertTrue("app2 restart should be before app1", ts2[2] < ts2[1]);
assertTrue("app1 restart should be before app3", ts2[1] < ts2[3]);
assertTrue("app2 should be restart in a very short moment", ts2[2] - ts2[0] < WAIT_MS);
@@ -131,7 +183,8 @@ public final class ServiceRestarterTest {
executeShellCmd("am service-restart-backoff enable " + TEST_PACKAGE2_NAME);
// Test restarts again.
final long[] ts3 = startKillAndRestart(am, ACTION_ALL, uid1Listener1, uid1Listener2,
- uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE);
+ uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, Long.MAX_VALUE,
+ false);
assertTrue("app1 restart should be before app2", ts3[1] < ts3[2]);
assertTrue("app2 restart should be before app3", ts3[2] < ts3[3]);
@@ -152,11 +205,101 @@ public final class ServiceRestarterTest {
}
}
+ @LargeTest
+ @Test
+ public void testExtraDelaysInServiceRestartOnLowMem() throws Exception {
+ final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ final MyUidImportanceListener uid1Listener1 = new MyUidImportanceListener(mTestPackage1Uid);
+ final MyUidImportanceListener uid1Listener2 = new MyUidImportanceListener(mTestPackage1Uid);
+ final MyUidImportanceListener uid2Listener1 = new MyUidImportanceListener(mTestPackage2Uid);
+ final MyUidImportanceListener uid2Listener2 = new MyUidImportanceListener(mTestPackage2Uid);
+ final MyUidImportanceListener uid3Listener1 = new MyUidImportanceListener(mTestPackage3Uid);
+ final MyUidImportanceListener uid3Listener2 = new MyUidImportanceListener(mTestPackage3Uid);
+ try {
+ am.addOnUidImportanceListener(uid1Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid1Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid2Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid2Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ am.addOnUidImportanceListener(uid3Listener1, RunningAppProcessInfo.IMPORTANCE_SERVICE);
+ am.addOnUidImportanceListener(uid3Listener2, RunningAppProcessInfo.IMPORTANCE_GONE);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE1_NAME);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE2_NAME);
+ executeShellCmd("cmd deviceidle whitelist +" + TEST_PACKAGE3_NAME);
+
+ // Force the memory pressure to normal.
+ setMemoryPressure(ADJ_MEM_FACTOR_NORMAL);
+
+ // Test restarts in normal condition.
+ final long[] ts1 = startKillAndRestart(am, ACTION_ALL, uid1Listener1, uid1Listener2,
+ uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, WAIT_LONG_MS, true);
+
+ // Mimic a memory pressure event.
+ setMemoryPressure(ADJ_MEM_FACTOR_MODERATE);
+
+ final long[] ts2 = startKillAndRestart(am, ACTION_ALL, uid1Listener1, uid1Listener2,
+ uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, WAIT_LONG_MS, true);
+
+ assertTrue("Expect extra delays in service restarts",
+ (ts2[1] - ts2[0]) > (ts1[1] - ts1[0]));
+ assertTrue("Expect extra delays in service restarts",
+ (ts2[2] - ts2[0]) > (ts1[2] - ts1[0]));
+ assertTrue("Expect extra delays in service restarts",
+ (ts2[3] - ts2[0]) > (ts1[3] - ts1[0]));
+
+ // Increase the memory pressure event.
+ setMemoryPressure(ADJ_MEM_FACTOR_LOW);
+
+ final long[] ts3 = startKillAndRestart(am, ACTION_ALL, uid1Listener1, uid1Listener2,
+ uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2, WAIT_LONG_MS, true);
+
+ assertTrue("Expect extra delays in service restarts",
+ (ts3[1] - ts3[0]) > (ts2[1] - ts2[0]));
+ assertTrue("Expect extra delays in service restarts",
+ (ts3[2] - ts3[0]) > (ts2[2] - ts2[0]));
+ assertTrue("Expect extra delays in service restarts",
+ (ts3[3] - ts3[0]) > (ts2[3] - ts2[0]));
+
+ // Start and kill them again, but don't wait for the restart.
+ final long now4 = startKillAndRestart(am, ACTION_START | ACTION_KILL, uid1Listener1,
+ uid1Listener2, uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2,
+ WAIT_LONG_MS, true)[0];
+
+ // Set the memory pressure to normal.
+ setMemoryPressure(ADJ_MEM_FACTOR_NORMAL);
+
+ // Now wait for the restarts.
+ final long[] ts4 = startKillAndRestart(am, ACTION_WAIT | ACTION_STOPPKG, uid1Listener1,
+ uid1Listener2, uid2Listener1, uid2Listener2, uid3Listener1, uid3Listener2,
+ WAIT_LONG_MS, true);
+
+ assertTrue("Expect less delays in service restarts",
+ (ts4[1] - now4) < (ts2[1] - ts2[0]));
+ assertTrue("Expect less delays in service restarts",
+ (ts4[2] - now4) < (ts2[2] - ts2[0]));
+ assertTrue("Expect less delays in service restarts",
+ (ts4[3] - now4) < (ts2[3] - ts2[0]));
+ } finally {
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE1_NAME);
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE2_NAME);
+ executeShellCmd("cmd deviceidle whitelist -" + TEST_PACKAGE3_NAME);
+ resetMemoryPressure();
+ am.removeOnUidImportanceListener(uid1Listener1);
+ am.removeOnUidImportanceListener(uid1Listener2);
+ am.removeOnUidImportanceListener(uid2Listener1);
+ am.removeOnUidImportanceListener(uid2Listener2);
+ am.removeOnUidImportanceListener(uid3Listener1);
+ am.removeOnUidImportanceListener(uid3Listener2);
+ am.forceStopPackage(TEST_PACKAGE1_NAME);
+ am.forceStopPackage(TEST_PACKAGE2_NAME);
+ am.forceStopPackage(TEST_PACKAGE3_NAME);
+ }
+ }
+
private long[] startKillAndRestart(ActivityManager am, int action,
MyUidImportanceListener uid1Listener1, MyUidImportanceListener uid1Listener2,
MyUidImportanceListener uid2Listener1, MyUidImportanceListener uid2Listener2,
MyUidImportanceListener uid3Listener1, MyUidImportanceListener uid3Listener2,
- long waitDuration) throws Exception {
+ long waitDuration, boolean checkStartSeq) throws Exception {
final long[] res = new long[4];
// Test restarts in normal condition.
if ((action & ACTION_START) != 0) {
@@ -179,9 +322,15 @@ public final class ServiceRestarterTest {
RunningAppProcessInfo.IMPORTANCE_SERVICE, waitDuration));
assertTrue("Timed out to restart " + TEST_PACKAGE3_NAME, uid3Listener1.waitFor(
RunningAppProcessInfo.IMPORTANCE_SERVICE, waitDuration));
- res[1] = uid1Listener1.mCurrentTimestamp;
- res[2] = uid2Listener1.mCurrentTimestamp;
- res[3] = uid3Listener1.mCurrentTimestamp;
+ final long uid1RestartTime = res[1] = uid1Listener1.mCurrentTimestamp;
+ final long uid2RestartTime = res[2] = uid2Listener1.mCurrentTimestamp;
+ final long uid3RestartTime = res[3] = uid3Listener1.mCurrentTimestamp;
+ if (checkStartSeq) {
+ assertTrue(TEST_PACKAGE1_NAME + " should restart before " + TEST_PACKAGE2_NAME,
+ uid1RestartTime <= uid2RestartTime);
+ assertTrue(TEST_PACKAGE2_NAME + " should restart before " + TEST_PACKAGE3_NAME,
+ uid2RestartTime <= uid3RestartTime);
+ }
}
if ((action & ACTION_STOPPKG) != 0) {
@@ -224,6 +373,14 @@ public final class ServiceRestarterTest {
return result;
}
+ private void setMemoryPressure(int pressure) throws Exception {
+ executeShellCmd("am memory-factor set " + MEMORY_PRESSURE_MAP[pressure]);
+ }
+
+ private void resetMemoryPressure() throws Exception {
+ executeShellCmd("am memory-factor reset");
+ }
+
private static class MyUidImportanceListener implements OnUidImportanceListener {
final CountDownLatch[] mLatchHolder = new CountDownLatch[1];
private final int mExpectedUid;
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
index c12eb32a9143..e98a4dded99b 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
@@ -64,12 +64,16 @@ public class AppOpsStartedWatcherTest {
.times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
- eq(AppOpsManager.MODE_ALLOWED));
+ eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
+ eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
+ eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
- eq(AppOpsManager.MODE_ALLOWED));
+ eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
+ eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
+ eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
// Stop watching
appOpsManager.stopWatchingStarted(listener);
@@ -94,7 +98,9 @@ public class AppOpsStartedWatcherTest {
.times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
- eq(AppOpsManager.MODE_ALLOWED));
+ eq(AppOpsManager.MODE_ALLOWED), eq(OnOpStartedListener.START_TYPE_STARTED),
+ eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
+ eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
verifyNoMoreInteractions(listener);
// Finish up
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 8592166aae15..f4d14995f7c7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -378,6 +378,11 @@ public class BiometricSchedulerTest {
protected void handleLifecycleAfterAuth(boolean authenticated) {
}
+
+ @Override
+ public boolean wasUserDetected() {
+ return false;
+ }
}
private static class TestAuthenticationClient extends AuthenticationClient<Object> {
@@ -407,6 +412,11 @@ public class BiometricSchedulerTest {
protected void handleLifecycleAfterAuth(boolean authenticated) {
}
+
+ @Override
+ public boolean wasUserDetected() {
+ return false;
+ }
}
private static class TestClientMonitor2 extends TestClientMonitor {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
index 7f5f3c2df077..bfb0be760f85 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.content.Context;
+import android.hardware.biometrics.BiometricConstants;
import android.os.Handler;
import android.os.Looper;
import android.platform.test.annotations.Presubmit;
@@ -61,6 +62,8 @@ public class CoexCoordinatorTest {
private Context mContext;
@Mock
private CoexCoordinator.Callback mCallback;
+ @Mock
+ private CoexCoordinator.ErrorCallback mErrorCallback;
@Before
public void setUp() {
@@ -255,13 +258,16 @@ public class CoexCoordinatorTest {
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+ // For easier reading
+ final CoexCoordinator.Callback faceCallback = mCallback;
+
mCoexCoordinator.onAuthenticationSucceeded(0 /* currentTimeMillis */, faceClient,
- mCallback);
- verify(mCallback, never()).sendHapticFeedback();
- verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+ faceCallback);
+ verify(faceCallback, never()).sendHapticFeedback();
+ verify(faceCallback, never()).sendAuthenticationResult(anyBoolean());
// CoexCoordinator requests the system to hold onto this AuthenticationClient until
// UDFPS result is known
- verify(mCallback, never()).handleLifecycleAfterAuth();
+ verify(faceCallback, never()).handleLifecycleAfterAuth();
// Reset the mock
CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
@@ -274,6 +280,8 @@ public class CoexCoordinatorTest {
verify(udfpsCallback).sendAuthenticationResult(true /* addAuthTokenIfStrong */);
verify(udfpsCallback).handleLifecycleAfterAuth();
+ verify(faceCallback).sendAuthenticationCanceled();
+
assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
} else {
mCoexCoordinator.onAuthenticationRejected(udfpsRejectedAfterMs, udfpsClient,
@@ -281,16 +289,16 @@ public class CoexCoordinatorTest {
if (udfpsRejectedAfterMs <= CoexCoordinator.SUCCESSFUL_AUTH_VALID_DURATION_MS) {
verify(udfpsCallback, never()).sendHapticFeedback();
- verify(mCallback).sendHapticFeedback();
- verify(mCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
- verify(mCallback).handleLifecycleAfterAuth();
+ verify(faceCallback).sendHapticFeedback();
+ verify(faceCallback).sendAuthenticationResult(eq(true) /* addAuthTokenIfStrong */);
+ verify(faceCallback).handleLifecycleAfterAuth();
assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
} else {
assertTrue(mCoexCoordinator.mSuccessfulAuths.isEmpty());
- verify(mCallback, never()).sendHapticFeedback();
- verify(mCallback, never()).sendAuthenticationResult(anyBoolean());
+ verify(faceCallback, never()).sendHapticFeedback();
+ verify(faceCallback, never()).sendAuthenticationResult(anyBoolean());
verify(udfpsCallback).sendHapticFeedback();
verify(udfpsCallback)
@@ -485,4 +493,82 @@ public class CoexCoordinatorTest {
verify(callback).handleLifecycleAfterAuth();
verify(successfulAuths).remove(eq(auth));
}
+
+ @Test
+ public void testBiometricPrompt_FaceError() {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> client = mock(AuthenticationClient.class);
+ when(client.isBiometricPrompt()).thenReturn(true);
+ when(client.wasAuthAttempted()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationError(client, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
+ mErrorCallback);
+ verify(mErrorCallback).sendHapticFeedback();
+ }
+
+ @Test
+ public void testKeyguard_faceAuthOnly_errorWhenBypassEnabled() {
+ testKeyguard_faceAuthOnly(true /* bypassEnabled */);
+ }
+
+ @Test
+ public void testKeyguard_faceAuthOnly_errorWhenBypassDisabled() {
+ testKeyguard_faceAuthOnly(false /* bypassEnabled */);
+ }
+
+ private void testKeyguard_faceAuthOnly(boolean bypassEnabled) {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> client = mock(AuthenticationClient.class);
+ when(client.isKeyguard()).thenReturn(true);
+ when(client.isKeyguardBypassEnabled()).thenReturn(bypassEnabled);
+ when(client.wasAuthAttempted()).thenReturn(true);
+ when(client.wasUserDetected()).thenReturn(true);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, client);
+
+ mCoexCoordinator.onAuthenticationError(client, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
+ mErrorCallback);
+ verify(mErrorCallback).sendHapticFeedback();
+ }
+
+ @Test
+ public void testKeyguard_coex_faceErrorWhenBypassEnabled() {
+ testKeyguard_coex_faceError(true /* bypassEnabled */);
+ }
+
+ @Test
+ public void testKeyguard_coex_faceErrorWhenBypassDisabled() {
+ testKeyguard_coex_faceError(false /* bypassEnabled */);
+ }
+
+ private void testKeyguard_coex_faceError(boolean bypassEnabled) {
+ mCoexCoordinator.reset();
+
+ AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
+ when(faceClient.isKeyguard()).thenReturn(true);
+ when(faceClient.isKeyguardBypassEnabled()).thenReturn(bypassEnabled);
+ when(faceClient.wasAuthAttempted()).thenReturn(true);
+ when(faceClient.wasUserDetected()).thenReturn(true);
+
+ AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
+ withSettings().extraInterfaces(Udfps.class));
+ when(udfpsClient.isKeyguard()).thenReturn(true);
+ when(((Udfps) udfpsClient).isPointerDown()).thenReturn(false);
+
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
+ mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
+
+ mCoexCoordinator.onAuthenticationError(faceClient,
+ BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, mErrorCallback);
+
+ if (bypassEnabled) {
+ verify(mErrorCallback).sendHapticFeedback();
+ } else {
+ verify(mErrorCallback, never()).sendHapticFeedback();
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 5ba375b922e2..d22ed7eb970c 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -67,6 +67,8 @@ import com.android.server.lights.LightsManager;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import com.google.common.collect.ImmutableMap;
+
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -82,6 +84,7 @@ import org.mockito.MockitoAnnotations;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.LongStream;
@@ -223,7 +226,8 @@ public class DisplayManagerServiceTest {
break;
}
case DisplayViewport.VIEWPORT_EXTERNAL: {
- fail("EXTERNAL viewport should not exist.");
+ // External view port is present for auto devices in the form of instrument
+ // cluster.
break;
}
case DisplayViewport.VIEWPORT_VIRTUAL: {
@@ -259,9 +263,14 @@ public class DisplayManagerServiceTest {
final int displayIds[] = bs.getDisplayIds();
final int size = displayIds.length;
assertTrue(size > 0);
+
+ Map<Integer, Integer> expectedDisplayTypeToViewPortTypeMapping = ImmutableMap.of(
+ Display.TYPE_INTERNAL, DisplayViewport.VIEWPORT_INTERNAL,
+ Display.TYPE_EXTERNAL, DisplayViewport.VIEWPORT_EXTERNAL
+ );
for (int i = 0; i < size; i++) {
DisplayInfo info = bs.getDisplayInfo(displayIds[i]);
- assertEquals(info.type, Display.TYPE_INTERNAL);
+ assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
}
displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
@@ -281,13 +290,13 @@ public class DisplayManagerServiceTest {
// Now verify that each viewport's displayId is valid.
Arrays.sort(displayIds);
for (int i = 0; i < viewportSize; i++) {
- DisplayViewport internalViewport = viewports.get(i);
-
- // INTERNAL is the only one actual display.
- assertNotNull(internalViewport);
- assertEquals(DisplayViewport.VIEWPORT_INTERNAL, internalViewport.type);
- assertTrue(internalViewport.valid);
- assertTrue(Arrays.binarySearch(displayIds, internalViewport.displayId) >= 0);
+ DisplayViewport viewport = viewports.get(i);
+ assertNotNull(viewport);
+ DisplayInfo displayInfo = bs.getDisplayInfo(viewport.displayId);
+ assertTrue(expectedDisplayTypeToViewPortTypeMapping.get(displayInfo.type)
+ == viewport.type);
+ assertTrue(viewport.valid);
+ assertTrue(Arrays.binarySearch(displayIds, viewport.displayId) >= 0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index a205a1d167fe..1ac28abb4c2f 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -1340,11 +1340,19 @@ public class DisplayModeDirectorTest {
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
director.start(createMockSensorManager());
- ArgumentCaptor<ProximityActiveListener> captor =
+ ArgumentCaptor<ProximityActiveListener> ProximityCaptor =
ArgumentCaptor.forClass(ProximityActiveListener.class);
verify(mSensorManagerInternalMock).addProximityActiveListener(any(Executor.class),
- captor.capture());
- ProximityActiveListener listener = captor.getValue();
+ ProximityCaptor.capture());
+ ProximityActiveListener proximityListener = ProximityCaptor.getValue();
+
+ ArgumentCaptor<DisplayListener> DisplayCaptor =
+ ArgumentCaptor.forClass(DisplayListener.class);
+ verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+ eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
+ | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+ DisplayListener displayListener = DisplayCaptor.getValue();
// Verify that there is no proximity vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -1353,13 +1361,38 @@ public class DisplayModeDirectorTest {
when(mDisplayManagerInternalMock.getRefreshRateForDisplayAndSensor(eq(DISPLAY_ID), eq(null),
eq(Sensor.STRING_TYPE_PROXIMITY))).thenReturn(new RefreshRateRange(60, 60));
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+
// Set the proximity to active and verify that we added a vote.
- listener.onProximityActive(true);
+ proximityListener.onProximityActive(true);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertVoteForRefreshRate(vote, 60.f);
+
+ // Set the display state to doze and verify that the vote is gone
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+ displayListener.onDisplayAdded(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+
+ // Set the display state to on and verify that we added the vote back.
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
+ displayListener.onDisplayChanged(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertVoteForRefreshRate(vote, 60.f);
+
+ // Set the display state to doze and verify that the vote is gone
+ when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
+ displayListener.onDisplayAdded(DISPLAY_ID);
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
+ assertNull(vote);
+
+ // Remove the display to cause the doze state to be removed
+ displayListener.onDisplayRemoved(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
assertVoteForRefreshRate(vote, 60.f);
// Turn prox off and verify vote is gone.
- listener.onProximityActive(false);
+ proximityListener.onProximityActive(false);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
assertNull(vote);
}
@@ -1710,6 +1743,11 @@ public class DisplayModeDirectorTest {
return null;
}
+ @Override
+ public boolean isDozeState(Display d) {
+ return false;
+ }
+
void notifyPeakRefreshRateChanged() {
if (mPeakRefreshRateObserver != null) {
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index a0fcd833e024..35c7e5d59844 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -29,7 +29,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -539,69 +538,4 @@ public class HdmiCecLocalDeviceTvTest {
verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt());
}
-
- @Test
- public void handleReportAudioStatus_SamOnArcOn_setStreamVolumeCalled() {
- mNativeWrapper.setPortConnectionStatus(2, true);
- HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
- ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
- mNativeWrapper.onCecMessage(hdmiCecMessage);
-
- HdmiCecFeatureAction systemAudioAutoInitiationAction =
- new SystemAudioAutoInitiationAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM);
- mHdmiCecLocalDeviceTv.addAndStartAction(systemAudioAutoInitiationAction);
-
- HdmiCecMessage reportSystemAudioMode =
- HdmiCecMessageBuilder.buildReportSystemAudioMode(
- ADDR_AUDIO_SYSTEM,
- mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
- true);
- mHdmiControlService.handleCecCommand(reportSystemAudioMode);
-
- HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
- ADDR_AUDIO_SYSTEM,
- ADDR_TV);
- mNativeWrapper.onCecMessage(requestArcInitiation);
-
- mTestLooper.dispatchAll();
-
- // SAM and ARC must be on
- assertTrue(mHdmiCecLocalDeviceTv.isSystemAudioActivated());
- assertTrue(mHdmiCecLocalDeviceTv.isArcEstablished());
-
- HdmiCecMessage reportAudioStatus = HdmiCecMessageBuilder.buildReportAudioStatus(
- ADDR_AUDIO_SYSTEM,
- ADDR_TV,
- 50, // Volume of incoming message does not affect HDMI-CEC logic
- false);
- mNativeWrapper.onCecMessage(reportAudioStatus);
-
- mTestLooper.dispatchAll();
-
- verify(mAudioManager, times(1)).setStreamVolume(anyInt(), anyInt(), anyInt());
- }
-
- @Test
- public void handleReportAudioStatus_SamOff_setStreamVolumeNotCalled() {
- // Emulate Audio device on port 0x1000 (does not support ARC)
- mNativeWrapper.setPortConnectionStatus(1, true);
- HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
- ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
- mNativeWrapper.onCecMessage(hdmiCecMessage);
-
- mTestLooper.dispatchAll();
-
- assertFalse(mHdmiCecLocalDeviceTv.isSystemAudioActivated());
-
- HdmiCecMessage reportAudioStatus = HdmiCecMessageBuilder.buildReportAudioStatus(
- ADDR_AUDIO_SYSTEM,
- ADDR_TV,
- 50, // Volume of incoming message does not affect HDMI-CEC logic
- false);
- mNativeWrapper.onCecMessage(reportAudioStatus);
-
- mTestLooper.dispatchAll();
-
- verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt());
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
new file mode 100644
index 000000000000..00e3bf13d136
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.hdmi.RequestSadAction.RequestSadCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public class RequestSadActionTest {
+
+ private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+ private static final ArrayList<Integer> CODECS_TO_QUERY_1 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_LPCM, Constants.AUDIO_CODEC_DD,
+ Constants.AUDIO_CODEC_MPEG1, Constants.AUDIO_CODEC_MP3));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_2 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_MPEG2, Constants.AUDIO_CODEC_AAC,
+ Constants.AUDIO_CODEC_DTS, Constants.AUDIO_CODEC_ATRAC));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_3 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_ONEBITAUDIO, Constants.AUDIO_CODEC_DDP,
+ Constants.AUDIO_CODEC_DTSHD, Constants.AUDIO_CODEC_TRUEHD));
+ private static final ArrayList<Integer> CODECS_TO_QUERY_4 = new ArrayList<Integer>(
+ Arrays.asList(Constants.AUDIO_CODEC_DST, Constants.AUDIO_CODEC_WMAPRO,
+ Constants.AUDIO_CODEC_MAX));
+
+ private HdmiControlService mHdmiControlService;
+ private HdmiCecController mHdmiCecController;
+ private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
+ private FakeNativeWrapper mNativeWrapper;
+ private Looper mMyLooper;
+ private TestLooper mTestLooper = new TestLooper();
+ private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ private List<byte[]> mSupportedSads;
+ private RequestSadCallback mCallback =
+ new RequestSadCallback() {
+ @Override
+ public void onRequestSadDone(
+ List<byte[]> supportedSads) {
+ mSupportedSads = supportedSads;
+ }
+ };
+ @Mock
+ private IPowerManager mIPowerManagerMock;
+ @Mock
+ private IThermalService mIThermalServiceMock;
+
+ private static byte[] concatenateSads(List<byte[]> sads) {
+ byte[] concatenatedSads = new byte[sads.size() * 3];
+ for (int i = 0; i < sads.size(); i++) {
+ for (int j = 0; j < 3; j++) {
+ concatenatedSads[3 * i + j] = sads.get(i)[j];
+ }
+ }
+ return concatenatedSads;
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = InstrumentationRegistry.getTargetContext();
+ mMyLooper = mTestLooper.getLooper();
+
+ mHdmiControlService =
+ new HdmiControlService(InstrumentationRegistry.getTargetContext(),
+ Collections.emptyList()) {
+ @Override
+ boolean isControlEnabled() {
+ return true;
+ }
+
+ @Override
+ void wakeUp() {
+ }
+
+ @Override
+ protected void writeStringSystemProperty(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ boolean isPowerStandbyOrTransient() {
+ return false;
+ }
+
+ @Override
+ protected PowerManager getPowerManager() {
+ return new PowerManager(context, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(mMyLooper));
+ }
+ };
+
+ mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
+ mHdmiCecLocalDeviceTv.init();
+ mHdmiControlService.setIoLooper(mMyLooper);
+ mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
+ mNativeWrapper = new FakeNativeWrapper();
+ mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+ mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+ mHdmiControlService.setCecController(mHdmiCecController);
+ mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+ mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+ mLocalDevices.add(mHdmiCecLocalDeviceTv);
+ mHdmiControlService.initService();
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mNativeWrapper.setPhysicalAddress(0x0000);
+ mTestLooper.dispatchAll();
+ mNativeWrapper.clearResultMessages();
+ }
+
+ @Test
+ public void noResponse_queryAgain_emptyResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void featureAbort_dontQueryAgain_emptyResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+ HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
+ Constants.ABORT_INVALID_OPERAND);
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(featureAbort);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void allSupported_completeResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18, 0x4A,
+ 0x02, 0x64, 0x5A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x05, 0x18, 0x4A,
+ 0x06, 0x64, 0x5A,
+ 0x07, 0x4B, 0x00,
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x09, 0x18, 0x4A,
+ 0x0A, 0x64, 0x5A,
+ 0x0B, 0x4B, 0x00,
+ 0x0C, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0D, 0x18, 0x4A,
+ 0x0E, 0x64, 0x5A,
+ 0x0F, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(15);
+ assertThat(Arrays.equals(sadsToRespond_1,
+ concatenateSads(mSupportedSads.subList(0, 4)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_2,
+ concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_3,
+ concatenateSads(mSupportedSads.subList(8, 12)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_4,
+ concatenateSads(mSupportedSads.subList(12, 15)))).isTrue();
+ }
+
+ @Test
+ public void subsetSupported_subsetResult() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18, 0x4A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x09, 0x18, 0x4A,
+ 0x0A, 0x64, 0x5A,
+ 0x0B, 0x4B, 0x00,
+ 0x0C, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0F, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(9);
+ assertThat(Arrays.equals(sadsToRespond_1,
+ concatenateSads(mSupportedSads.subList(0, 3)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_2,
+ concatenateSads(mSupportedSads.subList(3, 4)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_3,
+ concatenateSads(mSupportedSads.subList(4, 8)))).isTrue();
+ assertThat(Arrays.equals(sadsToRespond_4,
+ concatenateSads(mSupportedSads.subList(8, 9)))).isTrue();
+ }
+
+ @Test
+ public void invalidCodecs_emptyResults() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x20, 0x18, 0x4A,
+ 0x21, 0x64, 0x5A,
+ 0x22, 0x4B, 0x00,
+ 0x23, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x24, 0x18, 0x4A,
+ 0x25, 0x64, 0x5A,
+ 0x26, 0x4B, 0x00,
+ 0x27, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[]{
+ 0x28, 0x18, 0x4A,
+ 0x29, 0x64, 0x5A,
+ 0x2A, 0x4B, 0x00,
+ 0x2B, 0x20, 0x0A};
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x2C, 0x18, 0x4A,
+ 0x2D, 0x64, 0x5A,
+ 0x2E, 0x4B, 0x00};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void invalidMessageLength_queryAgain() {
+ RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
+ mCallback);
+ action.start();
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_1 = new byte[]{
+ 0x01, 0x18,
+ 0x02, 0x64, 0x5A,
+ 0x03, 0x4B, 0x00,
+ 0x04, 0x20, 0x0A};
+ HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_1);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response1);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected2 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_2.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_2 = new byte[]{
+ 0x05, 0x18, 0x4A,
+ 0x06, 0x64, 0x5A,
+ 0x07,
+ 0x08, 0x20, 0x0A};
+ HdmiCecMessage response2 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_2);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response2);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected2);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected3 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_3.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_3 = new byte[0];
+ HdmiCecMessage response3 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_3);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response3);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected3);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected4 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ Constants.ADDR_AUDIO_SYSTEM,
+ CODECS_TO_QUERY_4.stream().mapToInt(i -> i).toArray());
+ byte[] sadsToRespond_4 = new byte[]{
+ 0x0D, 0x18, 0x4A,
+ 0x0E, 0x64, 0x5A,
+ 0x0F, 0x4B};
+ HdmiCecMessage response4 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
+ Constants.ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(), sadsToRespond_4);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mNativeWrapper.clearResultMessages();
+ action.processCommand(response4);
+ mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected4);
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mSupportedSads.size()).isEqualTo(0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 8b8a7e631caf..2bda120afb9d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -40,6 +40,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -232,6 +233,21 @@ public class ApexManagerTest {
}
@Test
+ public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException {
+ doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any());
+
+ assertThrows(RuntimeException.class,
+ () -> mApexManager.getStagedApexInfos(testParamsWithChildren()));
+ }
+
+ @Test
+ public void testGetStagedApexInfos_returnsEmptyArrayOnError() throws RemoteException {
+ doThrow(ServiceSpecificException.class).when(mApexService).getStagedApexInfos(any());
+
+ assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0);
+ }
+
+ @Test
public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException {
doAnswer(invocation -> {
throw new Exception();
diff --git a/services/tests/servicestests/src/com/android/server/pm/OWNERS b/services/tests/servicestests/src/com/android/server/pm/OWNERS
index e15b5f57069c..2f51994a2b1a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/pm/OWNERS
@@ -1,3 +1,7 @@
include /services/core/java/com/android/server/pm/OWNERS
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+
+# apex support
+per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index e8c5fb3ecf5c..38b98ca7a9c5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -949,7 +949,7 @@ public class PackageParserTest {
.addConfigPreference(new ConfigurationInfo())
.addReqFeature(new FeatureInfo())
.addFeatureGroup(new FeatureGroupInfo())
- .setCompileSdkVersionCodename("foo23")
+ .setCompileSdkVersionCodeName("foo23")
.setCompileSdkVersion(100)
.setOverlayCategory("foo24")
.setOverlayIsStatic(true)
diff --git a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
index 65a97596cd73..4a253234b59e 100644
--- a/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
+++ b/services/tests/servicestests/src/com/android/server/tare/LedgerTest.java
@@ -19,19 +19,31 @@ package com.android.server.tare;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Clock;
+import java.time.ZoneOffset;
+
/** Test that the ledger records transactions correctly. */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LedgerTest {
+ @Before
+ public void setUp() {
+ TareUtils.sSystemClock = Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
+ }
+
@Test
public void testInitialState() {
final Ledger ledger = new Ledger();
@@ -72,4 +84,45 @@ public class LedgerTest {
assertEquals(1, ledger.get24HourSum(1, 27 * HOUR_IN_MILLIS));
assertEquals(0, ledger.get24HourSum(1, 28 * HOUR_IN_MILLIS));
}
+
+ @Test
+ public void testRemoveOldTransactions() {
+ final Ledger ledger = new Ledger();
+ ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+ assertNull(ledger.getEarliestTransaction());
+
+ final long now = getCurrentTimeMillis();
+ Ledger.Transaction transaction1 = new Ledger.Transaction(
+ now - 48 * HOUR_IN_MILLIS, now - 40 * HOUR_IN_MILLIS, 1, null, 4800);
+ Ledger.Transaction transaction2 = new Ledger.Transaction(
+ now - 24 * HOUR_IN_MILLIS, now - 23 * HOUR_IN_MILLIS, 1, null, 600);
+ Ledger.Transaction transaction3 = new Ledger.Transaction(
+ now - 22 * HOUR_IN_MILLIS, now - 21 * HOUR_IN_MILLIS, 1, null, 600);
+ // Instant event
+ Ledger.Transaction transaction4 = new Ledger.Transaction(
+ now - 20 * HOUR_IN_MILLIS, now - 20 * HOUR_IN_MILLIS, 1, null, 500);
+ // Recent event
+ Ledger.Transaction transaction5 = new Ledger.Transaction(
+ now - 5 * MINUTE_IN_MILLIS, now - MINUTE_IN_MILLIS, 1, null, 400);
+ ledger.recordTransaction(transaction1);
+ ledger.recordTransaction(transaction2);
+ ledger.recordTransaction(transaction3);
+ ledger.recordTransaction(transaction4);
+ ledger.recordTransaction(transaction5);
+
+ assertEquals(transaction1, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(24 * HOUR_IN_MILLIS);
+ assertEquals(transaction2, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(23 * HOUR_IN_MILLIS);
+ assertEquals(transaction3, ledger.getEarliestTransaction());
+ // Shouldn't delete transaction3 yet since there's still a piece of it within the min age
+ // window.
+ ledger.removeOldTransactions(21 * HOUR_IN_MILLIS + 30 * MINUTE_IN_MILLIS);
+ assertEquals(transaction3, ledger.getEarliestTransaction());
+ // Instant event should be removed as soon as we hit the exact threshold.
+ ledger.removeOldTransactions(20 * HOUR_IN_MILLIS);
+ assertEquals(transaction5, ledger.getEarliestTransaction());
+ ledger.removeOldTransactions(0);
+ assertNull(ledger.getEarliestTransaction());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
index 2f36c7fb9044..b8cb1492ad52 100644
--- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
@@ -25,7 +25,6 @@ import android.content.ContextWrapper;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.media.tv.TvInputService;
-import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tuner.frontend.FrontendSettings;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
@@ -33,6 +32,7 @@ import android.media.tv.tunerresourcemanager.ResourceClientProfile;
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
+import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
diff --git a/services/tests/servicestests/src/com/android/server/uwb/OWNERS b/services/tests/servicestests/src/com/android/server/uwb/OWNERS
deleted file mode 100644
index c31a2f1ed3bc..000000000000
--- a/services/tests/servicestests/src/com/android/server/uwb/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/base:/core/java/android/uwb/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java b/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java
deleted file mode 100644
index 11554c7a7dc5..000000000000
--- a/services/tests/servicestests/src/com/android/server/uwb/UwbServiceImplTest.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2021 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.uwb;
-
-import static android.Manifest.permission.UWB_PRIVILEGED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.platform.test.annotations.Presubmit;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.uwb.IUwbAdapter;
-import android.uwb.IUwbAdapterStateCallbacks;
-import android.uwb.IUwbRangingCallbacks;
-import android.uwb.RangingReport;
-import android.uwb.RangingSession;
-import android.uwb.SessionHandle;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link UwbServiceImpl}.
- */
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-@Presubmit
-public class UwbServiceImplTest {
- private static final int UID = 343453;
- private static final String PACKAGE_NAME = "com.uwb.test";
- private static final AttributionSource ATTRIBUTION_SOURCE =
- new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();
-
- @Mock private IUwbAdapter mVendorService;
- @Mock private IBinder mVendorServiceBinder;
- @Mock private Context mContext;
- @Mock private UwbInjector mUwbInjector;
- @Captor private ArgumentCaptor<IUwbRangingCallbacks> mRangingCbCaptor;
- @Captor private ArgumentCaptor<IBinder.DeathRecipient> mClientDeathCaptor;
- @Captor private ArgumentCaptor<IBinder.DeathRecipient> mVendorServiceDeathCaptor;
-
- private UwbServiceImpl mUwbServiceImpl;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- when(mUwbInjector.getVendorService()).thenReturn(mVendorService);
- when(mUwbInjector.checkUwbRangingPermissionForDataDelivery(any(), any())).thenReturn(true);
- when(mVendorService.asBinder()).thenReturn(mVendorServiceBinder);
- mUwbServiceImpl = new UwbServiceImpl(mContext, mUwbInjector);
- }
-
- @Test
- public void testApiCallThrowsIllegalStateExceptionIfVendorServiceNotFound() throws Exception {
- when(mUwbInjector.getVendorService()).thenReturn(null);
-
- final IUwbAdapterStateCallbacks cb = mock(IUwbAdapterStateCallbacks.class);
- try {
- mUwbServiceImpl.registerAdapterStateCallbacks(cb);
- fail();
- } catch (IllegalStateException e) { /* pass */ }
- }
-
- @Test
- public void testRegisterAdapterStateCallbacks() throws Exception {
- final IUwbAdapterStateCallbacks cb = mock(IUwbAdapterStateCallbacks.class);
- mUwbServiceImpl.registerAdapterStateCallbacks(cb);
-
- verify(mVendorService).registerAdapterStateCallbacks(cb);
- }
-
- @Test
- public void testUnregisterAdapterStateCallbacks() throws Exception {
- final IUwbAdapterStateCallbacks cb = mock(IUwbAdapterStateCallbacks.class);
- mUwbServiceImpl.unregisterAdapterStateCallbacks(cb);
-
- verify(mVendorService).unregisterAdapterStateCallbacks(cb);
- }
-
- @Test
- public void testGetTimestampResolutionNanos() throws Exception {
- final long timestamp = 34L;
- when(mVendorService.getTimestampResolutionNanos()).thenReturn(timestamp);
- assertThat(mUwbServiceImpl.getTimestampResolutionNanos()).isEqualTo(timestamp);
-
- verify(mVendorService).getTimestampResolutionNanos();
- }
-
- @Test
- public void testGetSpecificationInfo() throws Exception {
- final PersistableBundle specification = new PersistableBundle();
- when(mVendorService.getSpecificationInfo()).thenReturn(specification);
- assertThat(mUwbServiceImpl.getSpecificationInfo()).isEqualTo(specification);
-
- verify(mVendorService).getSpecificationInfo();
- }
-
- @Test
- public void testOpenRanging() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
-
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
-
- verify(mVendorService).openRanging(
- eq(ATTRIBUTION_SOURCE), eq(sessionHandle), mRangingCbCaptor.capture(),
- eq(parameters));
- assertThat(mRangingCbCaptor.getValue()).isNotNull();
- }
-
- @Test
- public void testStartRanging() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final PersistableBundle parameters = new PersistableBundle();
-
- mUwbServiceImpl.startRanging(sessionHandle, parameters);
-
- verify(mVendorService).startRanging(sessionHandle, parameters);
- }
-
- @Test
- public void testReconfigureRanging() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final PersistableBundle parameters = new PersistableBundle();
-
- mUwbServiceImpl.reconfigureRanging(sessionHandle, parameters);
-
- verify(mVendorService).reconfigureRanging(sessionHandle, parameters);
- }
-
- @Test
- public void testStopRanging() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
-
- mUwbServiceImpl.stopRanging(sessionHandle);
-
- verify(mVendorService).stopRanging(sessionHandle);
- }
-
- @Test
- public void testCloseRanging() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
-
- mUwbServiceImpl.closeRanging(sessionHandle);
-
- verify(mVendorService).closeRanging(sessionHandle);
- }
-
- @Test
- public void testRangingCallbacks() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
-
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
-
- verify(mVendorService).openRanging(
- eq(ATTRIBUTION_SOURCE), eq(sessionHandle), mRangingCbCaptor.capture(),
- eq(parameters));
- assertThat(mRangingCbCaptor.getValue()).isNotNull();
-
- // Invoke vendor service callbacks and ensure that the corresponding app callback is
- // invoked.
- mRangingCbCaptor.getValue().onRangingOpened(sessionHandle);
- verify(cb).onRangingOpened(sessionHandle);
-
- mRangingCbCaptor.getValue().onRangingOpenFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingOpenFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
-
- mRangingCbCaptor.getValue().onRangingStarted(sessionHandle, parameters);
- verify(cb).onRangingStarted(sessionHandle, parameters);
-
- mRangingCbCaptor.getValue().onRangingStartFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingStartFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
-
- mRangingCbCaptor.getValue().onRangingReconfigured(sessionHandle, parameters);
- verify(cb).onRangingReconfigured(sessionHandle, parameters);
-
- mRangingCbCaptor.getValue().onRangingReconfigureFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingReconfigureFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
-
- mRangingCbCaptor.getValue().onRangingStopped(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingStopped(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
-
- mRangingCbCaptor.getValue().onRangingStopFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingStopFailed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
-
- final RangingReport rangingReport = new RangingReport.Builder().build();
- mRangingCbCaptor.getValue().onRangingResult(sessionHandle, rangingReport);
- verify(cb).onRangingResult(sessionHandle, rangingReport);
-
- mRangingCbCaptor.getValue().onRangingClosed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- verify(cb).onRangingClosed(
- sessionHandle, RangingSession.Callback.REASON_GENERIC_ERROR, parameters);
- }
-
- @Test
- public void testHandleClientDeath() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
-
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
-
- verify(mVendorService).openRanging(
- eq(ATTRIBUTION_SOURCE), eq(sessionHandle), mRangingCbCaptor.capture(),
- eq(parameters));
- assertThat(mRangingCbCaptor.getValue()).isNotNull();
-
- verify(cbBinder).linkToDeath(mClientDeathCaptor.capture(), anyInt());
- assertThat(mClientDeathCaptor.getValue()).isNotNull();
-
- clearInvocations(cb);
-
- // Invoke cb, ensure it reaches the client.
- mRangingCbCaptor.getValue().onRangingOpened(sessionHandle);
- verify(cb).onRangingOpened(sessionHandle);
-
- // Trigger client death and ensure the session is stopped.
- mClientDeathCaptor.getValue().binderDied();
- verify(mVendorService).stopRanging(sessionHandle);
- verify(mVendorService).closeRanging(sessionHandle);
-
- // Invoke cb, it should be ignored.
- mRangingCbCaptor.getValue().onRangingStarted(sessionHandle, parameters);
- verify(cb, never()).onRangingStarted(any(), any());
- }
-
- @Test
- public void testHandleVendorServiceDeath() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
-
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
-
- verify(mVendorServiceBinder).linkToDeath(mVendorServiceDeathCaptor.capture(), anyInt());
- assertThat(mVendorServiceDeathCaptor.getValue()).isNotNull();
-
- verify(mVendorService).openRanging(
- eq(ATTRIBUTION_SOURCE), eq(sessionHandle), mRangingCbCaptor.capture(),
- eq(parameters));
- assertThat(mRangingCbCaptor.getValue()).isNotNull();
-
- clearInvocations(cb);
-
- // Invoke cb, ensure it reaches the client.
- mRangingCbCaptor.getValue().onRangingOpened(sessionHandle);
- verify(cb).onRangingOpened(sessionHandle);
-
- // Trigger vendor service death and ensure that the client is informed of session end.
- mVendorServiceDeathCaptor.getValue().binderDied();
- verify(cb).onRangingClosed(
- eq(sessionHandle), eq(RangingSession.Callback.REASON_UNKNOWN),
- argThat((p) -> p.isEmpty()));
- }
-
- @Test
- public void testThrowSecurityExceptionWhenCalledWithoutUwbPrivilegedPermission()
- throws Exception {
- doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(UWB_PRIVILEGED), any());
- final IUwbAdapterStateCallbacks cb = mock(IUwbAdapterStateCallbacks.class);
- try {
- mUwbServiceImpl.registerAdapterStateCallbacks(cb);
- fail();
- } catch (SecurityException e) { /* pass */ }
- }
-
- @Test
- public void testThrowSecurityExceptionWhenOpenRangingCalledWithoutUwbRangingPermission()
- throws Exception {
- doThrow(new SecurityException()).when(mUwbInjector).enforceUwbRangingPermissionForPreflight(
- any());
-
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
- try {
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
- fail();
- } catch (SecurityException e) { /* pass */ }
- }
-
- @Test
- public void testOnRangingResultCallbackNotSentWithoutUwbRangingPermission() throws Exception {
- final SessionHandle sessionHandle = new SessionHandle(5);
- final IUwbRangingCallbacks cb = mock(IUwbRangingCallbacks.class);
- final PersistableBundle parameters = new PersistableBundle();
- final IBinder cbBinder = mock(IBinder.class);
- when(cb.asBinder()).thenReturn(cbBinder);
-
- mUwbServiceImpl.openRanging(ATTRIBUTION_SOURCE, sessionHandle, cb, parameters);
-
- verify(mVendorService).openRanging(
- eq(ATTRIBUTION_SOURCE), eq(sessionHandle), mRangingCbCaptor.capture(),
- eq(parameters));
- assertThat(mRangingCbCaptor.getValue()).isNotNull();
-
- when(mUwbInjector.checkUwbRangingPermissionForDataDelivery(any(), any())).thenReturn(false);
-
- // Ensure the ranging cb is not delivered to the client.
- final RangingReport rangingReport = new RangingReport.Builder().build();
- mRangingCbCaptor.getValue().onRangingResult(sessionHandle, rangingReport);
- verify(cb, never()).onRangingResult(sessionHandle, rangingReport);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 61b5c2b09bb2..4cc4d55f228d 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -83,7 +83,7 @@ import java.util.stream.Collectors;
@Presubmit
public class VibrationThreadTest {
- private static final int TEST_TIMEOUT_MILLIS = 1_000;
+ private static final int TEST_TIMEOUT_MILLIS = 900;
private static final int UID = Process.ROOT_UID;
private static final int VIBRATOR_ID = 1;
private static final String PACKAGE_NAME = "package";
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
index 4e981b22cd32..ae46f52ff70c 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
@@ -60,6 +60,9 @@ public class SimpleService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
+ if (intent == null) {
+ return START_STICKY;
+ }
int command = intent.getIntExtra(EXTRA_COMMAND, COMMAND_INVALID);
if (command != COMMAND_INVALID) {
final String targetPkg = intent.getStringExtra(EXTRA_TARGET_PACKAGE);
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
index 4b3771b95c05..f21991defbec 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -475,7 +475,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_failsForBogusPackageName() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0))
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
.thenReturn(TestInjector.CALLING_UID + 1);
assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder,
@@ -485,7 +485,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_failsIfNameNotFound() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0))
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder,
@@ -495,7 +495,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_failsIfNoProjectionTypes() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
assertThrows(IllegalArgumentException.class,
() -> mService.requestProjection(mBinder, PROJECTION_TYPE_NONE, PACKAGE_NAME));
@@ -507,7 +508,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_failsIfMultipleProjectionTypes() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
// Don't use PROJECTION_TYPE_ALL because that's actually == -1 and will fail the > 0 check.
int multipleProjectionTypes = PROJECTION_TYPE_AUTOMOTIVE | 0x0002 | 0x0004;
@@ -522,7 +524,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_enforcesToggleAutomotiveProjectionPermission() throws Exception {
- doThrow(new SecurityException()).when(mPackageManager).getPackageUid(PACKAGE_NAME, 0);
+ doThrow(new SecurityException())
+ .when(mPackageManager).getPackageUidAsUser(eq(PACKAGE_NAME), anyInt());
assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder,
PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME));
@@ -531,12 +534,14 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_automotive_failsIfAlreadySetByOtherPackage() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
String otherPackage = "Raconteurs";
- when(mPackageManager.getPackageUid(otherPackage, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(otherPackage), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, otherPackage));
assertThat(mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE),
contains(PACKAGE_NAME));
@@ -544,7 +549,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection_failsIfCannotLinkToDeath() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
doThrow(new RemoteException()).when(mBinder).linkToDeath(any(), anyInt());
assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME));
@@ -553,7 +559,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void requestProjection() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
// Should work for all powers of two.
for (int i = 0; i < Integer.SIZE; ++i) {
int projectionType = 1 << i;
@@ -568,11 +575,12 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void releaseProjection_failsForBogusPackageName() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0))
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
.thenReturn(TestInjector.CALLING_UID + 1);
assertThrows(SecurityException.class, () -> mService.releaseProjection(
@@ -582,10 +590,11 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void releaseProjection_failsIfNameNotFound() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0))
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
assertThrows(SecurityException.class, () -> mService.releaseProjection(
@@ -595,7 +604,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void releaseProjection_enforcesToggleAutomotiveProjectionPermission() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
@@ -613,7 +623,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void releaseProjection() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
requestAllPossibleProjectionTypes();
assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes());
@@ -632,7 +643,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void binderDeath_releasesProjection() throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
requestAllPossibleProjectionTypes();
assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes());
ArgumentCaptor<IBinder.DeathRecipient> deathRecipientCaptor = ArgumentCaptor.forClass(
@@ -647,7 +659,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void getActiveProjectionTypes() throws Exception {
assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes());
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
@@ -657,7 +670,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void getProjectingPackages() throws Exception {
assertTrue(mService.getProjectingPackages(PROJECTION_TYPE_ALL).isEmpty());
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE).size());
assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_ALL).size());
@@ -681,7 +695,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
@Test
public void addOnProjectionStateChangedListener_callsListenerIfProjectionActive()
throws Exception {
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
@@ -710,7 +725,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
mService.removeOnProjectionStateChangedListener(listener);
// Now set automotive projection, should not call back.
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
verify(listener, never()).onProjectionStateChanged(anyInt(), any());
}
@@ -726,7 +742,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
verifyNoMoreInteractions(listener);
// Now set automotive projection, should call back.
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_AUTOMOTIVE),
eq(List.of(PACKAGE_NAME)));
@@ -752,8 +769,9 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
int fakeProjectionType = 0x0002;
int otherFakeProjectionType = 0x0004;
String otherPackageName = "Internet Arms";
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
- when(mPackageManager.getPackageUid(otherPackageName, 0))
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(otherPackageName), anyInt()))
.thenReturn(TestInjector.CALLING_UID);
IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class);
when(listener.asBinder()).thenReturn(mBinder); // Any binder will do.
@@ -806,7 +824,8 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
// Now kill the binder for the listener. This should remove it from the list of listeners.
listenerDeathRecipient.getValue().binderDied();
- when(mPackageManager.getPackageUid(PACKAGE_NAME, 0)).thenReturn(TestInjector.CALLING_UID);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
+ .thenReturn(TestInjector.CALLING_UID);
mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
verify(listener, never()).onProjectionStateChanged(anyInt(), any());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index fa1f4aca8642..b282cd7ce1cb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -27,6 +27,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMor
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
@@ -70,6 +71,7 @@ import java.util.function.ToIntFunction;
@Presubmit
@RunWith(WindowTestRunner.class)
public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
+ private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5);
private ActivityMetricsLogger mActivityMetricsLogger;
private ActivityMetricsLogger.LaunchingState mLaunchingState;
private ActivityMetricsLaunchObserver mLaunchObserver;
@@ -137,7 +139,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
// messages that are waiting for the lock.
waitHandlerIdle(mAtm.mH);
// AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
- return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
+ return verify(mock, timeout(TIMEOUT_MS));
}
private void verifyOnActivityLaunchFinished(ActivityRecord activity) {
@@ -258,15 +260,40 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
@Test
public void testOnActivityLaunchWhileSleeping() {
- notifyActivityLaunching(mTopActivity.intent);
- notifyActivityLaunched(START_SUCCESS, mTopActivity);
- doReturn(true).when(mTopActivity.mDisplayContent).isSleeping();
- mTopActivity.setState(ActivityRecord.State.RESUMED, "test");
- mTopActivity.setVisibility(false);
+ notifyActivityLaunching(mTrampolineActivity.intent);
+ notifyActivityLaunched(START_SUCCESS, mTrampolineActivity);
+ doReturn(true).when(mTrampolineActivity.mDisplayContent).isSleeping();
+ mTrampolineActivity.setState(ActivityRecord.State.RESUMED, "test");
+ mTrampolineActivity.setVisibility(false);
waitHandlerIdle(mAtm.mH);
// Not cancel immediately because in one of real cases, the keyguard may be going away or
// occluded later, then the activity can be drawn.
- verify(mLaunchObserver, never()).onActivityLaunchCancelled(eqProto(mTopActivity));
+ verify(mLaunchObserver, never()).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
+
+ clearInvocations(mLaunchObserver);
+ mLaunchTopByTrampoline = true;
+ mTopActivity.mVisibleRequested = false;
+ notifyActivityLaunching(mTopActivity.intent);
+ // It should schedule a message with UNKNOWN_VISIBILITY_CHECK_DELAY_MS to check whether
+ // the launch event is still valid.
+ notifyActivityLaunched(START_SUCCESS, mTopActivity);
+
+ // The posted message will acquire wm lock, so the test needs to release the lock to verify.
+ final Throwable error = awaitInWmLock(() -> {
+ try {
+ // Though the aborting target should be eqProto(mTopActivity), use any() to avoid
+ // any changes in proto that may cause failure by different arguments.
+ verify(mLaunchObserver, timeout(TIMEOUT_MS)).onActivityLaunchCancelled(any());
+ } catch (Throwable e) {
+ // Catch any errors including assertion because this runs in another thread.
+ return e;
+ }
+ return null;
+ });
+ // The launch event must be cancelled because the activity keeps invisible.
+ if (error != null) {
+ throw new AssertionError(error);
+ }
}
@Test
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 41f2246858b4..9ca09d20cd49 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -147,6 +147,7 @@ import org.mockito.invocation.InvocationOnMock;
import java.util.ArrayList;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
/**
@@ -1603,16 +1604,23 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
- public void testRemoveImmediately() throws RemoteException {
- final ActivityRecord activity = createActivityWithTask();
- final WindowProcessController wpc = activity.app;
- activity.getTask().removeImmediately("test");
-
- verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
- isA(DestroyActivityItem.class));
- assertNull(activity.app);
- assertEquals(DESTROYED, activity.getState());
- assertFalse(wpc.hasActivities());
+ public void testRemoveImmediately() {
+ final Consumer<Consumer<ActivityRecord>> test = setup -> {
+ final ActivityRecord activity = createActivityWithTask();
+ final WindowProcessController wpc = activity.app;
+ setup.accept(activity);
+ activity.getTask().removeImmediately("test");
+ try {
+ verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
+ isA(DestroyActivityItem.class));
+ } catch (RemoteException ignored) {
+ }
+ assertNull(activity.app);
+ assertEquals(DESTROYED, activity.getState());
+ assertFalse(wpc.hasActivities());
+ };
+ test.accept(activity -> activity.setState(RESUMED, "test"));
+ test.accept(activity -> activity.finishing = true);
}
@Test
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 d086474aa03b..f3bb59c4598a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -67,6 +67,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
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.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
@@ -107,9 +108,12 @@ import android.app.WindowConfiguration;
import android.app.servertransaction.FixedRotationAdjustmentsItem;
import android.content.res.Configuration;
import android.graphics.Insets;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.metrics.LogMaker;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -142,6 +146,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.Arrays;
@@ -2220,6 +2226,113 @@ public class DisplayContentTests extends WindowTestsBase {
assertNotEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
}
+ @Test
+ public void testVirtualDisplayContent() {
+ MockitoSession mockSession = mockitoSession()
+ .initMocks(this)
+ .spyStatic(SurfaceControl.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+ // mirror.
+ final IBinder tokenToMirror = setUpDefaultTaskDisplayAreaWindowToken();
+
+ // GIVEN SurfaceControl can successfully mirror the provided surface.
+ Point surfaceSize = new Point(
+ mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
+ mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
+ surfaceControlMirrors(surfaceSize);
+
+ // WHEN creating the DisplayContent for a new virtual display.
+ final DisplayContent virtualDisplay = new TestDisplayContent.Builder(mAtm,
+ mDisplayInfo).build();
+
+ // THEN mirroring is initiated for the default display's DisplayArea.
+ assertThat(virtualDisplay.mTokenToMirror).isEqualTo(tokenToMirror);
+
+ mockSession.finishMocking();
+ }
+
+ @Test
+ public void testVirtualDisplayContent_capturedAreaResized() {
+ MockitoSession mockSession = mockitoSession()
+ .initMocks(this)
+ .spyStatic(SurfaceControl.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+ // mirror.
+ final IBinder tokenToMirror = setUpDefaultTaskDisplayAreaWindowToken();
+
+ // GIVEN SurfaceControl can successfully mirror the provided surface.
+ Point surfaceSize = new Point(
+ mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(),
+ mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height());
+ SurfaceControl mirroredSurface = surfaceControlMirrors(surfaceSize);
+
+ // WHEN creating the DisplayContent for a new virtual display.
+ final DisplayContent virtualDisplay = new TestDisplayContent.Builder(mAtm,
+ mDisplayInfo).build();
+
+ // THEN mirroring is initiated for the default display's DisplayArea.
+ assertThat(virtualDisplay.mTokenToMirror).isEqualTo(tokenToMirror);
+
+ float xScale = 0.7f;
+ float yScale = 2f;
+ Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale),
+ Math.round(surfaceSize.y * yScale));
+ virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds);
+
+ // THEN content in the captured DisplayArea is scaled to fit the surface size.
+ verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0,
+ 1.0f / yScale);
+ // THEN captured content is positioned in the centre of the output surface.
+ float scaledWidth = displayAreaBounds.width() / xScale;
+ float xInset = (surfaceSize.x - scaledWidth) / 2;
+ verify(mTransaction, atLeastOnce()).setPosition(mirroredSurface, xInset, 0);
+
+ mockSession.finishMocking();
+ }
+
+ private class TestToken extends Binder {
+ }
+
+ /**
+ * Creates a WindowToken associated with the default task DisplayArea, in order for that
+ * DisplayArea to be mirrored.
+ */
+ private IBinder setUpDefaultTaskDisplayAreaWindowToken() {
+ // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to
+ // mirror.
+ final IBinder tokenToMirror = new TestToken();
+ doReturn(tokenToMirror).when(mWm.mDisplayManagerInternal).getWindowTokenClientToMirror(
+ anyInt());
+
+ // GIVEN the default task display area is represented by the WindowToken.
+ spyOn(mWm.mWindowContextListenerController);
+ doReturn(mDefaultDisplay.getDefaultTaskDisplayArea()).when(
+ mWm.mWindowContextListenerController).getContainer(any());
+ return tokenToMirror;
+ }
+
+ /**
+ * SurfaceControl successfully creates a mirrored surface of the given size.
+ */
+ private SurfaceControl surfaceControlMirrors(Point surfaceSize) {
+ // Do not set the parent, since the mirrored surface is the root of a new surface hierarchy.
+ SurfaceControl mirroredSurface = new SurfaceControl.Builder()
+ .setName("mirroredSurface")
+ .setBufferSize(surfaceSize.x, surfaceSize.y)
+ .setCallsite("mirrorSurface")
+ .build();
+ doReturn(mirroredSurface).when(() -> SurfaceControl.mirrorSurface(any()));
+ doReturn(surfaceSize).when(mWm.mDisplayManagerInternal).getDisplaySurfaceDefaultSize(
+ anyInt());
+ return mirroredSurface;
+ }
+
private void removeRootTaskTests(Runnable runnable) {
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index e3c38b06ec88..1b078b7454b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -788,6 +788,19 @@ public class RecentTasksTest extends WindowTestsBase {
}
@Test
+ public void testVisibleEmbeddedTask_expectNotVisible() {
+ Task task = createTaskBuilder(".Task")
+ .setFlags(FLAG_ACTIVITY_NEW_TASK)
+ .build();
+ doReturn(true).when(task).isEmbedded();
+ mRecentTasks.add(task);
+
+ assertThat(mCallbacksRecorder.mAdded).hasSize(1);
+ assertFalse("embedded task should not be visible recents",
+ mRecentTasks.isVisibleRecentTask(task));
+ }
+
+ @Test
public void testFreezeTaskListOrder_reorderExistingTask() {
// Add some tasks
mRecentTasks.add(mTasks.get(0));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 6cc60ea3d51a..56d01cd34e01 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -191,7 +191,6 @@ public class RootTaskTests extends WindowTestsBase {
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
// Root task removal is deferred if one of its child is animating.
- doReturn(true).when(rootTask).hasWindowsAlive();
doReturn(rootTask).when(task).getAnimatingContainer(
eq(TRANSITION | CHILDREN), anyInt());
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 d10c006831d2..3bebf6b39de1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1986,6 +1986,61 @@ public class SizeCompatTests extends WindowTestsBase {
assertTrue(mActivity.areBoundsLetterboxed());
}
+ /**
+ * Tests that all three paths in which aspect ratio logic can be applied yield the same
+ * result, which is that aspect ratio is respected on app bounds. The three paths are
+ * fixed orientation, no fixed orientation but fixed aspect ratio, and size compat mode.
+ */
+ @Test
+ public void testAllAspectRatioLogicConsistent() {
+ // Create display that has all stable insets and does not rotate. Make sure that status bar
+ // height is greater than notch height so that stable bounds do not equal app bounds.
+ final int notchHeight = 75;
+ final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1080, 600)
+ .setSystemDecorations(true).setNotch(notchHeight)
+ .setStatusBarHeight(notchHeight + 20).setCanRotate(false).build();
+
+ // Create task on test display.
+ final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build();
+
+ // Target min aspect ratio must be larger than parent aspect ratio to be applied.
+ final float targetMinAspectRatio = 3.0f;
+
+ // Create fixed portait activity with min aspect ratio greater than parent aspect ratio.
+ final ActivityRecord fixedOrientationActivity = new ActivityBuilder(mAtm)
+ .setTask(task).setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setMinAspectRatio(targetMinAspectRatio).build();
+ final Rect fixedOrientationAppBounds = new Rect(fixedOrientationActivity.getConfiguration()
+ .windowConfiguration.getAppBounds());
+
+ // Create activity with no fixed orientation and min aspect ratio greater than parent aspect
+ // ratio.
+ final ActivityRecord minAspectRatioActivity = new ActivityBuilder(mAtm).setTask(task)
+ .setMinAspectRatio(targetMinAspectRatio).build();
+ final Rect minAspectRatioAppBounds = new Rect(minAspectRatioActivity.getConfiguration()
+ .windowConfiguration.getAppBounds());
+
+ // Create unresizeable fixed portait activity with min aspect ratio greater than parent
+ // aspect ratio.
+ final ActivityRecord sizeCompatActivity = new ActivityBuilder(mAtm)
+ .setTask(task).setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setMinAspectRatio(targetMinAspectRatio).build();
+ // Resize display running unresizeable activity to make it enter size compat mode.
+ resizeDisplay(display, 1800, 1000);
+ final Rect sizeCompatAppBounds = new Rect(sizeCompatActivity.getConfiguration()
+ .windowConfiguration.getAppBounds());
+
+ // Check that aspect ratio of app bounds is equal to the min aspect ratio.
+ final float delta = 0.01f;
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(fixedOrientationAppBounds), delta);
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(minAspectRatioAppBounds), delta);
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(sizeCompatAppBounds), delta);
+ }
+
private void assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
float letterboxHorizontalPositionMultiplier) {
// Set up a display in landscape and ignoring orientation request.
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 629e45208234..807494429999 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -126,8 +126,15 @@ public class TaskTests extends WindowTestsBase {
final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
- task.removeIfPossible();
- // Assert that the container was removed.
+ task.remove(false /* withTransition */, "testRemoveContainer");
+ // There is still an activity to be destroyed, so the task is not removed immediately.
+ assertNotNull(task.getParent());
+ assertTrue(rootTask.hasChild());
+ assertTrue(task.hasChild());
+ assertTrue(activity.finishing);
+
+ activity.destroyed("testRemoveContainer");
+ // Assert that the container was removed after the activity is destroyed.
assertNull(task.getParent());
assertEquals(0, task.getChildCount());
assertNull(activity.getParent());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index 0d919d109587..061a4c5fe261 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -78,6 +79,7 @@ class TestDisplayContent extends DisplayContent {
private int mPosition = POSITION_BOTTOM;
protected final ActivityTaskManagerService mService;
private boolean mSystemDecorations = false;
+ private int mStatusBarHeight = 0;
Builder(ActivityTaskManagerService service, int width, int height) {
mService = service;
@@ -126,6 +128,10 @@ class TestDisplayContent extends DisplayContent {
Insets.of(0, height, 0, 0), null, new Rect(20, 0, 80, height), null, null);
return this;
}
+ Builder setStatusBarHeight(int height) {
+ mStatusBarHeight = height;
+ return this;
+ }
Builder setCanRotate(boolean canRotate) {
mCanRotate = canRotate;
return this;
@@ -160,6 +166,14 @@ class TestDisplayContent extends DisplayContent {
doReturn(false).when(displayPolicy).hasStatusBar();
doReturn(false).when(newDisplay).supportsSystemDecorations();
}
+ if (mStatusBarHeight > 0) {
+ doReturn(true).when(displayPolicy).hasStatusBar();
+ doAnswer(invocation -> {
+ Rect inOutInsets = (Rect) invocation.getArgument(0);
+ inOutInsets.top = mStatusBarHeight;
+ return null;
+ }).when(displayPolicy).convertNonDecorInsetsToStableInsets(any(), anyInt());
+ }
Configuration c = new Configuration();
newDisplay.computeScreenConfiguration(c);
c.windowConfiguration.setWindowingMode(mWindowingMode);
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 39fe952cc199..9160109e7e7f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -81,6 +81,7 @@ import android.window.ITaskOrganizer;
import android.window.IWindowContainerTransactionCallback;
import android.window.StartingWindowInfo;
import android.window.TaskAppearedInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
@@ -1275,6 +1276,24 @@ public class WindowOrganizerTests extends WindowTestsBase {
assertTrue(optionsCaptor.getValue().getOriginalOptions().getTransientLaunch());
}
+ @Test
+ public void testResumeTopsWhenLeavingPinned() {
+ final ActivityRecord record = makePipableActivity();
+ final Task rootTask = record.getRootTask();
+
+ clearInvocations(mWm.mAtmService.mRootWindowContainer);
+ final WindowContainerTransaction t = new WindowContainerTransaction();
+ WindowContainerToken wct = rootTask.mRemoteToken.toWindowContainerToken();
+ t.setWindowingMode(wct, WINDOWING_MODE_PINNED);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
+ verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
+
+ clearInvocations(mWm.mAtmService.mRootWindowContainer);
+ t.setWindowingMode(wct, WINDOWING_MODE_FULLSCREEN);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
+ verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
+ }
+
/**
* Verifies that task vanished is called for a specific task.
*/
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 aa5618397f29..17288c21adc8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -53,9 +53,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
import static com.google.common.truth.Truth.assertThat;
@@ -895,36 +892,6 @@ public class WindowStateTests extends WindowTestsBase {
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
}
- @UseTestDisplay(addWindows = W_INPUT_METHOD)
- @Test
- public void testAdjustImeInsetsVisibilityWhenTaskSwitchIsAnimating() {
- final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
- final InsetsStateController controller = mDisplayContent.getInsetsStateController();
- controller.getImeSourceProvider().setWindow(mImeWindow, null, null);
-
- // Simulate app requests IME with updating all windows Insets State when IME is above app.
- mDisplayContent.setImeLayeringTarget(app);
- mDisplayContent.setImeInputTarget(app);
- assertTrue(mDisplayContent.shouldImeAttachedToApp());
- controller.getImeSourceProvider().scheduleShowImePostLayout(app);
- controller.getImeSourceProvider().getSource().setVisible(true);
- controller.updateAboveInsetsState(mImeWindow, false);
-
- // Simulate task switching animation happens when switching app to app2.
- spyOn(app);
- spyOn(app2);
- doReturn(true).when(app).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
- doReturn(true).when(app2).isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_RECENTS);
- app.mActivityRecord.mLastImeShown = true;
-
- // Verify the IME insets is visible on app, but not for app2 during task animating.
- InsetsState stateApp = app.getInsetsState();
- InsetsState stateApp2 = app2.getInsetsState();
- assertTrue(stateApp.getSource(ITYPE_IME).isVisible());
- assertFalse(stateApp2.getSource(ITYPE_IME).isVisible());
- }
-
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
index 5874b4b9fd3e..49ea9df5b26f 100644
--- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
@@ -25,12 +25,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager.Sensors;
+import android.hardware.SensorPrivacyManagerInternal;
import android.hardware.usb.AccessoryFilter;
import android.hardware.usb.DeviceFilter;
import android.hardware.usb.UsbAccessory;
-import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Binder;
@@ -52,9 +52,9 @@ import android.util.TypedXmlSerializer;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.LocalServices;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -64,7 +64,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
/**
* UsbUserPermissionManager manages usb device or accessory access permissions.
@@ -110,19 +109,20 @@ class UsbUserPermissionManager {
*/
@GuardedBy("mLock")
private boolean mIsCopyPermissionsScheduled;
+ private final SensorPrivacyManagerInternal mSensorPrivacyMgrInternal;
UsbUserPermissionManager(@NonNull Context context,
@NonNull UsbUserSettingsManager usbUserSettingsManager) {
mContext = context;
mUser = context.getUser();
mUsbUserSettingsManager = usbUserSettingsManager;
+ mSensorPrivacyMgrInternal = LocalServices.getService(SensorPrivacyManagerInternal.class);
mDisablePermissionDialogs = context.getResources().getBoolean(
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
mPermissionsFile = new AtomicFile(new File(
Environment.getUserSystemDirectory(mUser.getIdentifier()),
"usb_permissions.xml"), "usb-permissions");
-
synchronized (mLock) {
readPermissionsLocked();
}
@@ -195,11 +195,27 @@ class UsbUserPermissionManager {
*/
boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid,
int uid) {
- if (isCameraDevicePresent(device)) {
- if (!isCameraPermissionGranted(packageName, pid, uid)) {
+ if (device.getHasVideoCapture()) {
+ boolean isCameraPrivacyEnabled = mSensorPrivacyMgrInternal.isSensorPrivacyEnabled(
+ UserHandle.getUserId(uid), Sensors.CAMERA);
+ if (DEBUG) {
+ Slog.d(TAG, "isCameraPrivacyEnabled: " + isCameraPrivacyEnabled);
+ }
+ if (isCameraPrivacyEnabled || !isCameraPermissionGranted(packageName, pid, uid)) {
return false;
}
}
+ // Only check for microphone privacy and not RECORD_AUDIO permission, because access to usb
+ // camera device with audio recording capabilities may still be granted with a warning
+ if (device.getHasAudioCapture() && mSensorPrivacyMgrInternal.isSensorPrivacyEnabled(
+ UserHandle.getUserId(uid), Sensors.MICROPHONE)) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Access to device with audio recording capabilities denied because "
+ + "microphone privacy is enabled.");
+ }
+ return false;
+ }
synchronized (mLock) {
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
return true;
@@ -673,8 +689,10 @@ class UsbUserPermissionManager {
try {
ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
if (aInfo.uid != uid) {
- throw new IllegalArgumentException("package " + packageName
+ Slog.w(TAG, "package " + packageName
+ " does not match caller's uid " + uid);
+ throw new IllegalArgumentException("package " + packageName
+ + " not found");
}
} catch (PackageManager.NameNotFoundException e) {
throw new IllegalArgumentException("package " + packageName + " not found");
@@ -698,7 +716,10 @@ class UsbUserPermissionManager {
}
return;
}
- if (isCameraDevicePresent(device)) {
+ // If the app doesn't have camera permission do not request permission to the USB device.
+ // Note that if the USB camera also has a microphone, a warning will be shown to the user if
+ // the app doesn't have RECORD_AUDIO permission.
+ if (device.getHasVideoCapture()) {
if (!isCameraPermissionGranted(packageName, pid, uid)) {
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
@@ -733,27 +754,4 @@ class UsbUserPermissionManager {
requestPermissionDialog(null, accessory,
mUsbUserSettingsManager.canBeDefault(accessory, packageName), packageName, pi, uid);
}
-
- /**
- * Check whether a particular device or any of its interfaces
- * is of class VIDEO.
- *
- * @param device The device that needs to get scanned
- * @return True in case a VIDEO device or interface is present,
- * False otherwise.
- */
- private boolean isCameraDevicePresent(UsbDevice device) {
- if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) {
- return true;
- }
-
- for (int i = 0; i < device.getInterfaceCount(); i++) {
- UsbInterface iface = device.getInterface(i);
- if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_VIDEO) {
- return true;
- }
- }
-
- return false;
- }
}
diff --git a/services/uwb/Android.bp b/services/uwb/Android.bp
deleted file mode 100644
index da30d43a4536..000000000000
--- a/services/uwb/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "services.uwb-sources",
- srcs: ["java/**/*.java"],
- path: "java",
- visibility: ["//frameworks/base/services"],
-}
-
-java_library_static {
- name: "services.uwb",
- defaults: ["platform_service_defaults"],
- srcs: [
- ":services.uwb-sources",
- ],
- libs: [
- "services.core",
- ],
-}
diff --git a/services/uwb/OWNERS b/services/uwb/OWNERS
deleted file mode 100644
index c31a2f1ed3bc..000000000000
--- a/services/uwb/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/base:/core/java/android/uwb/OWNERS
diff --git a/services/uwb/java/com/android/server/uwb/UwbInjector.java b/services/uwb/java/com/android/server/uwb/UwbInjector.java
deleted file mode 100644
index 64f1da1c8e16..000000000000
--- a/services/uwb/java/com/android/server/uwb/UwbInjector.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2021 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.uwb;
-
-import static android.Manifest.permission.UWB_RANGING;
-import static android.content.PermissionChecker.PERMISSION_GRANTED;
-
-import android.annotation.NonNull;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.content.PermissionChecker;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.uwb.IUwbAdapter;
-
-
-/**
- * To be used for dependency injection (especially helps mocking static dependencies).
- */
-public class UwbInjector {
- private static final String TAG = "UwbInjector";
-
- private static final String VENDOR_SERVICE_NAME = "uwb_vendor";
-
- private final Context mContext;
-
- public UwbInjector(@NonNull Context context) {
- mContext = context;
- }
-
- /**
- * @return Returns the vendor service handle.
- */
- public IUwbAdapter getVendorService() {
- IBinder b = ServiceManager.getService(VENDOR_SERVICE_NAME);
- if (b == null) return null;
- return IUwbAdapter.Stub.asInterface(b);
- }
-
- /**
- * Throws security exception if the UWB_RANGING permission is not granted for the calling app.
- *
- * <p>Should be used in situations where the app op should not be noted.
- */
- public void enforceUwbRangingPermissionForPreflight(
- @NonNull AttributionSource attributionSource) {
- if (!attributionSource.checkCallingUid()) {
- throw new SecurityException("Invalid attribution source " + attributionSource);
- }
- int permissionCheckResult = PermissionChecker.checkPermissionForPreflight(
- mContext, UWB_RANGING, attributionSource);
- if (permissionCheckResult != PERMISSION_GRANTED) {
- throw new SecurityException("Caller does not hold UWB_RANGING permission");
- }
- }
-
- /**
- * Returns true if the UWB_RANGING permission is granted for the calling app.
- *
- * <p>Should be used in situations where data will be delivered and hence the app op should
- * be noted.
- */
- public boolean checkUwbRangingPermissionForDataDelivery(
- @NonNull AttributionSource attributionSource, @NonNull String message) {
- int permissionCheckResult = PermissionChecker.checkPermissionForDataDelivery(
- mContext, UWB_RANGING, -1, attributionSource, message);
- return permissionCheckResult == PERMISSION_GRANTED;
- }
-}
diff --git a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java b/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java
deleted file mode 100644
index 4dd26a66cf0e..000000000000
--- a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2021 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.uwb;
-
-import android.annotation.NonNull;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.uwb.IUwbAdapter;
-import android.uwb.IUwbAdapterStateCallbacks;
-import android.uwb.IUwbRangingCallbacks;
-import android.uwb.RangingReport;
-import android.uwb.RangingSession;
-import android.uwb.SessionHandle;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.Map;
-
-/**
- * Implementation of {@link android.uwb.IUwbAdapter} binder service.
- */
-public class UwbServiceImpl extends IUwbAdapter.Stub implements IBinder.DeathRecipient{
- private static final String TAG = "UwbServiceImpl";
-
- private final Context mContext;
- private final UwbInjector mUwbInjector;
- /**
- * Map for storing the callbacks wrapper for each session.
- */
- @GuardedBy("mCallbacksMap")
- private final Map<SessionHandle, UwbRangingCallbacksWrapper> mCallbacksMap = new ArrayMap<>();
-
- /**
- * Used for caching the vendor implementation of {@link IUwbAdapter} interface.
- */
- private IUwbAdapter mVendorUwbAdapter;
-
- /**
- * Wrapper for callback registered with vendor service. This wrapper is needed for performing
- * permission check before sending the callback to the external app.
- *
- * Access to these callbacks are synchronized.
- */
- private class UwbRangingCallbacksWrapper extends IUwbRangingCallbacks.Stub
- implements IBinder.DeathRecipient {
- private final AttributionSource mAttributionSource;
- private final SessionHandle mSessionHandle;
- private final IUwbRangingCallbacks mExternalCb;
- private boolean mIsValid;
-
- UwbRangingCallbacksWrapper(@NonNull AttributionSource attributionSource,
- @NonNull SessionHandle sessionHandle,
- @NonNull IUwbRangingCallbacks externalCb) {
- mAttributionSource = attributionSource;
- mSessionHandle = sessionHandle;
- mExternalCb = externalCb;
- mIsValid = true;
-
- // Link to death for external callback.
- linkToDeath();
- }
-
- private void linkToDeath() {
- IBinder binder = mExternalCb.asBinder();
- try {
- binder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to link to client death event.", e);
- }
- }
-
- private void removeClientAndUnlinkToDeath() {
- // Remove from the map.
- synchronized (mCallbacksMap) {
- mCallbacksMap.remove(mSessionHandle);
- }
- IBinder binder = mExternalCb.asBinder();
- binder.unlinkToDeath(this, 0);
- mIsValid = false;
- }
-
-
- @Override
- public synchronized void onRangingOpened(SessionHandle sessionHandle)
- throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingOpened(sessionHandle);
- }
-
- @Override
- public synchronized void onRangingOpenFailed(SessionHandle sessionHandle,
- int reason, PersistableBundle parameters) throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingOpenFailed(sessionHandle, reason, parameters);
- }
-
- @Override
- public synchronized void onRangingStarted(SessionHandle sessionHandle,
- PersistableBundle parameters)
- throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingStarted(sessionHandle, parameters);
- }
-
- @Override
- public synchronized void onRangingStartFailed(SessionHandle sessionHandle,
- int reason, PersistableBundle parameters) throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingStartFailed(sessionHandle, reason, parameters);
- }
-
- @Override
- public synchronized void onRangingReconfigured(SessionHandle sessionHandle,
- PersistableBundle parameters)
- throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingReconfigured(sessionHandle, parameters);
- }
-
- @Override
- public synchronized void onRangingReconfigureFailed(SessionHandle sessionHandle,
- int reason, PersistableBundle parameters) throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingReconfigureFailed(sessionHandle, reason, parameters);
- }
-
- @Override
- public synchronized void onRangingStopped(SessionHandle sessionHandle, int reason,
- PersistableBundle parameters)
- throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingStopped(sessionHandle, reason, parameters);
- }
-
- @Override
- public synchronized void onRangingStopFailed(SessionHandle sessionHandle, int reason,
- PersistableBundle parameters) throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingStopFailed(sessionHandle, reason, parameters);
- }
-
- @Override
- public synchronized void onRangingClosed(SessionHandle sessionHandle, int reason,
- PersistableBundle parameters) throws RemoteException {
- if (!mIsValid) return;
- mExternalCb.onRangingClosed(sessionHandle, reason, parameters);
- removeClientAndUnlinkToDeath();
- }
-
- @Override
- public synchronized void onRangingResult(SessionHandle sessionHandle,
- RangingReport rangingReport)
- throws RemoteException {
- if (!mIsValid) return;
- boolean permissionGranted = Binder.withCleanCallingIdentity(
- () -> mUwbInjector.checkUwbRangingPermissionForDataDelivery(
- mAttributionSource, "uwb ranging result"));
- if (!permissionGranted) {
- Log.e(TAG, "Not delivering ranging result because of permission denial"
- + mSessionHandle);
- return;
- }
- mExternalCb.onRangingResult(sessionHandle, rangingReport);
- }
-
- @Override
- public synchronized void binderDied() {
- if (!mIsValid) return;
- Log.i(TAG, "Client died: ending session: " + mSessionHandle);
- try {
- removeClientAndUnlinkToDeath();
- stopRanging(mSessionHandle);
- closeRanging(mSessionHandle);
- } catch (RemoteException e) {
- Log.e(TAG, "Remote exception while handling client death", e);
- }
- }
- }
-
- private void linkToVendorServiceDeath() {
- IBinder binder = mVendorUwbAdapter.asBinder();
- try {
- binder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to link to vendor service death event.", e);
- }
- }
-
- @Override
- public void binderDied() {
- Log.i(TAG, "Vendor service died: sending session close callbacks");
- synchronized (mCallbacksMap) {
- for (Map.Entry<SessionHandle, UwbRangingCallbacksWrapper> e : mCallbacksMap.entrySet()) {
- try {
- e.getValue().mExternalCb.onRangingClosed(
- e.getKey(), RangingSession.Callback.REASON_UNKNOWN,
- new PersistableBundle());
- } catch (RemoteException ex) {
- Log.e(TAG, "Failed to send session close callback " + e.getKey(), ex);
- }
- }
- // Clear all sessions.
- mCallbacksMap.clear();
- }
- mVendorUwbAdapter = null;
- }
-
- private synchronized IUwbAdapter getVendorUwbAdapter() throws IllegalStateException {
- if (mVendorUwbAdapter != null) return mVendorUwbAdapter;
- mVendorUwbAdapter = mUwbInjector.getVendorService();
- if (mVendorUwbAdapter == null) {
- throw new IllegalStateException("No vendor service found!");
- }
- Log.i(TAG, "Retrieved vendor service");
- linkToVendorServiceDeath();
- return mVendorUwbAdapter;
- }
-
- UwbServiceImpl(@NonNull Context context, @NonNull UwbInjector uwbInjector) {
- mContext = context;
- mUwbInjector = uwbInjector;
- }
-
- private void enforceUwbPrivilegedPermission() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.UWB_PRIVILEGED,
- "UwbService");
- }
-
- @Override
- public void registerAdapterStateCallbacks(IUwbAdapterStateCallbacks adapterStateCallbacks)
- throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().registerAdapterStateCallbacks(adapterStateCallbacks);
- }
-
- @Override
- public void unregisterAdapterStateCallbacks(IUwbAdapterStateCallbacks adapterStateCallbacks)
- throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().unregisterAdapterStateCallbacks(adapterStateCallbacks);
- }
-
- @Override
- public long getTimestampResolutionNanos() throws RemoteException {
- enforceUwbPrivilegedPermission();
- return getVendorUwbAdapter().getTimestampResolutionNanos();
- }
-
- @Override
- public PersistableBundle getSpecificationInfo() throws RemoteException {
- enforceUwbPrivilegedPermission();
- return getVendorUwbAdapter().getSpecificationInfo();
- }
-
- @Override
- public void openRanging(AttributionSource attributionSource,
- SessionHandle sessionHandle, IUwbRangingCallbacks rangingCallbacks,
- PersistableBundle parameters) throws RemoteException {
- enforceUwbPrivilegedPermission();
- mUwbInjector.enforceUwbRangingPermissionForPreflight(attributionSource);
-
- UwbRangingCallbacksWrapper wrapperCb =
- new UwbRangingCallbacksWrapper(attributionSource, sessionHandle, rangingCallbacks);
- synchronized (mCallbacksMap) {
- mCallbacksMap.put(sessionHandle, wrapperCb);
- }
- getVendorUwbAdapter().openRanging(attributionSource, sessionHandle, wrapperCb, parameters);
- }
-
- @Override
- public void startRanging(SessionHandle sessionHandle, PersistableBundle parameters)
- throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().startRanging(sessionHandle, parameters);
- }
-
- @Override
- public void reconfigureRanging(SessionHandle sessionHandle, PersistableBundle parameters)
- throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().reconfigureRanging(sessionHandle, parameters);
- }
-
- @Override
- public void stopRanging(SessionHandle sessionHandle) throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().stopRanging(sessionHandle);
- }
-
- @Override
- public void closeRanging(SessionHandle sessionHandle) throws RemoteException {
- enforceUwbPrivilegedPermission();
- getVendorUwbAdapter().closeRanging(sessionHandle);
- }
-
- @Override
- public synchronized int getAdapterState() throws RemoteException {
- return getVendorUwbAdapter().getAdapterState();
- }
-
- @Override
- public synchronized void setEnabled(boolean enabled) throws RemoteException {
- getVendorUwbAdapter().setEnabled(enabled);
- }
-}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 965f126000fd..734172fc1549 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -36,6 +36,7 @@ import android.content.PermissionChecker;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
+import android.media.AudioManagerInternal;
import android.media.permission.Identity;
import android.media.permission.PermissionUtil;
import android.os.Binder;
@@ -44,6 +45,7 @@ import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SharedMemory;
@@ -275,6 +277,7 @@ final class HotwordDetectionConnection {
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(null);
mIdentity = null;
+ updateServiceUidForAudioPolicy(Process.INVALID_UID);
}
mCancellationTaskFuture.cancel(/* may interrupt */ true);
if (mAudioFlinger != null) {
@@ -893,6 +896,8 @@ final class HotwordDetectionConnection {
connection.run(service -> service.ping(new IRemoteCallback.Stub() {
@Override
public void sendResult(Bundle bundle) throws RemoteException {
+ // TODO: Exit if the service has been unbound already (though there's a very low
+ // chance this happens).
if (DEBUG) {
Slog.d(TAG, "updating hotword UID " + Binder.getCallingUid());
}
@@ -902,10 +907,21 @@ final class HotwordDetectionConnection {
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(() -> uid);
mIdentity = new HotwordDetectionServiceIdentity(uid, mVoiceInteractionServiceUid);
+ updateServiceUidForAudioPolicy(uid);
}
}));
}
+ private void updateServiceUidForAudioPolicy(int uid) {
+ mScheduledExecutorService.execute(() -> {
+ final AudioManagerInternal audioManager =
+ LocalServices.getService(AudioManagerInternal.class);
+ if (audioManager != null) {
+ audioManager.setHotwordDetectionServiceUid(uid);
+ }
+ });
+ }
+
private static void bestEffortClose(Closeable closeable) {
try {
closeable.close();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
index 68b2e6168b5c..c0c3e6f530db 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
@@ -60,7 +60,7 @@ final class SoundTriggerSessionPermissionsDecorator implements
@Override
public SoundTrigger.ModuleProperties getDspModuleProperties() throws RemoteException {
- // No permission needed.
+ // No permission needed here (the app must have the Assistant Role to retrieve the session).
return mDelegate.getDspModuleProperties();
}
@@ -71,7 +71,9 @@ final class SoundTriggerSessionPermissionsDecorator implements
if (DEBUG) {
Slog.d(TAG, "startRecognition");
}
- enforcePermissions();
+ if (!isHoldingPermissions()) {
+ return SoundTrigger.STATUS_PERMISSION_DENIED;
+ }
return mDelegate.startRecognition(i, s, iHotwordRecognitionStatusCallback,
recognitionConfig, b);
}
@@ -80,25 +82,28 @@ final class SoundTriggerSessionPermissionsDecorator implements
public int stopRecognition(int i,
IHotwordRecognitionStatusCallback iHotwordRecognitionStatusCallback)
throws RemoteException {
- enforcePermissions();
+ // Stopping a model does not require special permissions. Having a handle to the session is
+ // sufficient.
return mDelegate.stopRecognition(i, iHotwordRecognitionStatusCallback);
}
@Override
public int setParameter(int i, int i1, int i2) throws RemoteException {
- enforcePermissions();
+ if (!isHoldingPermissions()) {
+ return SoundTrigger.STATUS_PERMISSION_DENIED;
+ }
return mDelegate.setParameter(i, i1, i2);
}
@Override
public int getParameter(int i, int i1) throws RemoteException {
- enforcePermissions();
+ // No permission needed here (the app must have the Assistant Role to retrieve the session).
return mDelegate.getParameter(i, i1);
}
@Override
public SoundTrigger.ModelParamRange queryParameter(int i, int i1) throws RemoteException {
- enforcePermissions();
+ // No permission needed here (the app must have the Assistant Role to retrieve the session).
return mDelegate.queryParameter(i, i1);
}
@@ -109,9 +114,15 @@ final class SoundTriggerSessionPermissionsDecorator implements
}
// TODO: Share this code with SoundTriggerMiddlewarePermission.
- private void enforcePermissions() {
- enforcePermissionForPreflight(mContext, mOriginatorIdentity, RECORD_AUDIO);
- enforcePermissionForPreflight(mContext, mOriginatorIdentity, CAPTURE_AUDIO_HOTWORD);
+ private boolean isHoldingPermissions() {
+ try {
+ enforcePermissionForPreflight(mContext, mOriginatorIdentity, RECORD_AUDIO);
+ enforcePermissionForPreflight(mContext, mOriginatorIdentity, CAPTURE_AUDIO_HOTWORD);
+ return true;
+ } catch (SecurityException e) {
+ Slog.e(TAG, e.toString());
+ return false;
+ }
}
/**
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index 402b70b63204..93989b6744dc 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -89,6 +89,13 @@ public abstract class CallRedirectionService extends Service {
boolean allowInteractiveResponse);
/**
+ * Telecom calls this method when times out waiting for the {@link CallRedirectionService} to
+ * call {@link #placeCallUnmodified()}, {@link #redirectCall(Uri, PhoneAccountHandle, boolean)},
+ * or {@link #cancelCall()}
+ */
+ public void onRedirectionTimeout() {}
+
+ /**
* The implemented {@link CallRedirectionService} calls this method to response a request
* received via {@link #onPlaceCall(Uri, PhoneAccountHandle, boolean)} to inform Telecom that
* no changes are required to the outgoing call, and that the call should be placed as-is.
@@ -167,6 +174,12 @@ public abstract class CallRedirectionService extends Service {
private static final int MSG_PLACE_CALL = 1;
/**
+ * A handler message to process the attempt to notify the operation of redirection service timed
+ * out from Telecom
+ */
+ private static final int MSG_TIMEOUT = 2;
+
+ /**
* A handler to process the attempt to place call with redirection service from Telecom
*/
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -183,6 +196,9 @@ public abstract class CallRedirectionService extends Service {
args.recycle();
}
break;
+ case MSG_TIMEOUT:
+ onRedirectionTimeout();
+ break;
}
}
};
@@ -209,6 +225,15 @@ public abstract class CallRedirectionService extends Service {
args.arg4 = allowInteractiveResponse;
mHandler.obtainMessage(MSG_PLACE_CALL, args).sendToTarget();
}
+
+ /**
+ * Telecom calls this method to inform the CallRedirectionService of the timeout waiting for
+ * it to complete its operation.
+ */
+ @Override
+ public void notifyTimeout() {
+ mHandler.obtainMessage(MSG_TIMEOUT).sendToTarget();
+ }
}
@Override
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e000265f0a2c..abbce1cd869d 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -2430,7 +2430,8 @@ public class TelecomManager {
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.isIncomingCallPermitted(phoneAccountHandle);
+ return service.isIncomingCallPermitted(phoneAccountHandle,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error isIncomingCallPermitted", e);
}
@@ -2463,7 +2464,8 @@ public class TelecomManager {
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.isOutgoingCallPermitted(phoneAccountHandle);
+ return service.isOutgoingCallPermitted(phoneAccountHandle,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error isOutgoingCallPermitted", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
index c1bc44007b0b..ce1938b81727 100644
--- a/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl
@@ -31,4 +31,6 @@ import com.android.internal.telecom.ICallRedirectionAdapter;
oneway interface ICallRedirectionService {
void placeCall(in ICallRedirectionAdapter adapter, in Uri handle,
in PhoneAccountHandle initialPhoneAccount, boolean allowInteractiveResponse);
+
+ void notifyTimeout();
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6f286d9f3006..a75f79caeee0 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -306,12 +306,14 @@ interface ITelecomService {
/**
* @see TelecomServiceImpl#isIncomingCallPermitted
*/
- boolean isIncomingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
+ boolean isIncomingCallPermitted(in PhoneAccountHandle phoneAccountHandle,
+ String callingPackage);
/**
* @see TelecomServiceImpl#isOutgoingCallPermitted
*/
- boolean isOutgoingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
+ boolean isOutgoingCallPermitted(in PhoneAccountHandle phoneAccountHandle,
+ String callingPackage);
/**
* @see TelecomServiceImpl#waitOnHandler
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 628c48070314..4df8a4bc6413 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -4,13 +4,14 @@ amitmahajan@google.com
breadley@google.com
fionaxu@google.com
jackyu@google.com
-hallliu@google.com
rgreenwalt@google.com
tgunn@google.com
jminjie@google.com
shuoq@google.com
-refuhoo@google.com
nazaninb@google.com
sarahchin@google.com
-dbright@google.com
xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index c18ab33eb2c9..f0048248a5cc 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -193,6 +193,10 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe
return mDelegateBinder;
}
+ public ISipDelegateStateCallback getStateCallbackBinder() {
+ return mStateBinder;
+ }
+
private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
String transactionId = m.getViaBranchParameter();
SipDelegate d = mDelegate;
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 1f74c09af0f6..13ea99735ab4 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -21,6 +21,7 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteException;
import android.telephony.ims.DelegateMessageCallback;
import android.telephony.ims.DelegateRequest;
import android.telephony.ims.DelegateStateCallback;
@@ -33,6 +34,7 @@ import android.telephony.ims.aidl.SipDelegateAidlWrapper;
import android.util.Log;
import java.util.ArrayList;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -49,10 +51,15 @@ import java.util.concurrent.Executor;
public class SipTransportImplBase {
private static final String LOG_TAG = "SipTransportIB";
- private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+ private final IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
- mBinderExecutor.execute(() -> binderDiedInternal());
+ // Clean up all binders in this case.
+ mBinderExecutor.execute(() -> binderDiedInternal(null));
+ }
+ @Override
+ public void binderDied(IBinder who) {
+ mBinderExecutor.execute(() -> binderDiedInternal(who));
}
};
@@ -142,6 +149,7 @@ public class SipTransportImplBase {
ISipDelegateStateCallback cb, ISipDelegateMessageCallback mc) {
SipDelegateAidlWrapper wrapper = new SipDelegateAidlWrapper(mBinderExecutor, cb, mc);
mDelegates.add(wrapper);
+ linkDeathRecipient(wrapper);
createSipDelegate(subId, r, wrapper, wrapper);
}
@@ -155,6 +163,7 @@ public class SipTransportImplBase {
}
if (result != null) {
+ unlinkDeathRecipient(result);
mDelegates.remove(result);
destroySipDelegate(result.getDelegate(), reason);
} else {
@@ -163,12 +172,37 @@ public class SipTransportImplBase {
}
}
- private void binderDiedInternal() {
+ private void linkDeathRecipient(SipDelegateAidlWrapper w) {
+ try {
+ w.getStateCallbackBinder().asBinder().linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "linkDeathRecipient, remote process already died, cleaning up.");
+ mDeathRecipient.binderDied(w.getStateCallbackBinder().asBinder());
+ }
+ }
+
+ private void unlinkDeathRecipient(SipDelegateAidlWrapper w) {
+ try {
+ w.getStateCallbackBinder().asBinder().unlinkToDeath(mDeathRecipient, 0);
+ } catch (NoSuchElementException e) {
+ // Ignore this case.
+ }
+ }
+
+ private void binderDiedInternal(IBinder who) {
for (SipDelegateAidlWrapper w : mDelegates) {
- destroySipDelegate(w.getDelegate(),
- SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ // If the binder itself was not given from the platform, just clean up all binders.
+ if (who == null || w.getStateCallbackBinder().asBinder().equals(who)) {
+ Log.w(LOG_TAG, "Binder death detected for " + w + ", calling destroy and "
+ + "removing.");
+ mDelegates.remove(w);
+ destroySipDelegate(w.getDelegate(),
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ return;
+ }
}
- mDelegates.clear();
+ Log.w(LOG_TAG, "Binder death detected for IBinder " + who + ", but couldn't find matching "
+ + "SipDelegate");
}
/**
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index 4ecca2dc4c39..cf5658644a61 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -31,6 +31,8 @@ public class BootImageProfileTest implements IDeviceTest {
private static final String SYSTEM_SERVER_PROFILE =
"/data/misc/profiles/cur/0/android/primary.prof";
private static final boolean USE_PHENOTYPE = false;
+ private static final String DALVIK_VM_EXTRA_OPTS =
+ "-Xusejit:false -Xint -Xjitsaveprofilinginfo";
@Override
public void setDevice(ITestDevice testDevice) {
@@ -54,10 +56,10 @@ public class BootImageProfileTest implements IDeviceTest {
private String setProperty(String property, String value) throws Exception {
if (USE_PHENOTYPE) {
return mTestDevice.executeShellCommand(
- "device_config put runtime_native_boot " + property + " " + value);
+ String.format("device_config put runtime_native_boot %s '%s'", property, value));
} else {
return mTestDevice.executeShellCommand(
- "setprop dalvik.vm." + property + " " + value);
+ String.format("setprop dalvik.vm.%s '%s'", property, value));
}
}
@@ -69,6 +71,8 @@ public class BootImageProfileTest implements IDeviceTest {
assertTrue("profile boot class path not enabled: " + res, "true".equals(res));
res = getProperty("profilesystemserver");
assertTrue("profile system server not enabled: " + res, "true".equals(res));
+ res = getProperty("extra-opts");
+ assertTrue("extra options not set: " + res, DALVIK_VM_EXTRA_OPTS.equals(res));
}
private boolean forceSaveProfile(String pkg) throws Exception {
@@ -91,16 +95,20 @@ public class BootImageProfileTest implements IDeviceTest {
boolean profileBootClassPath = "true".equals(pbcp);
String pss = getProperty("profilesystemserver");
boolean profileSystemServer = "true".equals(pss);
- if (profileBootClassPath && profileSystemServer) {
+ String extraOpts = getProperty("extra-opts");
+ boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts);
+ if (profileBootClassPath && profileSystemServer && extraOptsOk) {
break;
}
if (i == numIterations) {
assertTrue("profile system server not enabled: " + pss, profileSystemServer);
assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath);
+ assertTrue("extra options not set: " + extraOpts, extraOptsOk);
}
setProperty("profilebootclasspath", "true");
setProperty("profilesystemserver", "true");
+ setProperty("extra-opts", DALVIK_VM_EXTRA_OPTS);
Thread.sleep(1000);
}
@@ -114,12 +122,15 @@ public class BootImageProfileTest implements IDeviceTest {
boolean profileBootClassPath = "true".equals(pbcp);
String pss = getProperty("profilesystemserver");
boolean profileSystemServer = "true".equals(pss);
+ String extraOpts = getProperty("extra-opts");
+ boolean extraOptsOk = DALVIK_VM_EXTRA_OPTS.equals(extraOpts);
if (profileBootClassPath && profileSystemServer) {
break;
}
if (i == numIterations) {
assertTrue("profile system server not enabled: " + pss, profileSystemServer);
assertTrue("profile boot class path not enabled: " + pbcp, profileBootClassPath);
+ assertTrue("extra options not set: " + extraOpts, extraOptsOk);
}
Thread.sleep(1000);
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 70a79d1aeb70..a21eae8cb4ed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.entireScreenCovered
@@ -76,7 +76,7 @@ class ActivitiesTransitionTest(val testSpec: FlickerTestParameter) {
}
}
- @Postsubmit
+ @Presubmit
@Test
fun finishSubActivity() {
testSpec.assertWm {
@@ -88,13 +88,13 @@ class ActivitiesTransitionTest(val testSpec: FlickerTestParameter) {
}
}
- @Postsubmit
+ @Presubmit
@Test
fun entireScreenCovered() {
testSpec.entireScreenCovered(testSpec.config.startRotation)
}
- @Postsubmit
+ @Presubmit
@Test
fun launcherWindowNotVisible() {
testSpec.assertWm {
@@ -102,7 +102,7 @@ class ActivitiesTransitionTest(val testSpec: FlickerTestParameter) {
}
}
- @Postsubmit
+ @Presubmit
@Test
fun launcherLayerNotVisible() {
testSpec.assertLayers { this.isInvisible(LAUNCHER_COMPONENT) }
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 4da3eca25ea0..3eeba7d4f415 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -70,7 +70,45 @@ class AnrTest {
}
@Test
- fun testGestureMonitorAnr() {
+ fun testGestureMonitorAnr_Close() {
+ triggerAnr()
+ clickCloseAppOnAnrDialog()
+ }
+
+ @Test
+ fun testGestureMonitorAnr_Wait() {
+ triggerAnr()
+ clickWaitOnAnrDialog()
+ SystemClock.sleep(500) // Wait at least 500ms after tapping on wait
+ // ANR dialog should reappear after a delay - find the close button on it to verify
+ clickCloseAppOnAnrDialog()
+ }
+
+ private fun clickCloseAppOnAnrDialog() {
+ // Find anr dialog and kill app
+ val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
+ val closeAppButton: UiObject2? =
+ uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000)
+ if (closeAppButton == null) {
+ fail("Could not find anr dialog")
+ return
+ }
+ closeAppButton.click()
+ }
+
+ private fun clickWaitOnAnrDialog() {
+ // Find anr dialog and tap on wait
+ val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
+ val waitButton: UiObject2? =
+ uiDevice.wait(Until.findObject(By.res("android:id/aerr_wait")), 20000)
+ if (waitButton == null) {
+ fail("Could not find anr dialog/wait button")
+ return
+ }
+ waitButton.click()
+ }
+
+ private fun triggerAnr() {
startUnresponsiveActivity()
val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
val obj: UiObject2? = uiDevice.wait(Until.findObject(
@@ -91,20 +129,6 @@ class AnrTest {
// Todo: replace using timeout from android.hardware.input.IInputManager
SystemClock.sleep(5000) // default ANR timeout for gesture monitors
-
- clickCloseAppOnAnrDialog()
- }
-
- private fun clickCloseAppOnAnrDialog() {
- // Find anr dialog and kill app
- val uiDevice: UiDevice = UiDevice.getInstance(mInstrumentation)
- val closeAppButton: UiObject2? =
- uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000)
- if (closeAppButton == null) {
- fail("Could not find anr dialog")
- return
- }
- closeAppButton.click()
}
private fun startUnresponsiveActivity() {
diff --git a/core/tests/uwbtests/Android.bp b/tests/InputMethodStressTest/Android.bp
index 31f446f7a60d..131611d28f0a 100644
--- a/core/tests/uwbtests/Android.bp
+++ b/tests/InputMethodStressTest/Android.bp
@@ -1,4 +1,4 @@
-// Copyright 2020 The Android Open Source Project
+// Copyright (C) 2021 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.
@@ -13,26 +13,23 @@
// limitations under the License.
package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
}
android_test {
- name: "UwbManagerTests",
+ name: "InputMethodStressTest",
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
- "androidx.test.rules",
- "mockito-target-minus-junit4",
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "platform-test-annotations",
+ "truth-prebuilt",
],
- libs: [
- "android.test.runner",
+ test_suites: [
+ "general-tests",
+ "vts",
],
- srcs: ["src/**/*.java"],
- platform_apis: true,
- certificate: "platform",
- test_suites: ["device-tests"],
+ sdk_version: "31",
}
diff --git a/tests/InputMethodStressTest/AndroidManifest.xml b/tests/InputMethodStressTest/AndroidManifest.xml
new file mode 100644
index 000000000000..e5d65188f7ad
--- /dev/null
+++ b/tests/InputMethodStressTest/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.inputmethod.stresstest">
+
+ <application>
+ <activity android:name=".TestActivity"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.inputmethod.stresstest">
+ </instrumentation>
+</manifest>
diff --git a/core/tests/uwbtests/AndroidTest.xml b/tests/InputMethodStressTest/AndroidTest.xml
index ff4b668cc625..b194010a985a 100644
--- a/core/tests/uwbtests/AndroidTest.xml
+++ b/tests/InputMethodStressTest/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2020 The Android Open Source Project
+<!-- Copyright (C) 2021 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.
@@ -13,20 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Config for UWB Manager test cases">
- <option name="test-suite-tag" value="apct"/>
- <option name="test-suite-tag" value="apct-instrumentation"/>
+<configuration description="InputMethod integration/regression test">
+ <option name="test-suite-tag" value="apct" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="UwbManagerTests.apk" />
+ <option name="test-file-name" value="InputMethodStressTest.apk" />
</target_preparer>
- <option name="test-suite-tag" value="apct"/>
- <option name="test-tag" value="UwbManagerTests"/>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.uwb" />
- <option name="hidden-api-checks" value="false"/>
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.inputmethod.stresstest" />
</test>
</configuration>
diff --git a/tests/InputMethodStressTest/OWNERS b/tests/InputMethodStressTest/OWNERS
new file mode 100644
index 000000000000..6bb4b17ed4eb
--- /dev/null
+++ b/tests/InputMethodStressTest/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
new file mode 100644
index 000000000000..5427fd833209
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/ImeOpenCloseStressTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 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.inputmethod.stresstest;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.platform.test.annotations.RootPermissionTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+@RootPermissionTest
+@RunWith(AndroidJUnit4.class)
+public class ImeOpenCloseStressTest {
+
+ private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+ private static final int NUM_TEST_ITERATIONS = 100;
+
+ private Instrumentation mInstrumentation;
+
+ @Test
+ public void test() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ Intent intent = new Intent()
+ .setAction(Intent.ACTION_MAIN)
+ .setClass(mInstrumentation.getContext(), TestActivity.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ TestActivity activity = (TestActivity) mInstrumentation.startActivitySync(intent);
+ eventually(() -> assertThat(callOnMainSync(activity::hasWindowFocus)).isTrue(), TIMEOUT);
+ for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
+ mInstrumentation.runOnMainSync(activity::showIme);
+ eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isTrue(), TIMEOUT);
+ mInstrumentation.runOnMainSync(activity::hideIme);
+ eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isFalse(), TIMEOUT);
+ }
+ }
+
+ private <V> V callOnMainSync(Callable<V> callable) {
+ AtomicReference<V> result = new AtomicReference<>();
+ AtomicReference<Exception> thrownException = new AtomicReference<>();
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ result.set(callable.call());
+ } catch (Exception e) {
+ thrownException.set(e);
+ }
+ });
+ if (thrownException.get() != null) {
+ throw new RuntimeException("Exception thrown from Main thread", thrownException.get());
+ }
+ return result.get();
+ }
+}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
new file mode 100644
index 000000000000..7baf037e4215
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/TestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 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.inputmethod.stresstest;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowInsets;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+public class TestActivity extends Activity {
+
+ private EditText mEditText;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LinearLayout rootView = new LinearLayout(this);
+ rootView.setOrientation(LinearLayout.VERTICAL);
+ mEditText = new EditText(this);
+ rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ setContentView(rootView);
+ }
+
+ public boolean hasWindowFocus() {
+ return mEditText.hasWindowFocus();
+ }
+
+ public boolean isImeShown() {
+ WindowInsets insets = mEditText.getRootWindowInsets();
+ return insets.isVisible(WindowInsets.Type.ime());
+ }
+
+ public void showIme() {
+ mEditText.requestFocus();
+ InputMethodManager imm = getSystemService(InputMethodManager.class);
+ imm.showSoftInput(mEditText, 0);
+ }
+
+ public void hideIme() {
+ InputMethodManager imm = getSystemService(InputMethodManager.class);
+ imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+ }
+}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 05c46ed4b7d9..7a668a5a8944 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -54,7 +54,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -203,194 +202,6 @@ public class RollbackTest {
}
/**
- * Test that multiple available rollbacks are properly persisted.
- */
- @Test
- public void testAvailableRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- Install.single(TestApp.A2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- Uninstall.packages(TestApp.B);
- Install.single(TestApp.B1).commit();
- Install.single(TestApp.B2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // Both test apps should now be available for rollback.
- RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A);
- assertThat(rollbackA).isNotNull();
- assertThat(rollbackA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
-
- RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B);
- assertThat(rollbackB).isNotNull();
- assertThat(rollbackB).packagesContainsExactly(
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // The apps should still be available for rollback.
- rollbackA = waitForAvailableRollback(TestApp.A);
- assertThat(rollbackA).isNotNull();
- assertThat(rollbackA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
-
- rollbackB = waitForAvailableRollback(TestApp.B);
- assertThat(rollbackB).isNotNull();
- assertThat(rollbackB).packagesContainsExactly(
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback of B should not rollback A
- RollbackUtils.rollback(rollbackB.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that available multi-package rollbacks are properly persisted.
- */
- @Test
- public void testAvailableMultiPackageRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.multi(TestApp.A1, TestApp.B1).commit();
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // The app should now be available for rollback.
- RollbackInfo availableA = waitForAvailableRollback(TestApp.A);
- assertThat(availableA).isNotNull();
- assertThat(availableA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- RollbackInfo availableB = waitForAvailableRollback(TestApp.B);
- assertThat(availableB).isNotNull();
- assertThat(availableB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Assert they're both the same rollback
- assertThat(availableA).hasRollbackId(availableB.getRollbackId());
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // The apps should still be available for rollback.
- availableA = waitForAvailableRollback(TestApp.A);
- assertThat(availableA).isNotNull();
- assertThat(availableA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- availableB = waitForAvailableRollback(TestApp.B);
- assertThat(availableB).isNotNull();
- assertThat(availableB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback of B should rollback A as well
- RollbackUtils.rollback(availableB.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
- RollbackInfo committedA = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committedA).isNotNull();
- assertThat(committedA).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- RollbackInfo committedB = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committedB).isNotNull();
- assertThat(committedB).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Assert they're both the same rollback
- assertThat(committedA).hasRollbackId(committedB.getRollbackId());
- assertThat(committedA).hasRollbackId(availableA.getRollbackId());
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that recently committed rollback data is properly persisted.
- */
- @Test
- public void testRecentlyCommittedRollbackPersistence() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- Install.single(TestApp.A2).setEnableRollback().commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- // The app should now be available for rollback.
- RollbackInfo available = waitForAvailableRollback(TestApp.A);
- assertThat(available).isNotNull();
-
- // Roll back the app.
- TestApp cause = new TestApp("Foo", "com.android.tests.rollback.testapp.Foo",
- /*versionCode*/ 42, /*isApex*/ false);
- RollbackUtils.rollback(available.getRollbackId(), cause);
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- // Verify the recent rollback has been recorded.
- RollbackInfo committed = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committed).isNotNull();
- assertThat(committed).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
- assertThat(committed).causePackagesContainsExactly(cause);
-
- // Reload the persisted data.
- rm.reloadPersistedData();
-
- // Verify the recent rollback is still recorded.
- committed = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
- assertThat(committed).isNotNull();
- assertThat(committed).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1));
- assertThat(committed).causePackagesContainsExactly(cause);
- assertThat(committed).hasRollbackId(available.getRollbackId());
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
* Test the scheduling aspect of rollback expiration.
*/
@Test
@@ -739,203 +550,6 @@ public class RollbackTest {
}
}
- /**
- * Test that the MANAGE_ROLLBACKS permission is required to call
- * RollbackManager APIs.
- */
- @Test
- public void testManageRollbacksPermission() throws Exception {
- // We shouldn't be allowed to call any of the RollbackManager APIs
- // without the MANAGE_ROLLBACKS permission.
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- try {
- rm.getAvailableRollbacks();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.getRecentlyCommittedRollbacks();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- // TODO: What if the implementation checks arguments for non-null
- // first? Then this test isn't valid.
- rm.commitRollback(0, Collections.emptyList(), null);
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.reloadPersistedData();
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
-
- try {
- rm.expireRollbackForPackage(TestApp.A);
- fail("expected SecurityException");
- } catch (SecurityException e) {
- // Expected.
- }
- }
-
- /**
- * Test that you cannot enable rollback for a package without the
- * MANAGE_ROLLBACKS permission.
- */
- @Test
- public void testEnableRollbackPermission() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES);
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- Install.single(TestApp.A2).setEnableRollback().commit();
-
- // We expect v2 of the app was installed, but rollback has not
- // been enabled.
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
- assertThat(
- getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test that you cannot enable rollback for a non-module package when
- * holding the MANAGE_ROLLBACKS permission.
- */
- @Test
- public void testNonModuleEnableRollback() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.MANAGE_ROLLBACKS);
-
- Uninstall.packages(TestApp.A);
- Install.single(TestApp.A1).commit();
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
-
- Install.single(TestApp.A2).setEnableRollback().commit();
-
- // We expect v2 of the app was installed, but rollback has not
- // been enabled because the test app is not a module.
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-
- RollbackManager rm = RollbackUtils.getRollbackManager();
- assertThat(
- getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test rollback of multi-package installs is implemented.
- */
- @Test
- public void testMultiPackage() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- // Prep installation of the test apps.
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.multi(TestApp.A1, TestApp.B1).commit();
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- // TestApp.A should now be available for rollback.
- RollbackInfo rollback = waitForAvailableRollback(TestApp.A);
- assertThat(rollback).isNotNull();
- assertThat(rollback).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- // Rollback the app. It should cause both test apps to be rolled
- // back.
- RollbackUtils.rollback(rollback.getRollbackId());
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
-
- // We should see recent rollbacks listed for both A and B.
- Thread.sleep(1000);
- RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.A);
-
- RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TestApp.B);
- assertThat(rollback).packagesContainsExactly(
- Rollback.from(TestApp.A2).to(TestApp.A1),
- Rollback.from(TestApp.B2).to(TestApp.B1));
-
- assertThat(rollbackA).hasRollbackId(rollbackB.getRollbackId());
-
- processUserData(TestApp.A);
- processUserData(TestApp.B);
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
- /**
- * Test failure to enable rollback for multi-package installs.
- * If any one of the packages fail to enable rollback, we shouldn't enable
- * rollback for any package.
- */
- @Test
- public void testMultiPackageEnableFail() throws Exception {
- try {
- InstallUtils.adoptShellPermissionIdentity(
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.DELETE_PACKAGES,
- Manifest.permission.TEST_MANAGE_ROLLBACKS);
- RollbackManager rm = RollbackUtils.getRollbackManager();
-
- Uninstall.packages(TestApp.A, TestApp.B);
- Install.single(TestApp.A1).commit();
- // We should fail to enable rollback here because TestApp B is not
- // already installed.
- Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
-
- assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
- assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
-
- assertThat(getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TestApp.A)).isNull();
- assertThat(getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TestApp.B)).isNull();
- } finally {
- InstallUtils.dropShellPermissionIdentity();
- }
- }
-
@Test
@Ignore("b/120200473")
/**
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 642b19e6d961..e874782c7183 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -301,9 +301,9 @@ public class StagedRollbackTest {
InstallUtils.processUserData(TestApp.C);
Install a2 = Install.single(TestApp.A2).setStaged()
- .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+ .setEnableRollback(PackageManager.ROLLBACK_DATA_POLICY_WIPE);
Install b2 = Install.single(TestApp.B2).setStaged()
- .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+ .setEnableRollback(PackageManager.ROLLBACK_DATA_POLICY_RESTORE);
// The rollback data policy of C2 is specified in the manifest
Install c2 = Install.single(TestApp.C2).setStaged().setEnableRollback();
Install.multi(a2, b2, c2).setEnableRollback().setStaged().commit();
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
index af9786b92f40..deff42a27f47 100644
--- a/tests/utils/testutils/Android.bp
+++ b/tests/utils/testutils/Android.bp
@@ -38,6 +38,6 @@ java_library {
"android.test.runner",
"android.test.base",
"android.test.mock",
- "mockito-target-minus-junit4",
+ "mockito-target-extended-minus-junit4",
],
}
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index ea886dbc2218..0bbde62728cf 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -27,7 +27,7 @@ namespace aapt {
static ApiVersion sDevelopmentSdkLevel = 10000;
static const auto sDevelopmentSdkCodeNames =
- std::unordered_set<StringPiece>({"Q", "R", "S", "Tiramisu"});
+ std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu"});
static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x021c, 1},
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
index 5736a8082ca3..900c2145975a 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
@@ -30,7 +30,8 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() {
CallingIdentityTokenDetector.ISSUE_NESTED_CLEAR_IDENTITY_CALLS,
CallingIdentityTokenDetector.ISSUE_RESTORE_IDENTITY_CALL_NOT_IN_FINALLY_BLOCK,
CallingIdentityTokenDetector.ISSUE_USE_OF_CALLER_AWARE_METHODS_WITH_CLEARED_IDENTITY,
- CallingIdentityTokenDetector.ISSUE_CLEAR_IDENTITY_CALL_NOT_FOLLOWED_BY_TRY_FINALLY
+ CallingIdentityTokenDetector.ISSUE_CLEAR_IDENTITY_CALL_NOT_FOLLOWED_BY_TRY_FINALLY,
+ CallingSettingsNonUserGetterMethodsDetector.ISSUE_NON_USER_GETTER_CALLED
)
override val api: Int
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
new file mode 100644
index 000000000000..641f337ab987
--- /dev/null
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsDetector.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 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.google.android.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+
+/**
+ * Lint Detector that finds issues with improper usages of the non-user getter methods of Settings
+ */
+@Suppress("UnstableApiUsage")
+class CallingSettingsNonUserGetterMethodsDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableMethodNames(): List<String> = listOf(
+ "getString",
+ "getInt",
+ "getLong",
+ "getFloat"
+ )
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ val evaluator = context.evaluator
+ if (evaluator.isMemberInClass(method, "android.provider.Settings.Secure") ||
+ evaluator.isMemberInClass(method, "android.provider.Settings.System")
+ ) {
+ val message = getIncidentMessageNonUserGetterMethods(getMethodSignature(method))
+ context.report(ISSUE_NON_USER_GETTER_CALLED, node, context.getLocation(node), message)
+ }
+ }
+
+ private fun getMethodSignature(method: PsiMethod) =
+ method.containingClass
+ ?.qualifiedName
+ ?.let { "$it#${method.name}" }
+ ?: method.name
+
+ companion object {
+ @JvmField
+ val ISSUE_NON_USER_GETTER_CALLED: Issue = Issue.create(
+ id = "NonUserGetterCalled",
+ briefDescription = "Non-ForUser Getter Method called to Settings",
+ explanation = """
+ System process should not call the non-ForUser getter methods of \
+ `Settings.Secure` or `Settings.System`. For example, instead of \
+ `Settings.Secure.getInt()`, use `Settings.Secure.getIntForUser()` instead. \
+ This will make sure that the correct Settings value is retrieved.
+ """,
+ category = Category.CORRECTNESS,
+ priority = 6,
+ severity = Severity.WARNING,
+ implementation = Implementation(
+ CallingSettingsNonUserGetterMethodsDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ )
+ )
+
+ fun getIncidentMessageNonUserGetterMethods(methodSignature: String) =
+ "`$methodSignature()` called from system process. " +
+ "Please call `${methodSignature}ForUser()` instead. "
+ }
+}
diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
new file mode 100644
index 000000000000..1034029f6e9d
--- /dev/null
+++ b/tools/lint/checks/src/test/java/com/google/android/lint/CallingSettingsNonUserGetterMethodsIssueDetectorTest.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2021 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.google.android.lint
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+
+@Suppress("UnstableApiUsage")
+class CallingSettingsNonUserGetterMethodsIssueDetectorTest : LintDetectorTest() {
+ override fun getDetector(): Detector = CallingSettingsNonUserGetterMethodsDetector()
+
+ override fun getIssues(): List<Issue> = listOf(
+ CallingSettingsNonUserGetterMethodsDetector.ISSUE_NON_USER_GETTER_CALLED
+ )
+
+ override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+ fun testDoesNotDetectIssues() {
+ lint().files(
+ java(
+ """
+ package test.pkg;
+ import android.provider.Settings.Secure;
+ public class TestClass1 {
+ private void testMethod(Context context) {
+ final int value = Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.KEY1, 0, 0);
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expectClean()
+ }
+
+ fun testDetectsNonUserGetterCalledFromSecure() {
+ lint().files(
+ java(
+ """
+ package test.pkg;
+ import android.provider.Settings.Secure;
+ public class TestClass1 {
+ private void testMethod(Context context) {
+ final int value = Secure.getInt(context.getContentResolver(),
+ Settings.Secure.KEY1);
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass1.java:5: Warning: \
+ android.provider.Settings.Secure#getInt() called from system process. \
+ Please call android.provider.Settings.Secure#getIntForUser() instead. \
+ [NonUserGetterCalled]
+ final int value = Secure.getInt(context.getContentResolver(),
+ ^
+ 0 errors, 1 warnings
+ """.addLineContinuation()
+ )
+ }
+ fun testDetectsNonUserGetterCalledFromSystem() {
+ lint().files(
+ java(
+ """
+ package test.pkg;
+ import android.provider.Settings.System;
+ public class TestClass1 {
+ private void testMethod(Context context) {
+ final float value = System.getFloat(context.getContentResolver(),
+ Settings.System.KEY1);
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass1.java:5: Warning: \
+ android.provider.Settings.System#getFloat() called from system process. \
+ Please call android.provider.Settings.System#getFloatForUser() instead. \
+ [NonUserGetterCalled]
+ final float value = System.getFloat(context.getContentResolver(),
+ ^
+ 0 errors, 1 warnings
+ """.addLineContinuation()
+ )
+ }
+
+ fun testDetectsNonUserGetterCalledFromSettings() {
+ lint().files(
+ java(
+ """
+ package test.pkg;
+ import android.provider.Settings;
+ public class TestClass1 {
+ private void testMethod(Context context) {
+ float value = Settings.System.getFloat(context.getContentResolver(),
+ Settings.System.KEY1);
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass1.java:5: Warning: \
+ android.provider.Settings.System#getFloat() called from system process. \
+ Please call android.provider.Settings.System#getFloatForUser() instead. \
+ [NonUserGetterCalled]
+ float value = Settings.System.getFloat(context.getContentResolver(),
+ ^
+ 0 errors, 1 warnings
+ """.addLineContinuation()
+ )
+ }
+
+ fun testDetectsNonUserGettersCalledFromSystemAndSecure() {
+ lint().files(
+ java(
+ """
+ package test.pkg;
+ import android.provider.Settings.Secure;
+ import android.provider.Settings.System;
+ public class TestClass1 {
+ private void testMethod(Context context) {
+ final long value1 = Secure.getLong(context.getContentResolver(),
+ Settings.Secure.KEY1, 0);
+ final String value2 = System.getString(context.getContentResolver(),
+ Settings.System.KEY2);
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/test/pkg/TestClass1.java:6: Warning: \
+ android.provider.Settings.Secure#getLong() called from system process. \
+ Please call android.provider.Settings.Secure#getLongForUser() instead. \
+ [NonUserGetterCalled]
+ final long value1 = Secure.getLong(context.getContentResolver(),
+ ^
+ src/test/pkg/TestClass1.java:8: Warning: \
+ android.provider.Settings.System#getString() called from system process. \
+ Please call android.provider.Settings.System#getStringForUser() instead. \
+ [NonUserGetterCalled]
+ final String value2 = System.getString(context.getContentResolver(),
+ ^
+ 0 errors, 2 warnings
+ """.addLineContinuation()
+ )
+ }
+
+ private val SettingsStub: TestFile = java(
+ """
+ package android.provider;
+ public class Settings {
+ public class Secure {
+ float getFloat(ContentResolver cr, String key) {
+ return 0.0f;
+ }
+ long getLong(ContentResolver cr, String key) {
+ return 0l;
+ }
+ int getInt(ContentResolver cr, String key) {
+ return 0;
+ }
+ }
+ public class System {
+ float getFloat(ContentResolver cr, String key) {
+ return 0.0f;
+ }
+ long getLong(ContentResolver cr, String key) {
+ return 0l;
+ }
+ String getString(ContentResolver cr, String key) {
+ return null;
+ }
+ }
+ }
+ """
+ ).indented()
+
+ private val stubs = arrayOf(SettingsStub)
+
+ // Substitutes "backslash + new line" with an empty string to imitate line continuation
+ private fun String.addLineContinuation(): String = this.trimIndent().replace("\\\n", "")
+}